From 832b180a6f94c963d2441d364700de5ba7abe9a6 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Wed, 3 Jun 2026 16:21:34 +0000 Subject: [PATCH 1/7] Optical Controller component: - Fix logging framework - Minor code fixes - Factorized RSA:init_graph() method --- src/opticalcontroller/OpticalController.py | 33 +++++--- src/opticalcontroller/RSA.py | 99 +++++++++++++--------- src/opticalcontroller/dijkstra.py | 15 +++- 3 files changed, 93 insertions(+), 54 deletions(-) diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py index 51a560f31..6890aacaa 100644 --- a/src/opticalcontroller/OpticalController.py +++ b/src/opticalcontroller/OpticalController.py @@ -30,6 +30,15 @@ global links_dict rsa = None +logging.basicConfig(level=logging.DEBUG) + +LOGGER = logging.getLogger(__name__) +LOGGER.setLevel(logging.DEBUG) + +def print(*args) -> None: + LOGGER.info(' '.join([str(a) for a in args])) + + app = Flask(__name__) api = Api(app, version='1.0', title='Optical controller API', description='Rest API to configure OC Optical devices in TFS') @@ -329,7 +338,8 @@ class GetFlows(Resource): print(rsa.db_flows) return rsa.db_flows, 200 except: - return "Error", 404 + LOGGER.exception('Error while getting lightpaths') + return 'Error', 404 @optical.route('/GetOpticalBands') @optical.response(200, 'Success') @@ -342,7 +352,8 @@ class GetBands(Resource): print(rsa.optical_bands) return rsa.optical_bands, 200 except: - return "Error", 404 + LOGGER.exception('Error while getting optical bands') + return 'Error', 404 @optical.route('/GetOpticalBand/') @@ -397,7 +408,8 @@ class GetFlows(Resource): print(links) return links, 200 except: - return "Error", 404 + LOGGER.exception('Error while getting links') + return 'Error', 404 @optical.route('/GetTopology//',methods=['GET']) @@ -481,12 +493,11 @@ class GetTopology(Resource): if debug: print(f'rsa.init_link_slots2() {rsa}') print(rsa.init_link_slots2()) - - - return "ok" ,200 - except Exception as e: - print(f"err {e}") - return "Error", 400 - -if __name__ == '__main__': + return 'OK', 200 + except Exception: + LOGGER.exception('Error while processing topology data') + #print(f'err {e}') + return 'Error', 400 + +if __name__ == '__main__': app.run(host='0.0.0.0', port=10060, debug=True) diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py index 106c73696..9254707ea 100644 --- a/src/opticalcontroller/RSA.py +++ b/src/opticalcontroller/RSA.py @@ -13,12 +13,12 @@ # limitations under the License. import logging +from typing import Dict, Tuple from opticalcontroller.dijkstra import * from opticalcontroller.tools import * from opticalcontroller.variables import * -logging.basicConfig(level=logging.DEBUG) LOGGER = logging.getLogger(__name__) LOGGER.setLevel(logging.DEBUG) @@ -31,11 +31,13 @@ class RSA(): self.nodes_dict = nodes self.links_dict = links self.g = None + self.node_key__to__node_name : Dict[str, Dict] = dict() + self.link_key__to__src_dst_node_names : Dict[str, Tuple[str, str]] = dict() self.flow_id = 0 self.opt_band_id = 0 self.db_flows = {} - self.initGraph2() + self.init_graph() self.c_slot_number = 0 self.l_slot_number = 0 self.s_slot_number = 0 @@ -97,45 +99,52 @@ class RSA(): break return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number) - def initGraph(self): + def init_graph(self): + self.node_key__to__node_name.clear() + self.link_key__to__src_dst_node_names.clear() self.g = Graph() - for n in self.nodes_dict: - self.g.add_vertex(n) - for l in self.links_dict["optical_links"]: - #if debug: - # print(l) - [s, d] = l["optical_link"]["name"].split('-') - ps = l["optical_link"]["details"]["source"] - pd = l["optical_link"]["details"]["target"] - self.g.add_edge(s, d, ps, pd, 1) - print("INFO: Graph initiated.") - if debug: - self.g.printGraph() + for node_name, node_data in self.nodes_dict.items(): + MSG = '[RSA:init_graph] processing node: name={:s}, data={:s}' + LOGGER.debug(MSG.format(str(node_name), str(node_data))) - def initGraph2(self): - - self.g = Graph() - - for n in self.nodes_dict: - self.g.add_vertex(n) - for l in self.links_dict["optical_links"]: - #if debug: - # print(l) - [s, d] = l["name"].split('-') - ps = l["optical_details"]["src_port"] - pd = l["optical_details"]["dst_port"] - self.g.add_edge(s, d, ps, pd, 1) + node_id = node_data['id'] + self.node_key__to__node_name[node_id] = node_name + self.node_key__to__node_name[node_name] = node_name + self.g.add_vertex(node_name) - print("INFO: Graph initiated.2") - if debug: - self.g.printGraph() + for link in self.links_dict['optical_links']: + MSG = '[RSA:init_graph] processing link: {:s}' + LOGGER.debug(MSG.format(str(link))) + + src_ep_id = link['link_endpoint_ids'][ 0] + src_node_uuid = src_ep_id['device_id']['device_uuid']['uuid'] + src_node_name = self.node_key__to__node_name[src_node_uuid] + + dst_ep_id = link['link_endpoint_ids'][-1] + dst_node_uuid = dst_ep_id['device_id']['device_uuid']['uuid'] + dst_node_name = self.node_key__to__node_name[dst_node_uuid] + + src_port = link['optical_details']['src_port'] + dst_port = link['optical_details']['dst_port'] + + link_name = '{:s}-{:s}'.format(src_node_name, dst_node_name) + self.link_key__to__src_dst_node_names[link_name] = (src_node_name, dst_node_name) + + self.g.add_edge(src_node_name, dst_node_name, src_port, dst_port, 1) + + LOGGER.info('[RSA:init_graph] Graph initiated') + self.g.printGraph() def compute_path(self, src, dst): path = shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) - print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance())) - if debug: - print(f"compute_path shortest_path {path}") + + MSG = '[RSA:compute_path] Path from {:s} to {:s} with distance {:f}' + LOGGER.info(MSG.format(src, dst, float(self.g.get_vertex(dst).get_distance()))) + + MSG = '[RSA:compute_path] Path: {:s}' + LOGGER.debug(MSG.format(str(path))) + links = [] for i in range(0, len(path) - 1): s = path[i] @@ -155,10 +164,18 @@ class RSA(): def compute_disjoint_path(self, src, dst, path1=None): if path1 is None: path1 = shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst)) - path = disjoint_path(self.g, src, dst, path1, False) - print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance())) - if debug: - print(path) + + MSG = '[RSA:compute_disjoint_path] Path1: {:s}' + LOGGER.info(MSG.format(str(path1))) + + path = disjoint_path(self.g, src, dst, path1, False) + + MSG = '[RSA:compute_disjoint_path] Path from {:s} to {:s} with distance {:f}' + LOGGER.info(MSG.format(src, dst, float(self.g.get_vertex(dst).get_distance()))) + + MSG = '[RSA:compute_disjoint_path] Path: {:s}' + LOGGER.debug(MSG.format(str(path))) + links = [] for i in range(0, len(path) - 1): s = path[i] @@ -195,13 +212,13 @@ class RSA(): s_slots = {} add = "" drop = "" - src_1, dst_1 = links[0].split('-') - src_2, dst_2 = links[-1].split('-') + src_1, dst_1 = self.link_key__to__src_dst_node_names[links[ 0]] + src_2, dst_2 = self.link_key__to__src_dst_node_names[links[-1]] if self.nodes_dict[src_1]["type"] == "OC-TP": add = links[0] if self.nodes_dict[dst_2]["type"] == "OC-TP": drop = links[-1] - found = 0 + for l in links: c_slots[l] = [] l_slots[l] = [] diff --git a/src/opticalcontroller/dijkstra.py b/src/opticalcontroller/dijkstra.py index f113c7425..54b29b385 100644 --- a/src/opticalcontroller/dijkstra.py +++ b/src/opticalcontroller/dijkstra.py @@ -16,7 +16,9 @@ # https://networkx.org/documentation/stable/index.html # https://networkx.org/documentation/stable/reference/algorithms/shortest_paths.html -import sys +import logging + +LOGGER = logging.getLogger(__name__) class Vertex: def __init__(self, node): @@ -99,11 +101,20 @@ class Graph: self.get_vertex(n).reset_vertex() def printGraph(self): + MSG = ', '.join([ + 'src_node={:s}', 'dst_node={:s}', + 'src_port={:s}', 'dst_port={:s}', + 'weight_src_to_dst={:d}', 'weight_dst_to_src={:d}' + ]) + for v in self: for w in v.get_connections(): vid = v.get_id() wid = w.get_id() - print ('( %s , %s, %s, %s, %s, %s)' % ( vid, wid, v.get_port(w), w.get_port(v), v.get_weight(w), w.get_weight(v))) + LOGGER.debug(MSG.format( + vid, wid, v.get_port(w), w.get_port(v), + v.get_weight(w), w.get_weight(v) + )) def add_vertex(self, node): self.num_vertices = self.num_vertices + 1 -- GitLab From 3c100ed449d569b3182d4a402f75bb2a69b2b361 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Thu, 4 Jun 2026 11:41:23 +0000 Subject: [PATCH 2/7] Optical Controller component: - Fixed computation of methods reverse_link(), reverse_links(), get_links_from_node(), and get_links_to_node() - Forced NETWORK (remote network) device type to operate as an emulated transponder for multi-domain path computations - Multiple log enhancements - Added typehints --- src/opticalcontroller/OpticalController.py | 7 ++-- src/opticalcontroller/RSA.py | 47 ++++++++++++---------- src/opticalcontroller/tools.py | 33 +++++++-------- 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py index 6890aacaa..f2ba0f6c6 100644 --- a/src/opticalcontroller/OpticalController.py +++ b/src/opticalcontroller/OpticalController.py @@ -434,13 +434,14 @@ class GetTopology(Resource): topo , nodes = readTopologyDataFromContext(topog_id) OPTICAL_ROADM_TYPES = { - DeviceTypeEnum.OPTICAL_ROADM.value, DeviceTypeEnum.EMULATED_OPTICAL_ROADM.value + DeviceTypeEnum.OPTICAL_ROADM.value, DeviceTypeEnum.EMULATED_OPTICAL_ROADM.value, } OPTICAL_OPENROADM_TYPES = { - DeviceTypeEnum.OPEN_ROADM.value, DeviceTypeEnum.EMULATED_OPEN_ROADM.value + DeviceTypeEnum.OPEN_ROADM.value, DeviceTypeEnum.EMULATED_OPEN_ROADM.value, } OPTICAL_TRANSPONDER_TYPES = { - DeviceTypeEnum.OPTICAL_TRANSPONDER.value, DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value + DeviceTypeEnum.OPTICAL_TRANSPONDER.value, DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value, + DeviceTypeEnum.NETWORK.value, } added_device_uuids = set() for device in nodes: diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py index 9254707ea..88df5c2c3 100644 --- a/src/opticalcontroller/RSA.py +++ b/src/opticalcontroller/RSA.py @@ -428,9 +428,10 @@ class RSA(): #self.restore_optical_band_2(o_b_id, slots, band,links) if bidir: for l in links: - r_l = reverse_link(l) - if debug: - print(f"reverse_link {r_l}") + r_l = reverse_link(l, self.link_key__to__src_dst_node_names) + MSG = '[RSA:del_flow] reverse link: {:s}' + LOGGER.debug(MSG.format(str(r_l))) + rlink = self.get_link_by_name(r_l) fib = rlink["optical_details"] #fib = self.get_link_by_name(r_l)["optical_details"] @@ -513,7 +514,7 @@ class RSA(): #self.restore_optical_band_2(o_b_id, slots, band,links) if bidir: for l in links: - r_l = reverse_link(l) + r_l = reverse_link(l, self.link_key__to__src_dst_node_names) if debug: print(r_l) rlink = self.get_link_by_name(r_l) @@ -599,9 +600,11 @@ class RSA(): return None def get_fibers_backward(self, links, slots, band): + LOGGER.info('[RSA:get_fibers_backward] Starting path backward computation') + fiber_list = {} - #r_drop = reverse_link(links[0]) - #r_add = reverse_link(links[-1]) + #r_drop = reverse_link(links[0], self.link_key__to__src_dst_node_names) + #r_add = reverse_link(links[-1], self.link_key__to__src_dst_node_names) for l in links: fib = self.get_link_by_name(l)["optical_details"] ''' @@ -613,13 +616,14 @@ class RSA(): s_port = fib["src_port"] d_port = fib["dst_port"] - if debug: - print(l, s_port, d_port) + MSG = '[RSA:get_fibers_backward] processing link: {:s}, src_port: {:s}, dst_port: {:s}' + LOGGER.debug(MSG.format(str(l), str(s_port), str(d_port))) - r_l = reverse_link(l) + r_l = reverse_link(l, self.link_key__to__src_dst_node_names) r_link = self.get_link_by_name(r_l) - #if debug: - # print(r_l) + + MSG = '[RSA:get_fibers_backward] reverse link: {:s}' + LOGGER.debug(MSG.format(str(r_l))) #for f in r_link["fibers"].keys(): r_fib = r_link["optical_details"] @@ -627,7 +631,8 @@ class RSA(): if list_in_list(slots, str_list_to_int(r_fib[band].keys())): #fiber_list[r_l] = r_fib["ID"] self.update_link(r_fib, slots, band) - print("INFO: Path backward computation completed") + + LOGGER.info('[RSA:get_fibers_backward] Path backward computation completed') return fiber_list #function invoked for lightpaths and OB @@ -666,7 +671,7 @@ class RSA(): fibx = self.get_fiber_details(lx, f) ''' - src, dst = llx.split("-") + src, dst = self.link_key__to__src_dst_node_names[llx] #outport = self.links_dict[lx]['fibers'][f]["src_port"] lx = self.get_link_by_name(llx)["optical_details"] outport = lx["src_port"] @@ -735,7 +740,7 @@ class RSA(): t_flows = {} #flows_add_side - src, dst = add.split("-") + src, dst = self.link_key__to__src_dst_node_names[add] lx = self.get_link_by_name(add)["optical_details"] #outport = self.links_dict[add]['fibers'][f]["src_port"] outport = lx["src_port"] @@ -772,7 +777,7 @@ class RSA(): #flows_drop_side # R2 rules ly = self.get_link_by_name(drop)["optical_details"] - src, dst = drop.split("-") + src, dst = self.link_key__to__src_dst_node_names[drop] #outport = self.links_dict[drop]['fibers'][f]["src_port"] outport = ly["src_port"] @@ -824,7 +829,7 @@ class RSA(): ''' #flows_add_side - src, dst = add.split("-") + src, dst = self.link_key__to__src_dst_node_names[add] lx = self.get_link_by_name(add)["optical_details"] #outport = self.links_dict[add]['fibers'][f]["src_port"] outport = lx["src_port"] @@ -1275,8 +1280,8 @@ class RSA(): temp_links2.append(list(dst_links.keys())[0]) if len(temp_links2) == 2: - [t_src, roadm_src] = temp_links2[0].split('-') - [roadm_dst, t_dst] = temp_links2[1].split('-') + t_src, roadm_src = self.link_key__to__src_dst_node_names[temp_links2[0]] + roadm_dst, t_dst = self.link_key__to__src_dst_node_names[temp_links2[1]] temp_path.append(t_src) temp_path.append(roadm_src) temp_path.append(roadm_dst) @@ -1591,7 +1596,7 @@ class RSA(): #self.restore_optical_band_2(o_b_id, slots, band,links) if bidir: for l in links: - r_l = reverse_link(l) + r_l = reverse_link(l, self.link_key__to__src_dst_node_names) if debug: print(r_l) rlink = self.get_link_by_name(r_l) @@ -1633,8 +1638,8 @@ class RSA(): r1 = "" r2 = "" if len(links) == 2: - [t1, r1] = links[0].split("-") - [r2, t2] = links[1].split("-") + t1, r1 = self.link_key__to__src_dst_node_names[links[0]] + r2, t2 = self.link_key__to__src_dst_node_names[links[1]] else: return 0, 0 existing_ob = self.get_optical_bands(r1, r2) diff --git a/src/opticalcontroller/tools.py b/src/opticalcontroller/tools.py index 78a47da8e..c15fcafa0 100644 --- a/src/opticalcontroller/tools.py +++ b/src/opticalcontroller/tools.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import numpy as np +import json, logging, numpy as np +from typing import Dict, List, Tuple from opticalcontroller.variables import * -import json , logging from context.client.ContextClient import ContextClient from common.proto.context_pb2 import TopologyId , LinkId , OpticalLink , OpticalLinkDetails from common.tools.object_factory.OpticalLink import correct_slot @@ -131,10 +131,10 @@ def list_in_list(a, b): return False -def reverse_link(link): - s, d = link.split('-') - r_link = "{}-{}".format(d, s) - return r_link +def reverse_link(link, link_key__to__src_dst_node_names : Dict[str, Tuple[str, str]]) -> str: + src_name, dst_name = link_key__to__src_dst_node_names[link] + rev_link_name = '{:s}-{:s}'.format(dst_name, src_name) + return rev_link_name def get_slot_frequency(b, n): @@ -225,28 +225,29 @@ def readTopologyDataFromContext(topology_id:TopologyId): return topo , nodes -def reverse_links(links): - temp_links = links.copy() - temp_links.reverse() - result = [] - for link in temp_links: - [a, b] = link.split("-") - result.append("{}-{}".format(b, a)) - return result +def reverse_links( + links : List[str], link_key__to__src_dst_node_names : Dict[str, Tuple[str, str]] +) -> List[str]: + return [ + reverse_link(link, link_key__to__src_dst_node_names) + for link in reversed(links) + ] def get_links_from_node(topology, node): + link_prefix = "{}-".format(node) result = {} for link in topology["optical_links"]: - if "{}-".format(node) in link["name"]: + if str(link["name"]).startswith(link_prefix): result[link["name"]] = link return result def get_links_to_node(topology, node): + link_suffix = "-{}".format(node) result = {} for link in topology["optical_links"]: - if "-{}".format(node) in link["name"]: + if str(link["name"]).endswith(link_suffix): result[link["name"]] = link return result -- GitLab From 06505bccf2e6ae025cc70f0fee2ed150c777fcea Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Thu, 4 Jun 2026 17:20:39 +0000 Subject: [PATCH 3/7] Optical Controller component: - Fix logging framework - Minor code fixes - Fixed composition of link_names --- src/opticalcontroller/OpticalController.py | 15 ++- src/opticalcontroller/RSA.py | 32 ++++-- .../service/service_handlers/oc/OCTools.py | 104 ++++++++++-------- 3 files changed, 90 insertions(+), 61 deletions(-) diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py index f2ba0f6c6..c2a4ff338 100644 --- a/src/opticalcontroller/OpticalController.py +++ b/src/opticalcontroller/OpticalController.py @@ -427,20 +427,23 @@ class GetTopology(Resource): topog_id = TopologyId() topog_id.topology_uuid.uuid=topology_id topog_id.context_id.context_uuid.uuid=context_id - - try: + + try: links_dict={"optical_links":[]} node_dict = {} topo , nodes = readTopologyDataFromContext(topog_id) OPTICAL_ROADM_TYPES = { - DeviceTypeEnum.OPTICAL_ROADM.value, DeviceTypeEnum.EMULATED_OPTICAL_ROADM.value, + DeviceTypeEnum.OPTICAL_ROADM.value, + DeviceTypeEnum.EMULATED_OPTICAL_ROADM.value, } OPTICAL_OPENROADM_TYPES = { - DeviceTypeEnum.OPEN_ROADM.value, DeviceTypeEnum.EMULATED_OPEN_ROADM.value, + DeviceTypeEnum.OPEN_ROADM.value, + DeviceTypeEnum.EMULATED_OPEN_ROADM.value, } OPTICAL_TRANSPONDER_TYPES = { - DeviceTypeEnum.OPTICAL_TRANSPONDER.value, DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value, + DeviceTypeEnum.OPTICAL_TRANSPONDER.value, + DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value, DeviceTypeEnum.NETWORK.value, } added_device_uuids = set() @@ -466,7 +469,7 @@ class GetTopology(Resource): #i+=1 #print(f"refresh_optical controller optical_links_dict= {links_dict}") #print(f"refresh_optical controller node_dict {node_dict}") - + for link in topo: endpoint_id_a = link.link_endpoint_ids[ 0] endpoint_id_z = link.link_endpoint_ids[-1] diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py index 88df5c2c3..8842ee826 100644 --- a/src/opticalcontroller/RSA.py +++ b/src/opticalcontroller/RSA.py @@ -42,8 +42,7 @@ class RSA(): self.l_slot_number = 0 self.s_slot_number = 0 self.optical_bands = {} - - + def init_link_slots(self, testing): if full_links: for l in self.links_dict["optical_links"]: @@ -130,6 +129,7 @@ class RSA(): link_name = '{:s}-{:s}'.format(src_node_name, dst_node_name) self.link_key__to__src_dst_node_names[link_name] = (src_node_name, dst_node_name) + link['name'] = link_name self.g.add_edge(src_node_name, dst_node_name, src_port, dst_port, 1) @@ -335,7 +335,7 @@ class RSA(): print(f"fib updated {fib}") #print(fib) - def update_link_2(self, fib, slots, band,link): + def update_link_2(self, fib, slots, band, link): #print(fib) for i in slots: fib[band][str(i)] = 0 @@ -542,6 +542,10 @@ class RSA(): def get_fibers_forward(self, links, slots, band): + LOGGER.info('[RSA:get_fibers_forward] Starting path forward computation') + MSG = '[RSA:get_fibers_forward] Input parameters: links={:s}, slots={:s}, band={:s}' + LOGGER.info(MSG.format(str(links), str(slots), str(band))) + fiber_list = {} add = links[0] drop = links[-1] @@ -578,16 +582,23 @@ class RSA(): #self.update_link(fib, slots, band) self.update_link_2(fib,slots,band,link) break - print("INFO: Path forward computation completed") + + MSG = '[RSA:get_fibers_forward] Path forward computation completed: fiber_list={:s}' + LOGGER.info(MSG.format(str(fiber_list))) return fiber_list - def get_link_by_name (self, key): + def get_link_by_name(self, key : str) -> Dict: for link in self.links_dict["optical_links"]: if link["name"] == key: #if debug: # print(link) - break - return link + return link + + MSG = '[RSA:get_link_by_name] Link with name {:s} not found. links_dict: {:s}' + LOGGER.error(MSG.format(str(key), str(self.links_dict["optical_links"]))) + + MSG = '[RSA:get_link_by_name] Link with name {:s} not found' + raise ValueError(MSG.format(str(key))) def get_fiber_details(self, link_key, fiber_id): for link in self.links_dict["optical_links"]: @@ -601,6 +612,8 @@ class RSA(): def get_fibers_backward(self, links, slots, band): LOGGER.info('[RSA:get_fibers_backward] Starting path backward computation') + MSG = '[RSA:get_fibers_backward] Input parameters: links={:s}, slots={:s}, band={:s}' + LOGGER.info(MSG.format(str(links), str(slots), str(band))) fiber_list = {} #r_drop = reverse_link(links[0], self.link_key__to__src_dst_node_names) @@ -631,8 +644,9 @@ class RSA(): if list_in_list(slots, str_list_to_int(r_fib[band].keys())): #fiber_list[r_l] = r_fib["ID"] self.update_link(r_fib, slots, band) - - LOGGER.info('[RSA:get_fibers_backward] Path backward computation completed') + + MSG = '[RSA:get_fibers_backward] Path backward computation completed: fiber_list={:s}' + LOGGER.info(MSG.format(str(fiber_list))) return fiber_list #function invoked for lightpaths and OB diff --git a/src/service/service/service_handlers/oc/OCTools.py b/src/service/service/service_handlers/oc/OCTools.py index 8a07de859..d3fbb5e8f 100644 --- a/src/service/service/service_handlers/oc/OCTools.py +++ b/src/service/service/service_handlers/oc/OCTools.py @@ -18,8 +18,8 @@ from common.proto.context_pb2 import DeviceId, Service from common.tools.object_factory.Device import json_device_id from service.service.service_handler_api.Tools import get_endpoint_matching -log = logging.getLogger(__name__) +LOGGER = logging.getLogger(__name__) def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]])->Dict: @@ -28,7 +28,7 @@ def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]]) end = len(endpoints) i = 0 bidir = 0 - log.debug("end={}".format(end)) + LOGGER.debug("end={}".format(end)) while(i < end): endpoint = endpoints[i] device_uuid, endpoint_uuid = endpoint[0:2] @@ -41,12 +41,12 @@ def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]]) next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] if next_device_uuid == device_uuid : bidir = 1 - log.info("connection is bidirectional") + LOGGER.info("connection is bidirectional") entry_tuple = next_endpoint_uuid, "0" entries[device_uuid].append(entry_tuple) i = i + 1 else: - log.debug("connection is unidirectional") + LOGGER.debug("connection is unidirectional") else: if not bidir: if i == end-1: @@ -62,17 +62,17 @@ def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]]) entries[device_uuid].append(entry_tuple) i = i + 1 else: - log.debug("ERROR in unidirectional connection 4") + LOGGER.debug("ERROR in unidirectional connection 4") return {} else: - log.debug("Ocheck i {}, {}, {}".format(i, i+1, end-1)) + LOGGER.debug("Ocheck i {}, {}, {}".format(i, i+1, end-1)) if i + 1 == end-1: - log.debug("current OCTools step {}, {}, {}".format(i, device_uuid, endpoint_uuid)) + LOGGER.debug("current OCTools step {}, {}, {}".format(i, device_uuid, endpoint_uuid)) #is the last node entry_tuple = endpoint_uuid, "0" entries[device_uuid].append(entry_tuple) next_endpoint = endpoints[i+1] - log.debug("OCTools i+1 step {}, {}, {}".format(i+1, next_device_uuid, device_uuid)) + LOGGER.debug("OCTools i+1 step {}, {}, {}".format(i+1, next_device_uuid, device_uuid)) next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] if next_device_uuid == device_uuid: @@ -80,10 +80,10 @@ def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]]) entries[device_uuid].append(entry_tuple) i = i + 1 else: - log.debug("ERROR in bidirectional connection 2") + LOGGER.debug("ERROR in bidirectional connection 2") return entries else: - log.debug("OCTools i+1+2+3 step {}, {}, {}".format(i+1, next_device_uuid, device_uuid)) + LOGGER.debug("OCTools i+1+2+3 step {}, {}, {}".format(i+1, next_device_uuid, device_uuid)) #i+1 next_endpoint = endpoints[i+1] next_device_uuid, next_endpoint_uuid = next_endpoint[0:2] @@ -91,8 +91,8 @@ def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]]) entry_tuple = endpoint_uuid, next_endpoint_uuid entries[device_uuid].append(entry_tuple) else: - log.debug("ERROR in bidirectional connection 3") - log.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) + LOGGER.debug("ERROR in bidirectional connection 3") + LOGGER.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) return entries #i+2 next_2_endpoint = endpoints[i+2] @@ -100,14 +100,14 @@ def convert_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]]) #i+3 next_3_endpoint = endpoints[i+3] next_3_device_uuid, next_3_endpoint_uuid = next_3_endpoint[0:2] - log.debug(f"de {device_uuid} and i {i}") - log.debug(f"de2 {next_2_device_uuid} and dev3 {next_3_device_uuid}") + LOGGER.debug(f"de {device_uuid} and i {i}") + LOGGER.debug(f"de2 {next_2_device_uuid} and dev3 {next_3_device_uuid}") if next_2_device_uuid == next_3_device_uuid and next_3_device_uuid == device_uuid: entry_tuple = next_2_endpoint_uuid, next_3_endpoint_uuid entries[device_uuid].append(entry_tuple) i = i + 3 else: - log.debug("ERROR in bidirection connection 4") + LOGGER.debug("ERROR in bidirection connection 4") return {} i = i + 1 return entries @@ -121,7 +121,7 @@ def convert_or_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str] end = len(endpoints) i = 0 if bidir: - log.info(f"i starts with {i} ") + LOGGER.info(f"i starts with {i} ") i = i + 1 while(i < end-2): #i @@ -146,8 +146,8 @@ def convert_or_endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str] #i+3 next_3_endpoint = endpoints[i+3] next_3_device_uuid, next_3_endpoint_uuid = next_3_endpoint[0:2] - log.info(f"dev {device_uuid} ") - log.info(f"dev2 {next_2_device_uuid} dev3 {next_3_device_uuid} ") + LOGGER.info(f"dev {device_uuid} ") + LOGGER.info(f"dev2 {next_2_device_uuid} dev3 {next_3_device_uuid} ") if next_2_device_uuid == next_3_device_uuid and next_3_device_uuid == device_uuid: entry_tuple = next_2_endpoint_uuid, next_3_endpoint_uuid entries[device_uuid].append(entry_tuple) @@ -198,7 +198,7 @@ def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): entry_tuple = next_endpoint_uuid, "0" entries[next_device_uuid].append(entry_tuple) else: - log.info("error expected device_id {}, found {}".format(device_uuid, next_device_uuid)) + LOGGER.info("error expected device_id {}, found {}".format(device_uuid, next_device_uuid)) return {} i = i + 2 if end > 4: @@ -207,7 +207,7 @@ def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): #i endpoint = endpoints[i] device_uuid, endpoint_uuid = endpoint[0:2] - log.debug("current OCTools step {}, {}, {}".format(i, device_uuid, endpoint_uuid)) + LOGGER.debug("current OCTools step {}, {}, {}".format(i, device_uuid, endpoint_uuid)) if device_uuid not in entries.keys(): entries[device_uuid] = [] #i+1 @@ -217,8 +217,8 @@ def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): entry_tuple = endpoint_uuid, next_endpoint_uuid entries[device_uuid].append(entry_tuple) else: - log.debug("ERROR in bidirectional ob") - log.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) + LOGGER.debug("ERROR in bidirectional ob") + LOGGER.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) return {} #i+2 next_2_endpoint = endpoints[i+2] @@ -231,7 +231,7 @@ def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): entries[device_uuid].append(entry_tuple) i = i + 4 else: - log.debug("ERROR in bidirection ob") + LOGGER.debug("ERROR in bidirection ob") return {} endpoint = endpoints[i] device_uuid, endpoint_uuid = endpoint[0:2] @@ -247,7 +247,7 @@ def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): entry_tuple = "0", next_endpoint_uuid entries[next_device_uuid].append(entry_tuple) else: - log.debug("error expected device_id {}, found {}".format(device_uuid, next_device_uuid)) + LOGGER.debug("error expected device_id {}, found {}".format(device_uuid, next_device_uuid)) else: endpoint = endpoints[i] device_uuid, endpoint_uuid = endpoint[0:2] @@ -273,8 +273,8 @@ def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): entry_tuple = endpoint_uuid, next_endpoint_uuid entries[device_uuid].append(entry_tuple) else: - log.debug("ERROR in bidirectional ob") - log.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) + LOGGER.debug("ERROR in bidirectional ob") + LOGGER.debug("{}, {}, {}".format(i, next_device_uuid, device_uuid)) return {} i = i + 2 next_endpoint = endpoints[i] @@ -284,9 +284,12 @@ def ob_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int): entry_tuple = next_endpoint_uuid, "0" entries[next_device_uuid].append(entry_tuple) return entries - - + + def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op_mode: int): + MSG = '[OCTools:conn_flows] endpoints={:s}, bidir={:s}, op_mode={:s}' + LOGGER.info(MSG.format(str(endpoints), str(bidir), str(op_mode))) + if op_mode is not None: entries = {} end = len(endpoints) @@ -302,7 +305,7 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op i = i + 1 #if bidir reading 4 endpoints per node if bidir: - log.info(f"i starts with {i} ") + LOGGER.info(f"i starts with {i} ") device0 , endpoint0=endpoints[0][0:2] device1 , endpoint1=endpoints[1][0:2] finalend=end-2 @@ -324,23 +327,25 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op entry_tuple = endpoint_uuid, next_endpoint_uuid entries[device_uuid].append(entry_tuple) else: - log.info(f"error : next_dev {next_device_uuid} dev {device_uuid} for i {i} ") - return {} + MSG = '[OCTools:conn_flows] error : next_dev {:s} dev {:s} for i {:d}' + LOGGER.error(MSG.format(str(next_device_uuid), str(device_uuid), i)) + return {} #i+2 - + next_2_endpoint = endpoints[i+2] next_2_device_uuid, next_2_endpoint_uuid = next_2_endpoint[0:2] #i+3 next_3_endpoint = endpoints[i+3] next_3_device_uuid, next_3_endpoint_uuid = next_3_endpoint[0:2] - log.info(f"dev {device_uuid} ") - log.info(f"dev2 {next_2_device_uuid} dev3 {next_3_device_uuid} ") + LOGGER.info(f"dev {device_uuid} ") + LOGGER.info(f"dev2 {next_2_device_uuid} dev3 {next_3_device_uuid} ") if next_2_device_uuid == next_3_device_uuid and next_3_device_uuid == device_uuid: entry_tuple = next_2_endpoint_uuid, next_3_endpoint_uuid entries[device_uuid].append(entry_tuple) i = i + 4 else: - log.info(f"error : next_2_dev {next_2_device_uuid} next_3_device{next_3_device_uuid} dev {device_uuid} for i {i} ") + MSG = '[OCTools:conn_flows] error : next_2_dev {:s} next_3_device{:s} dev {:s} for i {:d}' + LOGGER.error(MSG.format(str(next_2_device_uuid), str(next_3_device_uuid), str(device_uuid), i)) return {} else: while(i < end-1): @@ -358,8 +363,10 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op entries[device_uuid].append(entry_tuple) i = i + 2 else: + MSG = '[OCTools:conn_flows] error : next_dev {:s} dev {:s} for i {:d}' + LOGGER.error(MSG.format(str(next_device_uuid), str(device_uuid), i)) return {} - #rx tp + #rx tp endpoint = endpoints[i] device_uuid, endpoint_uuid = endpoint[0:2] if device_uuid not in entries.keys(): @@ -369,8 +376,9 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op else: entries = {} if len(endpoints) != 4: - log.info(f"PDP : expected alien configuration with 4 endpoints ") - return {} + MSG = '[OCTools:conn_flows] error : expected 4 endpoints for PDP, found {:d}' + LOGGER.error(MSG.format(len(endpoints))) + return {} i = 0 device0 , endpoint0 = endpoints[0][0:2] device1 , endpoint1 = endpoints[1][0:2] @@ -395,7 +403,7 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op #if bidir reading 4 endpoints per node ''' if bidir: - log.info(f"i starts with {i} ") + LOGGER.info(f"i starts with {i} ") device0 , endpoint0=endpoints[0][0:2] device1 , endpoint1=endpoints[1][0:2] finalend=end-2 @@ -417,7 +425,7 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op entry_tuple = endpoint_uuid, next_endpoint_uuid entries[device_uuid].append(entry_tuple) else: - log.info(f"error : next_dev {next_device_uuid} dev {device_uuid} for i {i} ") + LOGGER.info(f"error : next_dev {next_device_uuid} dev {device_uuid} for i {i} ") return {} #i+2 @@ -426,14 +434,14 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op #i+3 next_3_endpoint = endpoints[i+3] next_3_device_uuid, next_3_endpoint_uuid = next_3_endpoint[0:2] - log.info(f"dev {device_uuid} ") - log.info(f"dev2 {next_2_device_uuid} dev3 {next_3_device_uuid} ") + LOGGER.info(f"dev {device_uuid} ") + LOGGER.info(f"dev2 {next_2_device_uuid} dev3 {next_3_device_uuid} ") if next_2_device_uuid == next_3_device_uuid and next_3_device_uuid == device_uuid: entry_tuple = next_2_endpoint_uuid, next_3_endpoint_uuid entries[device_uuid].append(entry_tuple) i = i + 4 else: - log.info(f"error : next_2_dev {next_2_device_uuid} next_3_device{next_3_device_uuid} dev {device_uuid} for i {i} ") + LOGGER.info(f"error : next_2_dev {next_2_device_uuid} next_3_device{next_3_device_uuid} dev {device_uuid} for i {i} ") return {} else: while(i < end-1): @@ -460,18 +468,22 @@ def conn_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, op entry_tuple = endpoint_uuid, "0", entries[device_uuid].append(entry_tuple) ''' + + MSG = '[OCTools:conn_flows] entries={:s}' + LOGGER.info(MSG.format(str(entries))) return entries - -def endpoints_to_flows(endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, is_ob: bool, op_mode: int)->Dict: +def endpoints_to_flows( + endpoints : List[Tuple[str, str, Optional[str]]], bidir : int, is_ob : bool, op_mode : int +) -> Dict: if is_ob: entries = ob_flows(endpoints, bidir) else: entries = conn_flows(endpoints, bidir, op_mode) - return entries + def get_device_endpint_name(endpoint_uuid : str, device_uuid : str, task_executor) -> Tuple: device_obj = task_executor.get_device(DeviceId(**json_device_id(device_uuid))) endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid) -- GitLab From c1f7fe0798cf31b252b5405551bc5873da6b1733 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Thu, 4 Jun 2026 17:24:10 +0000 Subject: [PATCH 4/7] Added temporarily deploy specs and scripts --- deploy/all.sh | 4 ++-- my_deploy.sh | 12 ++++++------ redeploy.sh | 4 ++++ 3 files changed, 12 insertions(+), 8 deletions(-) create mode 100755 redeploy.sh diff --git a/deploy/all.sh b/deploy/all.sh index 0f71d6ded..72c8643aa 100755 --- a/deploy/all.sh +++ b/deploy/all.sh @@ -250,7 +250,7 @@ export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} ./deploy/nats.sh # Deploy QuestDB -./deploy/qdb.sh +#./deploy/qdb.sh # Deploy Apache Kafka ./deploy/kafka.sh @@ -259,7 +259,7 @@ export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} # ./deploy/monitoring.sh # Expose Dashboard -./deploy/expose_dashboard.sh +#./deploy/expose_dashboard.sh # Deploy TeraFlowSDN ./deploy/tfs.sh diff --git a/my_deploy.sh b/my_deploy.sh index bc7e2dc97..5bbe31819 100644 --- a/my_deploy.sh +++ b/my_deploy.sh @@ -38,11 +38,11 @@ export TFS_COMPONENTS="context device pathcomp service nbi webui" # To manage optical connections, "service" requires "opticalcontroller" to be deployed # before "service", thus we "hack" the TFS_COMPONENTS environment variable prepending the # "opticalcontroller" only if "service" is already in TFS_COMPONENTS, and re-export it. -#if [[ "$TFS_COMPONENTS" == *"service"* ]]; then -# BEFORE="${TFS_COMPONENTS% service*}" -# AFTER="${TFS_COMPONENTS#* service}" -# export TFS_COMPONENTS="${BEFORE} opticalcontroller service ${AFTER}" -#fi +if [[ "$TFS_COMPONENTS" == *"service"* ]]; then + BEFORE="${TFS_COMPONENTS% service*}" + AFTER="${TFS_COMPONENTS#* service}" + export TFS_COMPONENTS="${BEFORE} opticalcontroller service ${AFTER}" +fi # Uncomment to activate ZTP #export TFS_COMPONENTS="${TFS_COMPONENTS} ztp" @@ -143,7 +143,7 @@ export CRDB_PASSWORD="tfs123" export CRDB_DEPLOY_MODE="single" # Disable flag for dropping database, if it exists. -export CRDB_DROP_DATABASE_IF_EXISTS="" +export CRDB_DROP_DATABASE_IF_EXISTS="YES" # Disable flag for re-deploying CockroachDB from scratch. export CRDB_REDEPLOY="" diff --git a/redeploy.sh b/redeploy.sh new file mode 100755 index 000000000..d2025ca6b --- /dev/null +++ b/redeploy.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source my_deploy.sh +./deploy/all.sh -- GitLab From 14da4b5afc1b6a767120152bbb2240ef854674fc Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Wed, 17 Jun 2026 12:32:53 +0000 Subject: [PATCH 5/7] Merge branch 'develop' of ssh://gifrerenom_labs.etsi.org/tfs/controller into feat/404-cttc-multiple-enhancements-in-optical-controller --- .gitlab-ci.yml | 2 +- deploy/all.sh | 7 + deploy/build-only.sh | 7 + deploy/component.sh | 9 + deploy/crdb.sh | 8 + deploy/kafka.sh | 6 + deploy/mock_blockchain.sh | 8 + deploy/nats.sh | 9 +- deploy/qdb.sh | 6 + deploy/tfs.sh | 8 + my_deploy.sh | 5 + proto/context.proto | 40 + proto/device.proto | 1 + scripts/ci_cleanup_gitlab_runner.sh | 38 + .../ci_prepare_microk8s_storage_registry.sh | 176 + scripts/dockerhub_k8s_secret.sh | 75 + scripts/dockerhub_login.sh | 23 + scripts/prune_old_mr_docker_images.sh | 50 + src/analytics/.gitlab-ci.yml | 3 + src/automation/.gitlab-ci.yml | 1 + src/bgpls_speaker/.gitlab-ci.yml | 1 + src/common/tests/MockServicerImpl_Context.py | 124 + .../tools/rest_conf/client/RestConfClient.py | 2 +- src/context/.gitlab-ci.yml | 2 + src/context/client/ContextClient.py | 38 +- .../service/ContextServiceServicerImpl.py | 38 +- src/context/service/database/ConfigRule.py | 3 + src/context/service/database/Device.py | 13 +- .../database/OpticalSpectrumReservation.py | 337 ++ .../models/OpticalSpectrumReservationModel.py | 93 + .../test_optical_spectrum_reservation.py | 201 + src/dbscanserving/.gitlab-ci.yml | 2 + src/device/.gitlab-ci.yml | 2 + src/device/client/DeviceClient.py | 8 + .../service/DeviceServiceServicerImpl.py | 66 +- src/device/service/Tools.py | 20 + .../drivers/openconfig/OpenConfigDriver.py | 2 + .../openconfig/templates/Interfaces.py | 15 + src/dlt/.gitlab-ci.yml | 3 + src/e2e_orchestrator/.gitlab-ci.yml | 1 + src/e2e_orchestrator/Dockerfile | 3 + .../E2EOrchestratorServiceServicerImpl.py | 15 + src/forecaster/.gitlab-ci.yml | 2 + src/gitlab-ci.yml_generator.py | 2 + src/interdomain/.gitlab-ci.yml | 2 + src/kpi_manager/.gitlab-ci.yml | 2 + src/kpi_value_api/.gitlab-ci.yml | 2 + src/kpi_value_writer/.gitlab-ci.yml | 2 + src/l3_attackmitigator/.gitlab-ci.yml | 2 + .../.gitlab-ci.yml | 2 + .../.gitlab-ci.yml | 2 + src/load_generator/.gitlab-ci.yml | 1 + src/monitoring/.gitlab-ci.yml | 2 + src/nbi/.gitlab-ci.yml | 2 + src/nbi/Dockerfile | 4 + src/nbi/service/app.py | 2 + .../service/ietf_sap_topology/NameMapping.py | 48 + .../ietf_sap_topology/NetworkTypeEnum.py | 23 + src/nbi/service/ietf_sap_topology/Networks.py | 86 + .../service/ietf_sap_topology/SAP_Topology.py | 88 + .../service/ietf_sap_topology/YangHandler.py | 177 + src/nbi/service/ietf_sap_topology/__init__.py | 39 + .../ietf_sap_topology/build-yang-bindings.sh | 34 + .../yang/iana-routing-types@2017-12-04.yang | 473 +++ .../yang/ietf-ac-ntw@2024-05-15.yang | 2019 ++++++++++ .../yang/ietf-eth-te-topology@2023-09-28.yang | 2275 +++++++++++ .../ietf-eth-tran-service@2023-10-23.yang | 1004 +++++ .../yang/ietf-eth-tran-types@2023-10-23.yang | 457 +++ .../yang/ietf-ethertypes@2019-03-04.yang | 381 ++ .../yang/ietf-inet-types@2013-07-15.yang | 459 +++ .../ietf-l3-unicast-topology@2018-02-26.yang | 359 ++ .../yang/ietf-layer1-types@2022-10-14.yang | 1414 +++++++ .../yang/ietf-netconf-acm@2018-02-14.yang | 464 +++ .../ietf-network-topology@2018-02-26.yang | 294 ++ .../yang/ietf-network@2018-02-26.yang | 193 + .../yang/ietf-otn-topology@2023-07-06.yang | 2405 ++++++++++++ .../yang/ietf-packet-fields@2019-03-04.yang | 576 +++ .../yang/ietf-routing-types@2017-12-04.yang | 774 ++++ .../yang/ietf-sap-ntw@2023-06-20.yang | 350 ++ .../yang/ietf-te-packet-types@2020-06-10.yang | 475 +++ .../yang/ietf-te-topology@2020-08-06.yang | 1952 ++++++++++ .../yang/ietf-te-types@2020-06-10.yang | 3379 +++++++++++++++++ .../ietf-trans-client-service@2023-10-23.yang | 325 ++ ...etf-trans-client-svc-types@2023-10-23.yang | 63 + .../yang/ietf-vpn-common@2022-02-11.yang | 2251 +++++++++++ .../yang/ietf-yang-types@2013-07-15.yang | 475 +++ src/nbi/service/tfs_api/Resources.py | 157 +- src/nbi/service/tfs_api/Tools.py | 10 + src/nbi/service/tfs_api/__init__.py | 15 +- src/nbi/tests/test_tfs_api.py | 166 +- .../tests/test_tfs_api_grpc_error_mapping.py | 54 + src/opticalattackdetector/.gitlab-ci.yml | 1 + src/opticalattackmanager/.gitlab-ci.yml | 1 + src/opticalattackmitigator/.gitlab-ci.yml | 1 + src/opticalcontroller/.gitlab-ci.yml | 1 + src/opticalcontroller/OpticalController.py | 13 +- src/opticalcontroller/RSA.py | 41 +- .../tests/test_spectrum_reservation.py | 90 + src/opticalcontroller/tools.py | 78 +- src/osm_client/.gitlab-ci.yml | 2 + src/pathcomp/.gitlab-ci.yml | 3 + .../frontend/service/OpticalPathComp.py | 443 +++ .../service/PathCompServiceServicerImpl.py | 7 + .../frontend/service/TopologyTools.py | 36 +- src/pluggables/.gitlab-ci.yml | 1 + src/policy/.gitlab-ci.yml | 2 + src/qkd_app/.gitlab-ci.yml | 1 + src/qos_profile/.gitlab-ci.yml | 2 + src/service/.gitlab-ci.yml | 2 + .../service/ServiceServiceServicerImpl.py | 17 +- .../tools/OpticalSpectrumReservation.py | 75 + src/service/service/tools/OpticalTools.py | 14 +- .../test_optical_spectrum_reservation.py | 74 + src/simap_connector/.gitlab-ci.yml | 1 + src/slice/.gitlab-ci.yml | 1 + src/telemetry/.gitlab-ci.yml | 3 + src/tests/acl_end2end/.gitlab-ci.yml | 98 +- src/tests/ecoc22/.gitlab-ci.yml | 93 +- src/tests/ecoc22/deploy_specs.sh | 2 +- src/tests/eucnc24/.gitlab-ci.yml | 102 +- src/tests/l2_vpn_gnmi_oc/.gitlab-ci.yml | 102 +- src/tests/ofc22/.gitlab-ci.yml | 100 +- src/tests/ofc22/deploy_specs.sh | 2 +- src/tests/ofc24/.gitlab-ci.yml | 106 +- .../.gitlab-ci.yml | 24 +- .../.gitlab-ci.yml | 26 +- src/tests/ofc25/.gitlab-ci.yml | 153 +- src/tests/ofc25/deploy_all_in_one.sh | 1 - src/tests/osm_end2end/.gitlab-ci.yml | 107 +- src/tests/osm_end2end/run-local.sh | 15 +- src/tests/qkd_end2end/.gitlab-ci.yml | 114 +- src/tests/ryu-openflow/.gitlab-ci.yml | 109 +- src/tests/spectrum_negotiation/README.md | 41 + .../live_reservation_validation.py | 196 + src/tests/tools/mock_osm_nbi/.gitlab-ci.yml | 1 + src/tests/tools/mock_qkd_node/.gitlab-ci.yml | 1 + .../mock_tfs_nbi_dependencies/.gitlab-ci.yml | 1 + .../tools/simap_datastore/.gitlab-ci.yml | 1 + src/vnt_manager/.gitlab-ci.yml | 1 + src/webui/.gitlab-ci.yml | 2 + src/webui/service/device/routes.py | 15 +- .../service/templates/device/detail.html | 6 + src/ztp/.gitlab-ci.yml | 2 + src/ztp_server/.gitlab-ci.yml | 2 + 144 files changed, 26618 insertions(+), 929 deletions(-) create mode 100755 scripts/ci_cleanup_gitlab_runner.sh create mode 100755 scripts/ci_prepare_microk8s_storage_registry.sh create mode 100644 scripts/dockerhub_k8s_secret.sh create mode 100644 scripts/dockerhub_login.sh create mode 100644 scripts/prune_old_mr_docker_images.sh create mode 100644 src/context/service/database/OpticalSpectrumReservation.py create mode 100644 src/context/service/database/models/OpticalSpectrumReservationModel.py create mode 100644 src/context/tests/test_optical_spectrum_reservation.py create mode 100644 src/nbi/service/ietf_sap_topology/NameMapping.py create mode 100644 src/nbi/service/ietf_sap_topology/NetworkTypeEnum.py create mode 100644 src/nbi/service/ietf_sap_topology/Networks.py create mode 100644 src/nbi/service/ietf_sap_topology/SAP_Topology.py create mode 100644 src/nbi/service/ietf_sap_topology/YangHandler.py create mode 100644 src/nbi/service/ietf_sap_topology/__init__.py create mode 100755 src/nbi/service/ietf_sap_topology/build-yang-bindings.sh create mode 100644 src/nbi/service/ietf_sap_topology/yang/iana-routing-types@2017-12-04.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-ac-ntw@2024-05-15.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-eth-te-topology@2023-09-28.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-service@2023-10-23.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-types@2023-10-23.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-ethertypes@2019-03-04.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-inet-types@2013-07-15.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-l3-unicast-topology@2018-02-26.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-layer1-types@2022-10-14.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-netconf-acm@2018-02-14.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-network-topology@2018-02-26.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-network@2018-02-26.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-otn-topology@2023-07-06.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-packet-fields@2019-03-04.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-routing-types@2017-12-04.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-sap-ntw@2023-06-20.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-te-packet-types@2020-06-10.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-te-topology@2020-08-06.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-te-types@2020-06-10.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-service@2023-10-23.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-svc-types@2023-10-23.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-vpn-common@2022-02-11.yang create mode 100644 src/nbi/service/ietf_sap_topology/yang/ietf-yang-types@2013-07-15.yang create mode 100644 src/nbi/tests/test_tfs_api_grpc_error_mapping.py create mode 100644 src/opticalcontroller/tests/test_spectrum_reservation.py create mode 100644 src/pathcomp/frontend/service/OpticalPathComp.py create mode 100644 src/service/service/tools/OpticalSpectrumReservation.py create mode 100644 src/service/tests/test_optical_spectrum_reservation.py create mode 100644 src/tests/spectrum_negotiation/README.md create mode 100644 src/tests/spectrum_negotiation/live_reservation_validation.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cc8c151c9..601c0f659 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -48,7 +48,7 @@ include: #- local: '/src/l3_distributedattackdetector/.gitlab-ci.yml' #- local: '/src/l3_centralizedattackdetector/.gitlab-ci.yml' #- local: '/src/l3_attackmitigator/.gitlab-ci.yml' - - local: '/src/slice/.gitlab-ci.yml' + #- local: '/src/slice/.gitlab-ci.yml' #- local: '/src/interdomain/.gitlab-ci.yml' - local: '/src/pathcomp/.gitlab-ci.yml' #- local: '/src/dlt/.gitlab-ci.yml' diff --git a/deploy/all.sh b/deploy/all.sh index 72c8643aa..cc20f7f3e 100755 --- a/deploy/all.sh +++ b/deploy/all.sh @@ -88,6 +88,11 @@ export TFS_GRAFANA_PASSWORD=${TFS_GRAFANA_PASSWORD:-"admin123+"} # If TFS_SKIP_BUILD is "YES", the containers are not rebuilt-retagged-repushed and existing ones are used. export TFS_SKIP_BUILD=${TFS_SKIP_BUILD:-""} +# Optionally set Docker Hub credentials to avoid anonymous pull rate limits while building/pulling public images. +# If either variable is empty, Docker Hub is used anonymously. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + # ----- CockroachDB ------------------------------------------------------------ @@ -243,6 +248,8 @@ export GRAF_EXT_PORT_HTTP=${GRAF_EXT_PORT_HTTP:-"3000"} # Automated steps start here ######################################################################################################################## +bash scripts/dockerhub_login.sh + # Deploy CockroachDB ./deploy/crdb.sh diff --git a/deploy/build-only.sh b/deploy/build-only.sh index 0790ff178..5f9e90501 100755 --- a/deploy/build-only.sh +++ b/deploy/build-only.sh @@ -32,11 +32,18 @@ export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device pathcomp service slice n # If not already set, set the tag you want to use for your images. export TFS_IMAGE_TAG=${TFS_IMAGE_TAG:-"dev"} +# Optionally set Docker Hub credentials to avoid anonymous pull rate limits while building/pulling public images. +# If either variable is empty, Docker Hub is used anonymously. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + ######################################################################################################################## # Automated steps start here ######################################################################################################################## +bash scripts/dockerhub_login.sh + # Create a tmp folder for files modified during the deployment TMP_LOGS_FOLDER="./tmp/build" mkdir -p $TMP_LOGS_FOLDER diff --git a/deploy/component.sh b/deploy/component.sh index ab347a9e1..65b56197d 100755 --- a/deploy/component.sh +++ b/deploy/component.sh @@ -36,10 +36,17 @@ export TFS_EXTRA_MANIFESTS=${TFS_EXTRA_MANIFESTS:-""} # If not already set, set the neew Grafana admin password export TFS_GRAFANA_PASSWORD=${TFS_GRAFANA_PASSWORD:-"admin123+"} +# Optionally set Docker Hub credentials to avoid anonymous pull rate limits while building/pulling public images. +# If either variable is empty, Docker Hub is used anonymously. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + ######################################################################################################################## # Automated steps start here ######################################################################################################################## +bash scripts/dockerhub_login.sh + DOCKER_BUILD="docker build" DOCKER_MAJOR_VERSION=$(docker --version | grep -o -E "Docker version [0-9]+\." | grep -o -E "[0-9]+" | cut -c 1-3) if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then @@ -63,6 +70,8 @@ TMP_FOLDER="./tmp" TMP_MANIFESTS_FOLDER="$TMP_FOLDER/manifests" TMP_LOGS_FOLDER="$TMP_FOLDER/logs" +bash scripts/dockerhub_k8s_secret.sh "$TFS_K8S_NAMESPACE" + echo "Deploying component and collecting environment variables..." ENV_VARS_SCRIPT=tfs_runtime_env_vars.sh diff --git a/deploy/crdb.sh b/deploy/crdb.sh index 1bade068b..009c771c1 100755 --- a/deploy/crdb.sh +++ b/deploy/crdb.sh @@ -55,6 +55,11 @@ export CRDB_DROP_DATABASE_IF_EXISTS=${CRDB_DROP_DATABASE_IF_EXISTS:-""} # If CRDB_REDEPLOY is "YES", the database will be dropped while checking/deploying CockroachDB. export CRDB_REDEPLOY=${CRDB_REDEPLOY:-""} +# Optionally set Docker Hub credentials to avoid anonymous Kubernetes image pull rate limits. +# If either variable is empty, Kubernetes uses anonymous Docker Hub image pulls. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + ######################################################################################################################## # Automated steps start here @@ -72,6 +77,7 @@ function crdb_deploy_single() { echo "CockroachDB Namespace" echo ">>> Create CockroachDB Namespace (if missing)" kubectl create namespace ${CRDB_NAMESPACE} + bash scripts/dockerhub_k8s_secret.sh "${CRDB_NAMESPACE}" echo echo "CockroachDB (single-mode)" @@ -185,6 +191,7 @@ function crdb_deploy_cluster() { echo "CockroachDB Operator Namespace" echo ">>> Create CockroachDB Operator Namespace (if missing)" kubectl apply -f "${CRDB_MANIFESTS_PATH}/pre_operator.yaml" + bash scripts/dockerhub_k8s_secret.sh "cockroach-operator-system" echo echo "Cockroach Operator CRDs" @@ -226,6 +233,7 @@ function crdb_deploy_cluster() { echo "CockroachDB Namespace" echo ">>> Create CockroachDB Namespace (if missing)" kubectl create namespace ${CRDB_NAMESPACE} + bash scripts/dockerhub_k8s_secret.sh "${CRDB_NAMESPACE}" echo echo "CockroachDB (cluster-mode)" diff --git a/deploy/kafka.sh b/deploy/kafka.sh index 2a4808c88..f257ccbac 100755 --- a/deploy/kafka.sh +++ b/deploy/kafka.sh @@ -35,6 +35,11 @@ export KFK_DEPLOY_MODE=${KFK_DEPLOY_MODE:-"single"} # If KFK_REDEPLOY is "YES", the message broker will be dropped while checking/deploying Kafka. export KFK_REDEPLOY=${KFK_REDEPLOY:-""} +# Optionally set Docker Hub credentials to avoid anonymous Kubernetes image pull rate limits. +# If either variable is empty, Kubernetes uses anonymous Docker Hub image pulls. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + ######################################################################################################################## # Automated steps start here @@ -52,6 +57,7 @@ function kfk_deploy_single() { echo "Kafka Namespace" echo ">>> Create Kafka Namespace (if missing)" kubectl create namespace ${KFK_NAMESPACE} + bash scripts/dockerhub_k8s_secret.sh "${KFK_NAMESPACE}" echo echo "Kafka (single-mode)" diff --git a/deploy/mock_blockchain.sh b/deploy/mock_blockchain.sh index 53c16fb4c..28dc04335 100755 --- a/deploy/mock_blockchain.sh +++ b/deploy/mock_blockchain.sh @@ -27,12 +27,19 @@ IMAGE_TAG="dev" # Set the name of the Kubernetes namespace to deploy to. K8S_NAMESPACE="tfs-bchain" +# Optionally set Docker Hub credentials to avoid anonymous pull rate limits while building/pulling public images. +# If either variable is empty, Docker Hub is used anonymously. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + COMPONENT="mock_blockchain" ######################################################################################################################## # Automated steps start here ######################################################################################################################## +bash scripts/dockerhub_login.sh + # Constants GITLAB_REPO_URL="labs.etsi.org:5050/tfs/controller" TMP_FOLDER="./tmp" @@ -46,6 +53,7 @@ mkdir -p $TMP_LOGS_FOLDER echo "Deleting and Creating a new namespace..." kubectl delete namespace $K8S_NAMESPACE --ignore-not-found kubectl create namespace $K8S_NAMESPACE +bash scripts/dockerhub_k8s_secret.sh "$K8S_NAMESPACE" printf "\n" echo "Deploying components and collecting environment variables..." diff --git a/deploy/nats.sh b/deploy/nats.sh index 34b9d8907..81ae50682 100755 --- a/deploy/nats.sh +++ b/deploy/nats.sh @@ -40,6 +40,11 @@ export NATS_DEPLOY_MODE=${NATS_DEPLOY_MODE:-"single"} # If NATS_REDEPLOY is "YES", the message broker will be dropped while checking/deploying NATS. export NATS_REDEPLOY=${NATS_REDEPLOY:-""} +# Optionally set Docker Hub credentials to avoid anonymous Kubernetes image pull rate limits. +# If either variable is empty, Kubernetes uses anonymous Docker Hub image pulls. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + ######################################################################################################################## # Automated steps start here @@ -57,6 +62,7 @@ function nats_deploy_single() { echo "NATS Namespace" echo ">>> Create NATS Namespace (if missing)" kubectl create namespace ${NATS_NAMESPACE} + bash scripts/dockerhub_k8s_secret.sh "${NATS_NAMESPACE}" echo echo "Add NATS Helm Chart" @@ -123,6 +129,7 @@ function nats_deploy_cluster() { echo "NATS Namespace" echo ">>> Create NATS Namespace (if missing)" kubectl create namespace ${NATS_NAMESPACE} + bash scripts/dockerhub_k8s_secret.sh "${NATS_NAMESPACE}" echo echo "Add NATS Helm Chart" @@ -230,4 +237,4 @@ elif [ "$NATS_DEPLOY_MODE" == "cluster" ]; then nats_deploy_cluster else echo "Unsupported value: NATS_DEPLOY_MODE=$NATS_DEPLOY_MODE" -fi \ No newline at end of file +fi diff --git a/deploy/qdb.sh b/deploy/qdb.sh index e1275d870..0b634f562 100755 --- a/deploy/qdb.sh +++ b/deploy/qdb.sh @@ -54,6 +54,11 @@ export QDB_DROP_TABLES_IF_EXIST=${QDB_DROP_TABLES_IF_EXIST:-""} # If QDB_REDEPLOY is "YES", the database will be dropped while checking/deploying QuestDB. export QDB_REDEPLOY=${QDB_REDEPLOY:-""} +# Optionally set Docker Hub credentials to avoid anonymous Kubernetes image pull rate limits. +# If either variable is empty, Kubernetes uses anonymous Docker Hub image pulls. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + ######################################################################################################################## # Automated steps start here @@ -71,6 +76,7 @@ function qdb_deploy() { echo "QuestDB Namespace" echo ">>> Create QuestDB Namespace (if missing)" kubectl create namespace ${QDB_NAMESPACE} + bash scripts/dockerhub_k8s_secret.sh "${QDB_NAMESPACE}" sleep 2 echo diff --git a/deploy/tfs.sh b/deploy/tfs.sh index 39ee95bed..887d73630 100755 --- a/deploy/tfs.sh +++ b/deploy/tfs.sh @@ -45,6 +45,11 @@ export TFS_GRAFANA_PASSWORD=${TFS_GRAFANA_PASSWORD:-"admin123+"} # If TFS_SKIP_BUILD is "YES", the containers are not rebuilt-retagged-repushed and existing ones are used. export TFS_SKIP_BUILD=${TFS_SKIP_BUILD:-""} +# Optionally set Docker Hub credentials to avoid anonymous pull rate limits while building/pulling public images. +# If either variable is empty, Docker Hub is used anonymously. +export DOCKERHUB_USER_NAME=${DOCKERHUB_USER_NAME:-""} +export DOCKERHUB_ACCESS_TOKEN=${DOCKERHUB_ACCESS_TOKEN:-""} + # ----- CockroachDB ------------------------------------------------------------ @@ -106,6 +111,8 @@ export LOAD_BALANCER_IP=${LOAD_BALANCER_IP:-""} # Automated steps start here ######################################################################################################################## +bash scripts/dockerhub_login.sh + # Constants GITLAB_REPO_URL="labs.etsi.org:5050/tfs/controller" TMP_FOLDER="./tmp" @@ -119,6 +126,7 @@ mkdir -p $TMP_LOGS_FOLDER echo "Deleting and Creating a new namespace..." kubectl delete namespace $TFS_K8S_NAMESPACE --ignore-not-found kubectl create namespace $TFS_K8S_NAMESPACE +bash scripts/dockerhub_k8s_secret.sh "$TFS_K8S_NAMESPACE" sleep 2 printf "\n" diff --git a/my_deploy.sh b/my_deploy.sh index 5bbe31819..64b0fd06c 100644 --- a/my_deploy.sh +++ b/my_deploy.sh @@ -19,6 +19,11 @@ # Set the URL of the internal MicroK8s Docker registry where the images will be uploaded to. export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" +# Optionally set Docker Hub credentials to avoid anonymous pull rate limits while building/pulling public images. +# If either variable is empty, Docker Hub is used anonymously. +export DOCKERHUB_USER_NAME="" +export DOCKERHUB_ACCESS_TOKEN="" + # Set the list of components, separated by spaces, you want to build images for, and deploy. export TFS_COMPONENTS="context device pathcomp service nbi webui" diff --git a/proto/context.proto b/proto/context.proto index 0625d0440..3550fb180 100644 --- a/proto/context.proto +++ b/proto/context.proto @@ -99,6 +99,11 @@ service ContextService { rpc GetOpticalBand (Empty ) returns (OpticalBandList) {} rpc SelectOpticalBand (OpticalBandId ) returns (OpticalBand) {} + rpc SetOpticalSpectrumReservation (OpticalSpectrumReservation ) returns (OpticalSpectrumReservationId ) {} + rpc GetOpticalSpectrumReservation (OpticalSpectrumReservationId) returns (OpticalSpectrumReservation ) {} + rpc ListOpticalSpectrumReservations (ContextId ) returns (OpticalSpectrumReservationList) {} + rpc ConsumeOpticalSpectrumReservation (OpticalSpectrumReservation ) returns (OpticalSpectrumReservationId ) {} + rpc ReleaseOpticalSpectrumReservation (OpticalSpectrumReservationId) returns (Empty ) {} rpc DeleteServiceConfigRule(ServiceConfigRule) returns (Empty ) {} } @@ -813,6 +818,41 @@ message OpticalBandList { } +enum OpticalSpectrumReservationStatusEnum { + OPTICALSPECTRUMRESERVATIONSTATUS_UNDEFINED = 0; + OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED = 1; + OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED = 2; + OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED = 3; + OPTICALSPECTRUMRESERVATIONSTATUS_EXPIRED = 4; +} + +message OpticalSpectrumReservationId { + ContextId context_id = 1; + Uuid reservation_uuid = 2; +} + +message OpticalSpectrumReservation { + OpticalSpectrumReservationId reservation_id = 1; + TopologyId topology_id = 2; + repeated LinkId optical_link_ids = 3; + string band = 4; + uint32 n_start = 5; + uint32 n_end = 6; + uint32 required_slots = 7; + ServiceId service_id = 8; + ConnectionId connection_id = 9; + string owner_id = 10; + string correlation_id = 11; + OpticalSpectrumReservationStatusEnum status = 12; + Timestamp created_at = 13; + Timestamp updated_at = 14; + Timestamp expires_at = 15; +} + +message OpticalSpectrumReservationList { + repeated OpticalSpectrumReservation reservations = 1; +} + ////////////////// Config Rule Delete //////////// diff --git a/proto/device.proto b/proto/device.proto index 005521abf..40803e8e2 100644 --- a/proto/device.proto +++ b/proto/device.proto @@ -25,6 +25,7 @@ service DeviceService { rpc GetInitialConfig (context.DeviceId ) returns (context.DeviceConfig ) {} rpc MonitorDeviceKpi (MonitoringSettings ) returns (context.Empty ) {} rpc SSETelemetrySubscribe(monitoring.SSEMonitoringSubscriptionConfig) returns (monitoring.SSEMonitoringSubscriptionResponse ) {} + rpc UpdateDeviceInventory(context.DeviceId ) returns (context.Empty ) {} } message MonitoringSettings { diff --git a/scripts/ci_cleanup_gitlab_runner.sh b/scripts/ci_cleanup_gitlab_runner.sh new file mode 100755 index 000000000..38764b49b --- /dev/null +++ b/scripts/ci_cleanup_gitlab_runner.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +CI_CLEANUP_CONTAINERLAB="${CI_CLEANUP_CONTAINERLAB:-yes}" +CI_DOCKER_BUILD_CACHE_PRUNE="${CI_DOCKER_BUILD_CACHE_PRUNE:-yes}" + +if [[ -f scripts/prune_old_mr_docker_images.sh ]]; then + bash scripts/prune_old_mr_docker_images.sh +fi + +if [[ "${CI_CLEANUP_CONTAINERLAB}" == "yes" ]] && command -v containerlab >/dev/null 2>&1; then + containerlab destroy --all --cleanup || true +fi + +docker ps --all --quiet | xargs --no-run-if-empty docker stop +docker container prune --force +docker ps --all --quiet | xargs --no-run-if-empty docker rm --force +docker image prune --force +docker network prune --force +docker volume prune --all --force + +if [[ "${CI_DOCKER_BUILD_CACHE_PRUNE}" == "yes" ]]; then + docker buildx prune --force +fi diff --git a/scripts/ci_prepare_microk8s_storage_registry.sh b/scripts/ci_prepare_microk8s_storage_registry.sh new file mode 100755 index 000000000..24fa3586f --- /dev/null +++ b/scripts/ci_prepare_microk8s_storage_registry.sh @@ -0,0 +1,176 @@ +#!/bin/bash +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euo pipefail + +MICROK8S_CMD="${MICROK8S_CMD:-microk8s}" +KUBECTL_CMD="${KUBECTL_CMD:-kubectl}" +HELM_CMD="${HELM_CMD:-helm3}" +CI_RESET_MICROK8S_STORAGE_REGISTRY="${CI_RESET_MICROK8S_STORAGE_REGISTRY:-yes}" +CI_RESET_MICROK8S_STORAGE_ADDON="${CI_RESET_MICROK8S_STORAGE_ADDON:-auto}" +CI_K8S_NAMESPACES_PATTERN="${CI_K8S_NAMESPACES_PATTERN:-^(tfs|crdb|qdb|kafka|nats)}" +CI_MICROK8S_WAIT_ATTEMPTS="${CI_MICROK8S_WAIT_ATTEMPTS:-30}" +CI_MICROK8S_WAIT_SLEEP="${CI_MICROK8S_WAIT_SLEEP:-2}" +CI_MICROK8S_ADDON_WAIT_TIMEOUT="${CI_MICROK8S_ADDON_WAIT_TIMEOUT:-180s}" + +wait_for_kubectl() { + local counter=0 + until ${KUBECTL_CMD} get pods --all-namespaces >/dev/null 2>&1; do + printf "." + sleep "${CI_MICROK8S_WAIT_SLEEP}" + counter=$((counter + 1)) + if [[ "${counter}" -ge "${CI_MICROK8S_WAIT_ATTEMPTS}" ]]; then + echo "Kubernetes API did not become ready in time." >&2 + return 1 + fi + done + echo +} + +delete_pods_by_phase() { + local phase=$1 + ${KUBECTL_CMD} get pods --all-namespaces --no-headers --field-selector=status.phase="${phase}" \ + -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | + xargs --no-run-if-empty --max-args=2 ${KUBECTL_CMD} delete pod --namespace || true +} + +wait_for_addon_pods() { + local namespace=$1 + local label=$2 + if ! ${KUBECTL_CMD} get namespace "${namespace}" >/dev/null 2>&1; then + return 1 + fi + ${KUBECTL_CMD} wait --namespace "${namespace}" --for=condition=Ready pod \ + --selector "${label}" --timeout="${CI_MICROK8S_ADDON_WAIT_TIMEOUT}" +} + +wait_for_storage_ready() { + ${KUBECTL_CMD} rollout status deployment/hostpath-provisioner --namespace kube-system \ + --timeout="${CI_MICROK8S_ADDON_WAIT_TIMEOUT}" && return 0 + wait_for_addon_pods kube-system name=hostpath-provisioner && return 0 + wait_for_addon_pods kube-system app=hostpath-provisioner && return 0 + wait_for_addon_pods kube-system k8s-app=hostpath-provisioner && return 0 + echo "MicroK8s hostpath storage did not become ready." >&2 + return 1 +} + +wait_for_registry_ready() { + ${KUBECTL_CMD} rollout status deployment/registry --namespace container-registry \ + --timeout="${CI_MICROK8S_ADDON_WAIT_TIMEOUT}" && return 0 + wait_for_addon_pods container-registry app=registry && return 0 + echo "MicroK8s registry did not become ready." >&2 + return 1 +} + +can_reset_storage_addon() { + case "${CI_RESET_MICROK8S_STORAGE_ADDON}" in + yes) return 0 ;; + no) return 1 ;; + auto) + sudo -n true >/dev/null 2>&1 + return $? + ;; + *) + echo "Invalid CI_RESET_MICROK8S_STORAGE_ADDON=${CI_RESET_MICROK8S_STORAGE_ADDON}; use auto, yes, or no." >&2 + return 1 + ;; + esac +} + +echo "Checking MicroK8s readiness..." +${MICROK8S_CMD} status --wait-ready +wait_for_kubectl +${KUBECTL_CMD} get pods --all-namespaces + +echo "Deleting old TeraFlowSDN-related namespaces..." +K8S_NAMESPACES="$(${KUBECTL_CMD} get namespace -o jsonpath='{.items[*].metadata.name}')" +echo "K8S_NAMESPACES=${K8S_NAMESPACES}" + +OLD_NATS_NAMESPACES="$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats' || true)" +echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" +for ns in ${OLD_NATS_NAMESPACES}; do + if [[ "${ns}" == nats* ]]; then + if ${HELM_CMD} status "${ns}" --namespace "${ns}" >/dev/null 2>&1; then + ${HELM_CMD} uninstall "${ns}" --namespace "${ns}" + else + echo "Release '${ns}' not found, skipping..." + fi + fi +done + +OLD_NAMESPACES="$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E "${CI_K8S_NAMESPACES_PATTERN}" || true)" +echo "OLD_NAMESPACES=${OLD_NAMESPACES}" +if [[ -n "${OLD_NAMESPACES}" ]]; then + ${KUBECTL_CMD} delete namespace ${OLD_NAMESPACES} --ignore-not-found || true + for ns in ${OLD_NAMESPACES}; do + for _ in $(seq 1 "${CI_MICROK8S_WAIT_ATTEMPTS}"); do + ${KUBECTL_CMD} get namespace "${ns}" >/dev/null 2>&1 || break + sleep "${CI_MICROK8S_WAIT_SLEEP}" + done + done +fi + +echo "Deleting completed and failed Kubernetes pods..." +delete_pods_by_phase Failed +delete_pods_by_phase Succeeded + +if [[ "${CI_RESET_MICROK8S_STORAGE_REGISTRY}" != "yes" ]]; then + echo "Skipping MicroK8s storage/registry reset." + exit 0 +fi + +echo "Disabling MicroK8s registry addon..." +${MICROK8S_CMD} disable registry || true + +RESET_STORAGE_ADDON="no" +if can_reset_storage_addon; then + RESET_STORAGE_ADDON="yes" + echo "Disabling MicroK8s storage addon and destroying storage..." + ${MICROK8S_CMD} disable hostpath-storage:destroy-storage || \ + ${MICROK8S_CMD} disable storage:destroy-storage || \ + ${MICROK8S_CMD} disable hostpath-storage --destroy-storage || \ + ${MICROK8S_CMD} disable storage --destroy-storage || \ + ${MICROK8S_CMD} disable hostpath-storage || \ + ${MICROK8S_CMD} disable storage || true +else + echo "Skipping MicroK8s storage addon reset; non-interactive sudo is not available." + echo "Set CI_RESET_MICROK8S_STORAGE_ADDON=yes only on runners where MicroK8s can recreate hostpath storage non-interactively." +fi + +echo "Deleting leftover hostpath provisioner pods and jobs..." +if [[ "${RESET_STORAGE_ADDON}" == "yes" ]]; then + ${KUBECTL_CMD} delete pods --namespace kube-system --selector name=hostpath-provisioner --ignore-not-found || true + ${KUBECTL_CMD} delete pods --namespace kube-system --selector app=hostpath-provisioner --ignore-not-found || true + ${KUBECTL_CMD} delete pods --namespace kube-system --selector k8s-app=hostpath-provisioner --ignore-not-found || true +fi +${KUBECTL_CMD} get jobs --all-namespaces --no-headers \ + -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | + grep -E 'hostpath|provision' | + xargs --no-run-if-empty --max-args=2 ${KUBECTL_CMD} delete job --namespace || true + +if [[ "${RESET_STORAGE_ADDON}" == "yes" ]]; then + echo "Re-enabling MicroK8s storage addon..." + ${MICROK8S_CMD} enable hostpath-storage || ${MICROK8S_CMD} enable storage +fi + +echo "Re-enabling MicroK8s registry addon..." +${MICROK8S_CMD} enable registry + +echo "Waiting for storage and registry pods..." +${MICROK8S_CMD} status --wait-ready +wait_for_kubectl +wait_for_storage_ready +wait_for_registry_ready +${KUBECTL_CMD} get pods --all-namespaces diff --git a/scripts/dockerhub_k8s_secret.sh b/scripts/dockerhub_k8s_secret.sh new file mode 100644 index 000000000..6e83156da --- /dev/null +++ b/scripts/dockerhub_k8s_secret.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +NAMESPACE="$1" +SECRET_NAME="${DOCKERHUB_K8S_SECRET_NAME:-dockerhub-credentials}" +DOCKERHUB_REGISTRY="${DOCKERHUB_REGISTRY:-https://index.docker.io/v1/}" + +if [ -z "${NAMESPACE}" ]; then + echo "Usage: $0 " + exit 1 +fi + +if [ -z "${DOCKERHUB_USER_NAME:-}" ] || [ -z "${DOCKERHUB_ACCESS_TOKEN:-}" ]; then + echo "Docker Hub credentials not fully configured; Kubernetes namespace '${NAMESPACE}' will use anonymous image pulls." + exit 0 +fi + +if ! kubectl get namespace "${NAMESPACE}" >/dev/null 2>&1; then + echo "Kubernetes namespace '${NAMESPACE}' does not exist; skipping Docker Hub image pull secret." + exit 0 +fi + +for _ in $(seq 1 30); do + if kubectl get serviceaccount default --namespace "${NAMESPACE}" >/dev/null 2>&1; then + break + fi + sleep 1 +done + +if ! kubectl get serviceaccount default --namespace "${NAMESPACE}" >/dev/null 2>&1; then + echo "Default service account not found in namespace '${NAMESPACE}'; skipping Docker Hub image pull secret." + exit 0 +fi + +DOCKER_CONFIG_JSON="$(mktemp)" +trap 'rm -f "${DOCKER_CONFIG_JSON}"' EXIT + +AUTH="$(printf "%s:%s" "${DOCKERHUB_USER_NAME}" "${DOCKERHUB_ACCESS_TOKEN}" | base64 | tr -d '\n')" +cat > "${DOCKER_CONFIG_JSON}" </dev/null || true)" + if [ -z "${CREATED}" ]; then + continue + fi + + CREATED_EPOCH="$(date -u -d "${CREATED}" +%s)" + if [ "${CREATED_EPOCH}" -lt "${CUTOFF_EPOCH}" ]; then + echo "${IMAGE_REF}" >> "${IMAGE_REFS_TO_REMOVE}" + fi +done + +if [ ! -s "${IMAGE_REFS_TO_REMOVE}" ]; then + echo "No Docker images tagged 'mr[0-9]+' older than ${MAX_AGE_DAYS} days found." + exit 0 +fi + +echo "Removing Docker images tagged 'mr[0-9]+' older than ${MAX_AGE_DAYS} days:" +sort -u "${IMAGE_REFS_TO_REMOVE}" +sort -u "${IMAGE_REFS_TO_REMOVE}" | xargs --no-run-if-empty docker image rm --force diff --git a/src/analytics/.gitlab-ci.yml b/src/analytics/.gitlab-ci.yml index 336dfcc88..7f79e69a8 100644 --- a/src/analytics/.gitlab-ci.yml +++ b/src/analytics/.gitlab-ci.yml @@ -20,6 +20,7 @@ build analytics: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # This first build tags the builder resulting image to prevent being removed by dangling image removal command @@ -57,6 +58,7 @@ unit_test analytics-backend: needs: - build analytics before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep kafka; then docker rm -f kafka; else echo "Kafka container is not in the system"; fi @@ -125,6 +127,7 @@ unit_test analytics-frontend: needs: - build analytics before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep crdb; then docker rm -f crdb; else echo "CockroachDB container is not in the system"; fi diff --git a/src/automation/.gitlab-ci.yml b/src/automation/.gitlab-ci.yml index bef688e1a..88133a053 100644 --- a/src/automation/.gitlab-ci.yml +++ b/src/automation/.gitlab-ci.yml @@ -20,6 +20,7 @@ build automation: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/bgpls_speaker/.gitlab-ci.yml b/src/bgpls_speaker/.gitlab-ci.yml index 0cf29edbb..266dbe0cf 100644 --- a/src/bgpls_speaker/.gitlab-ci.yml +++ b/src/bgpls_speaker/.gitlab-ci.yml @@ -20,6 +20,7 @@ build bgpls_speaker: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/common/tests/MockServicerImpl_Context.py b/src/common/tests/MockServicerImpl_Context.py index e5b86bc58..d29cb8d3b 100644 --- a/src/common/tests/MockServicerImpl_Context.py +++ b/src/common/tests/MockServicerImpl_Context.py @@ -22,6 +22,8 @@ from common.proto.context_pb2 import ( Empty, EventTypeEnum, Link, LinkEvent, LinkId, LinkIdList, LinkList, OpticalLink, OpticalLinkList, + OpticalSpectrumReservation, OpticalSpectrumReservationId, OpticalSpectrumReservationList, + OpticalSpectrumReservationStatusEnum, Service, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList, Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList @@ -765,3 +767,125 @@ class MockServicerImpl_Context(ContextServiceServicer): LOGGER.debug('[DeleteOpticalLink] reply={:s}'.format(grpc_message_to_json_string(reply))) return reply + + # ----- Optical Spectrum Reservation ------------------------------------------------------------------------------ + + def _optical_spectrum_reservation_is_active(self, reservation : OpticalSpectrumReservation) -> bool: + return reservation.status in { + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED, + } + + def _optical_spectrum_reservation_ranges_overlap( + self, a_start : int, a_end : int, b_start : int, b_end : int + ) -> bool: + return a_start <= b_end and b_start <= a_end + + def _validate_optical_spectrum_reservation( + self, request : OpticalSpectrumReservation, container_name : str, context : grpc.ServicerContext + ) -> None: + reservation_uuid = request.reservation_id.reservation_uuid.uuid + topology_uuid = request.topology_id.topology_uuid.uuid + band = str(request.band) + n_start = int(request.n_start) + n_end = int(request.n_end) + requested_link_uuids = {link_id.link_uuid.uuid for link_id in request.optical_link_ids} + + for link_uuid in requested_link_uuids: + optical_link = self.obj_db.get_entry('optical_link', link_uuid, context) + slots = getattr(optical_link.optical_details, band) + for slot_index in range(n_start, n_end + 1): + if int(slots.get(str(slot_index), 1)) != 1: + context.abort( + grpc.StatusCode.ALREADY_EXISTS, + 'slot {:s}:{:d} is not available on optical link({:s})'.format( + band, slot_index, link_uuid + ) + ) + + for reservation in self.obj_db.get_entries(container_name): + if reservation.reservation_id.reservation_uuid.uuid == reservation_uuid: + continue + if reservation.topology_id.topology_uuid.uuid != topology_uuid: + continue + if reservation.band != band: + continue + if not self._optical_spectrum_reservation_is_active(reservation): + continue + existing_link_uuids = {link_id.link_uuid.uuid for link_id in reservation.optical_link_ids} + if len(requested_link_uuids.intersection(existing_link_uuids)) == 0: + continue + if self._optical_spectrum_reservation_ranges_overlap( + n_start, n_end, int(reservation.n_start), int(reservation.n_end) + ): + context.abort( + grpc.StatusCode.ALREADY_EXISTS, + 'OpticalSpectrumReservation({:s}) already exists; overlapping spectrum reservation'.format( + reservation.reservation_id.reservation_uuid.uuid + ) + ) + + def ListOpticalSpectrumReservations( + self, request : ContextId, context : grpc.ServicerContext + ) -> OpticalSpectrumReservationList: + LOGGER.debug('[ListOpticalSpectrumReservations] request={:s}'.format(grpc_message_to_json_string(request))) + reservations = self.obj_db.get_entries('optical_spectrum_reservation[{:s}]'.format( + str(request.context_uuid.uuid) + )) + reply = OpticalSpectrumReservationList(reservations=reservations) + LOGGER.debug('[ListOpticalSpectrumReservations] reply={:s}'.format(grpc_message_to_json_string(reply))) + return reply + + def GetOpticalSpectrumReservation( + self, request : OpticalSpectrumReservationId, context : grpc.ServicerContext + ) -> OpticalSpectrumReservation: + LOGGER.debug('[GetOpticalSpectrumReservation] request={:s}'.format(grpc_message_to_json_string(request))) + container_name = 'optical_spectrum_reservation[{:s}]'.format(str(request.context_id.context_uuid.uuid)) + reply = self.obj_db.get_entry(container_name, request.reservation_uuid.uuid, context) + LOGGER.debug('[GetOpticalSpectrumReservation] reply={:s}'.format(grpc_message_to_json_string(reply))) + return reply + + def SetOpticalSpectrumReservation( + self, request : OpticalSpectrumReservation, context : grpc.ServicerContext + ) -> OpticalSpectrumReservationId: + LOGGER.debug('[SetOpticalSpectrumReservation] request={:s}'.format(grpc_message_to_json_string(request))) + if request.status == OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_UNDEFINED: + request.status = OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED + container_name = 'optical_spectrum_reservation[{:s}]'.format( + str(request.reservation_id.context_id.context_uuid.uuid) + ) + self._validate_optical_spectrum_reservation(request, container_name, context) + reply, _ = self._set( + request, container_name, request.reservation_id.reservation_uuid.uuid, 'reservation_id', TOPIC_CONTEXT + ) + LOGGER.debug('[SetOpticalSpectrumReservation] reply={:s}'.format(grpc_message_to_json_string(reply))) + return reply + + def ConsumeOpticalSpectrumReservation( + self, request : OpticalSpectrumReservation, context : grpc.ServicerContext + ) -> OpticalSpectrumReservationId: + LOGGER.debug('[ConsumeOpticalSpectrumReservation] request={:s}'.format(grpc_message_to_json_string(request))) + container_name = 'optical_spectrum_reservation[{:s}]'.format( + str(request.reservation_id.context_id.context_uuid.uuid) + ) + reservation = self.obj_db.get_entry(container_name, request.reservation_id.reservation_uuid.uuid, context) + reservation.status = OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED + if request.HasField('service_id'): + reservation.service_id.CopyFrom(request.service_id) + if request.HasField('connection_id'): + reservation.connection_id.CopyFrom(request.connection_id) + LOGGER.debug('[ConsumeOpticalSpectrumReservation] reply={:s}'.format( + grpc_message_to_json_string(reservation.reservation_id) + )) + return reservation.reservation_id + + def ReleaseOpticalSpectrumReservation( + self, request : OpticalSpectrumReservationId, context : grpc.ServicerContext + ) -> Empty: + LOGGER.debug('[ReleaseOpticalSpectrumReservation] request={:s}'.format(grpc_message_to_json_string(request))) + container_name = 'optical_spectrum_reservation[{:s}]'.format(str(request.context_id.context_uuid.uuid)) + reservation = self.obj_db.get_entry(container_name, request.reservation_uuid.uuid, context) + reservation.status = OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED + reply = Empty() + LOGGER.debug('[ReleaseOpticalSpectrumReservation] reply={:s}'.format(grpc_message_to_json_string(reply))) + return reply diff --git a/src/common/tools/rest_conf/client/RestConfClient.py b/src/common/tools/rest_conf/client/RestConfClient.py index 4f99c0736..685e3e327 100644 --- a/src/common/tools/rest_conf/client/RestConfClient.py +++ b/src/common/tools/rest_conf/client/RestConfClient.py @@ -26,7 +26,7 @@ class RestConfClient(RestApiClient): username : Optional[str] = None, password : Optional[str] = None, restconf_version : Optional[str] = None, timeout : int = 30, verify_certs : bool = True, allow_redirects : bool = True, - logger : Optional[logging.Logger] = None + logger : Optional[logging.Logger] = None, **kwargs ) -> None: super().__init__( address, port=port, scheme=scheme, username=username, password=password, diff --git a/src/context/.gitlab-ci.yml b/src/context/.gitlab-ci.yml index 6a60c5bd4..7dc431fcf 100644 --- a/src/context/.gitlab-ci.yml +++ b/src/context/.gitlab-ci.yml @@ -20,6 +20,7 @@ build context: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test context: needs: - build context before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep crdb; then docker rm -f crdb; else echo "CockroachDB container is not in the system"; fi diff --git a/src/context/client/ContextClient.py b/src/context/client/ContextClient.py index e85e99ad3..08bc91cad 100644 --- a/src/context/client/ContextClient.py +++ b/src/context/client/ContextClient.py @@ -28,7 +28,8 @@ from common.proto.context_pb2 import ( Service, ServiceConfigRule, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList, Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList, Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList, - OpticalBand, OpticalBandId, OpticalBandList + OpticalBand, OpticalBandId, OpticalBandList, + OpticalSpectrumReservation, OpticalSpectrumReservationId, OpticalSpectrumReservationList ) from common.proto.context_pb2_grpc import ContextServiceStub from common.proto.context_policy_pb2_grpc import ContextPolicyServiceStub @@ -513,6 +514,41 @@ class ContextClient: response = self.stub.SetOpticalBand(request) LOGGER.debug('SetOpticalBand result: {:s}'.format(grpc_message_to_json_string(response))) return response + + @RETRY_DECORATOR + def SetOpticalSpectrumReservation(self, request : OpticalSpectrumReservation) -> OpticalSpectrumReservationId: + LOGGER.debug('SetOpticalSpectrumReservation request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.SetOpticalSpectrumReservation(request) + LOGGER.debug('SetOpticalSpectrumReservation result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def GetOpticalSpectrumReservation(self, request : OpticalSpectrumReservationId) -> OpticalSpectrumReservation: + LOGGER.debug('GetOpticalSpectrumReservation request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetOpticalSpectrumReservation(request) + LOGGER.debug('GetOpticalSpectrumReservation result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def ListOpticalSpectrumReservations(self, request : ContextId) -> OpticalSpectrumReservationList: + LOGGER.debug('ListOpticalSpectrumReservations request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListOpticalSpectrumReservations(request) + LOGGER.debug('ListOpticalSpectrumReservations result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def ConsumeOpticalSpectrumReservation(self, request : OpticalSpectrumReservation) -> OpticalSpectrumReservationId: + LOGGER.debug('ConsumeOpticalSpectrumReservation request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ConsumeOpticalSpectrumReservation(request) + LOGGER.debug('ConsumeOpticalSpectrumReservation result: {:s}'.format(grpc_message_to_json_string(response))) + return response + + @RETRY_DECORATOR + def ReleaseOpticalSpectrumReservation(self, request : OpticalSpectrumReservationId) -> Empty: + LOGGER.debug('ReleaseOpticalSpectrumReservation request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ReleaseOpticalSpectrumReservation(request) + LOGGER.debug('ReleaseOpticalSpectrumReservation result: {:s}'.format(grpc_message_to_json_string(response))) + return response #--------------------------- Optical Link ------------------------ def GetOpticalLinkList(self, request: Empty) -> OpticalLinkList: diff --git a/src/context/service/ContextServiceServicerImpl.py b/src/context/service/ContextServiceServicerImpl.py index 99ef84617..514e8f67f 100644 --- a/src/context/service/ContextServiceServicerImpl.py +++ b/src/context/service/ContextServiceServicerImpl.py @@ -25,7 +25,8 @@ from common.proto.context_pb2 import ( Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList, Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList, OpticalConfigList, OpticalConfigId, OpticalConfig, OpticalLink, OpticalLinkList, - OpticalBand, OpticalBandId, OpticalBandList + OpticalBand, OpticalBandId, OpticalBandList, + OpticalSpectrumReservation, OpticalSpectrumReservationId, OpticalSpectrumReservationList ) from common.proto.policy_pb2 import PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule from common.proto.context_pb2_grpc import ContextServiceServicer @@ -72,6 +73,11 @@ from .database.OpticalConfig import ( from .database.OpticalLink import ( optical_link_delete, optical_link_get, optical_link_list_objs, optical_link_set ) +from .database.OpticalSpectrumReservation import ( + optical_spectrum_reservation_consume, optical_spectrum_reservation_get, + optical_spectrum_reservation_list, optical_spectrum_reservation_release, + optical_spectrum_reservation_set +) LOGGER = logging.getLogger(__name__) @@ -381,6 +387,36 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer result = set_optical_band(self.db_engine, request) return Empty() + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def SetOpticalSpectrumReservation( + self, request : OpticalSpectrumReservation, context : grpc.ServicerContext + ) -> OpticalSpectrumReservationId: + return optical_spectrum_reservation_set(self.db_engine, request) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetOpticalSpectrumReservation( + self, request : OpticalSpectrumReservationId, context : grpc.ServicerContext + ) -> OpticalSpectrumReservation: + return optical_spectrum_reservation_get(self.db_engine, request) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def ListOpticalSpectrumReservations( + self, request : ContextId, context : grpc.ServicerContext + ) -> OpticalSpectrumReservationList: + return optical_spectrum_reservation_list(self.db_engine, request) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def ConsumeOpticalSpectrumReservation( + self, request : OpticalSpectrumReservation, context : grpc.ServicerContext + ) -> OpticalSpectrumReservationId: + return optical_spectrum_reservation_consume(self.db_engine, request) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def ReleaseOpticalSpectrumReservation( + self, request : OpticalSpectrumReservationId, context : grpc.ServicerContext + ) -> Empty: + return optical_spectrum_reservation_release(self.db_engine, request) + #--------------------- Experimental Optical Link ------------------- diff --git a/src/context/service/database/ConfigRule.py b/src/context/service/database/ConfigRule.py index d9f6b06cb..04d6b837f 100644 --- a/src/context/service/database/ConfigRule.py +++ b/src/context/service/database/ConfigRule.py @@ -38,6 +38,9 @@ def compose_config_rules_data( dict_config_rules : List[Dict] = list() for position,config_rule in enumerate(config_rules): str_kind = config_rule.WhichOneof('config_rule') + if device_uuid is not None and str_kind == 'custom': + if '/inventory' in config_rule.custom.resource_key: + continue kind = ConfigRuleKindEnum._member_map_.get(str_kind.upper()) # pylint: disable=no-member dict_config_rule = { 'position' : position, diff --git a/src/context/service/database/Device.py b/src/context/service/database/Device.py index bff03a0a5..145d917af 100644 --- a/src/context/service/database/Device.py +++ b/src/context/service/database/Device.py @@ -31,6 +31,7 @@ from .models.DeviceModel import DeviceModel from .models.EndPointModel import EndPointModel from .models.ComponentModel import ComponentModel from .models.TopologyModel import TopologyDeviceModel, TopologyModel +from .models.ConfigRuleModel import DeviceConfigRuleModel, ConfigRuleKindEnum from .models.enums.DeviceDriver import grpc_to_enum__device_driver from .models.enums.DeviceOperationalStatus import grpc_to_enum__device_operational_status from .models.enums.KpiSampleType import grpc_to_enum__kpi_sample_type @@ -243,6 +244,9 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi device_topology_ids = [obj.dump_id() for obj in device_topologies] #LOGGER.warning('device_topology_ids={:s}'.format(str(device_topology_ids))) + # Delete old components of the device to make sure they are fully updated + session.query(ComponentModel).filter_by(device_uuid=device_uuid).delete() + updated_components = False if len(components_data) > 0: @@ -261,6 +265,13 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi component_updates = session.execute(stmt).fetchall() updated_components = any([(updated_at > created_at) for created_at,updated_at in component_updates]) + # Delete old /inventory config rules of the device to make sure they are fully updated + session.query(DeviceConfigRuleModel).filter( + DeviceConfigRuleModel.device_uuid == device_uuid, + DeviceConfigRuleModel.kind == ConfigRuleKindEnum.CUSTOM, + DeviceConfigRuleModel.data.contains('/inventory') + ).delete(synchronize_session=False) + changed_config_rules = upsert_config_rules(session, config_rules, device_uuid=device_uuid) return updated or updated_endpoints or updated_components or changed_config_rules, device_topology_ids @@ -332,7 +343,7 @@ def device_select(db_engine : Engine, request : DeviceFilter) -> DeviceList: query = session.query(DeviceModel) if request.include_endpoints : query = query.options(selectinload(DeviceModel.endpoints)) if request.include_config_rules: query = query.options(selectinload(DeviceModel.config_rules)) - #if request.include_components : query = query.options(selectinload(DeviceModel.components)) + if request.include_components : query = query.options(selectinload(DeviceModel.components)) obj_list : List[DeviceModel] = query.filter(DeviceModel.device_uuid.in_(device_uuids)).all() return [obj.dump(**dump_params) for obj in obj_list] devices = run_transaction(sessionmaker(bind=db_engine), callback) diff --git a/src/context/service/database/OpticalSpectrumReservation.py b/src/context/service/database/OpticalSpectrumReservation.py new file mode 100644 index 000000000..aa5eb1362 --- /dev/null +++ b/src/context/service/database/OpticalSpectrumReservation.py @@ -0,0 +1,337 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import datetime, json, logging +from sqlalchemy.dialects.postgresql import insert +from sqlalchemy.engine import Engine +from sqlalchemy.orm import Session, sessionmaker +from sqlalchemy_cockroachdb import run_transaction +from typing import Dict, List, Optional, Set +from common.method_wrappers.ServiceExceptions import AlreadyExistsException, InvalidArgumentException, NotFoundException +from common.proto.context_pb2 import ( + ContextId, Empty, OpticalSpectrumReservation, OpticalSpectrumReservationId, OpticalSpectrumReservationList, + OpticalSpectrumReservationStatusEnum +) +from .models.OpticalLinkModel import OpticalLinkModel +from .models.OpticalSpectrumReservationModel import OpticalSpectrumReservationModel +from .models.TopologyModel import TopologyOpticalLinkModel +from .uuids._Builder import get_uuid_from_string, get_uuid_random +from .uuids.Context import context_get_uuid +from .uuids.Link import link_get_uuid +from .uuids.Service import service_get_uuid +from .uuids.Topology import topology_get_uuid + +LOGGER = logging.getLogger(__name__) + +ACTIVE_STATUSES = { + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED, +} + +TERMINAL_STATUSES = { + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_EXPIRED, +} + +VALID_BANDS = {'c_slots', 'l_slots', 's_slots'} + + +def _now() -> datetime.datetime: + return datetime.datetime.now(datetime.timezone.utc) + + +def _timestamp_to_datetime(timestamp) -> Optional[datetime.datetime]: + if timestamp.timestamp <= 0: + return None + return datetime.datetime.fromtimestamp(timestamp.timestamp, tz=datetime.timezone.utc) + + +def _reservation_get_uuid(request : OpticalSpectrumReservationId, allow_random : bool = False) -> str: + raw_reservation_uuid = request.reservation_uuid.uuid + if len(raw_reservation_uuid) > 0: + return get_uuid_from_string(raw_reservation_uuid) + if allow_random: + return get_uuid_random() + raise InvalidArgumentException('reservation_id.reservation_uuid.uuid', raw_reservation_uuid) + + +def _normalize_band(band : str) -> str: + normalized_band = str(band).strip().lower().replace('-', '_') + if normalized_band in {'c', 'c_band', 'c_slots'}: + return 'c_slots' + if normalized_band in {'l', 'l_band', 'l_slots'}: + return 'l_slots' + if normalized_band in {'s', 's_band', 's_slots'}: + return 's_slots' + raise InvalidArgumentException('band', str(band)) + + +def _normalize_link_uuids(request : OpticalSpectrumReservation) -> List[str]: + link_uuids = [ + link_get_uuid(link_id, allow_random=False) + for link_id in request.optical_link_ids + ] + if len(link_uuids) == 0: + raise InvalidArgumentException('optical_link_ids', '[]') + return sorted(set(link_uuids)) + + +def _normalize_status(status : int) -> int: + if status == OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_UNDEFINED: + return OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED + if status in { + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_EXPIRED, + }: + return status + raise InvalidArgumentException('status', str(status)) + + +def _service_uuid(request : OpticalSpectrumReservation) -> Optional[str]: + if not request.HasField('service_id'): + return None + if len(request.service_id.service_uuid.uuid) == 0: + return None + _, service_uuid = service_get_uuid(request.service_id, allow_random=False) + return service_uuid + + +def _connection_uuid(request : OpticalSpectrumReservation) -> Optional[str]: + if not request.HasField('connection_id'): + return None + raw_connection_uuid = request.connection_id.connection_uuid.uuid + if len(raw_connection_uuid) == 0: + return None + return get_uuid_from_string(raw_connection_uuid) + + +def _ranges_overlap(a_start : int, a_end : int, b_start : int, b_end : int) -> bool: + return a_start <= b_end and b_start <= a_end + + +def _is_expired(obj : OpticalSpectrumReservationModel, now : datetime.datetime) -> bool: + return obj.expires_at is not None and obj.expires_at <= now + + +def _conflicts( + obj : OpticalSpectrumReservationModel, reservation_uuid : str, context_uuid : str, topology_uuid : str, + link_uuids : Set[str], band : str, n_start : int, n_end : int, now : datetime.datetime +) -> bool: + if obj.reservation_uuid == reservation_uuid: + return False + if obj.context_uuid != context_uuid or obj.topology_uuid != topology_uuid: + return False + if obj.band != band: + return False + if obj.status not in ACTIVE_STATUSES or _is_expired(obj, now): + return False + if len(link_uuids.intersection(obj.get_optical_link_uuids())) == 0: + return False + return _ranges_overlap(n_start, n_end, obj.n_start, obj.n_end) + + +def _validate_optical_link_slots( + session : Session, topology_uuid : str, link_uuids : List[str], band : str, n_start : int, n_end : int +) -> None: + optical_links : List[OpticalLinkModel] = session.query(OpticalLinkModel)\ + .filter(OpticalLinkModel.opticallink_uuid.in_(link_uuids)).all() + optical_link_by_uuid = {optical_link.opticallink_uuid: optical_link for optical_link in optical_links} + + for link_uuid in link_uuids: + if link_uuid not in optical_link_by_uuid: + raise NotFoundException('OpticalLink', link_uuid) + + topology_link_rows : List[TopologyOpticalLinkModel] = session.query(TopologyOpticalLinkModel)\ + .filter(TopologyOpticalLinkModel.topology_uuid == topology_uuid)\ + .filter(TopologyOpticalLinkModel.optical_link_uuid.in_(link_uuids)).all() + topology_link_uuids = {topology_link.optical_link_uuid for topology_link in topology_link_rows} + + missing_topology_links = sorted(set(link_uuids) - topology_link_uuids) + if len(missing_topology_links) > 0: + raise InvalidArgumentException( + 'optical_link_ids', str(missing_topology_links), + extra_details='optical links are not part of the requested topology' + ) + + for link_uuid in link_uuids: + optical_link = optical_link_by_uuid[link_uuid] + slots = getattr(optical_link, band) + if slots is None: + raise AlreadyExistsException( + 'OpticalSpectrumReservation', link_uuid, + extra_details='requested band {:s} is not available on optical link'.format(band) + ) + for slot_index in range(n_start, n_end + 1): + if int(slots.get(str(slot_index), 0)) != 1: + raise AlreadyExistsException( + 'OpticalSpectrumReservation', link_uuid, + extra_details='slot {:s}:{:d} is not available on optical link'.format(band, slot_index) + ) + + +def optical_spectrum_reservation_set( + db_engine : Engine, request : OpticalSpectrumReservation +) -> OpticalSpectrumReservationId: + context_uuid = context_get_uuid(request.reservation_id.context_id, allow_random=False, allow_default=True) + reservation_uuid = _reservation_get_uuid(request.reservation_id, allow_random=True) + topology_context_uuid, topology_uuid = topology_get_uuid(request.topology_id, allow_random=False, allow_default=True) + if topology_context_uuid != context_uuid: + raise InvalidArgumentException('topology_id.context_id', topology_context_uuid) + + band = _normalize_band(request.band) + n_start = int(request.n_start) + n_end = int(request.n_end) + if n_end < n_start: + raise InvalidArgumentException('n_end', str(n_end), extra_details='n_end must be >= n_start') + required_slots = int(request.required_slots) + if required_slots < 0: + raise InvalidArgumentException('required_slots', str(required_slots)) + + link_uuids = _normalize_link_uuids(request) + now = _now() + expires_at = _timestamp_to_datetime(request.expires_at) + status = _normalize_status(request.status) + data = { + 'reservation_uuid': reservation_uuid, + 'context_uuid': context_uuid, + 'topology_uuid': topology_uuid, + 'optical_link_uuids': json.dumps(link_uuids), + 'band': band, + 'n_start': n_start, + 'n_end': n_end, + 'required_slots': required_slots, + 'service_uuid': _service_uuid(request), + 'connection_uuid': _connection_uuid(request), + 'owner_id': request.owner_id or None, + 'correlation_id': request.correlation_id or None, + 'status': status, + 'created_at': now, + 'updated_at': now, + 'expires_at': expires_at, + } + + def callback(session : Session) -> Dict: + _validate_optical_link_slots(session, topology_uuid, link_uuids, band, n_start, n_end) + + active_objects : List[OpticalSpectrumReservationModel] = session.query(OpticalSpectrumReservationModel).all() + for obj in active_objects: + if _conflicts(obj, reservation_uuid, context_uuid, topology_uuid, set(link_uuids), band, n_start, n_end, now): + raise AlreadyExistsException( + 'OpticalSpectrumReservation', obj.reservation_uuid, + extra_details='overlapping spectrum reservation' + ) + + stmt = insert(OpticalSpectrumReservationModel).values([data]) + stmt = stmt.on_conflict_do_update( + index_elements=[OpticalSpectrumReservationModel.reservation_uuid], + set_=dict( + context_uuid=stmt.excluded.context_uuid, + topology_uuid=stmt.excluded.topology_uuid, + optical_link_uuids=stmt.excluded.optical_link_uuids, + band=stmt.excluded.band, + n_start=stmt.excluded.n_start, + n_end=stmt.excluded.n_end, + required_slots=stmt.excluded.required_slots, + service_uuid=stmt.excluded.service_uuid, + connection_uuid=stmt.excluded.connection_uuid, + owner_id=stmt.excluded.owner_id, + correlation_id=stmt.excluded.correlation_id, + status=stmt.excluded.status, + updated_at=stmt.excluded.updated_at, + expires_at=stmt.excluded.expires_at, + ) + ) + session.execute(stmt) + return {'context_id': {'context_uuid': {'uuid': context_uuid}}, 'reservation_uuid': {'uuid': reservation_uuid}} + + reservation_id = run_transaction(sessionmaker(bind=db_engine), callback) + return OpticalSpectrumReservationId(**reservation_id) + + +def optical_spectrum_reservation_get( + db_engine : Engine, request : OpticalSpectrumReservationId +) -> OpticalSpectrumReservation: + context_uuid = context_get_uuid(request.context_id, allow_random=False, allow_default=True) + reservation_uuid = _reservation_get_uuid(request) + + def callback(session : Session) -> Optional[Dict]: + obj : Optional[OpticalSpectrumReservationModel] = session.query(OpticalSpectrumReservationModel)\ + .filter_by(context_uuid=context_uuid, reservation_uuid=reservation_uuid).one_or_none() + return None if obj is None else obj.dump() + + obj = run_transaction(sessionmaker(bind=db_engine), callback) + if obj is None: + raise NotFoundException('OpticalSpectrumReservation', reservation_uuid) + return OpticalSpectrumReservation(**obj) + + +def optical_spectrum_reservation_list( + db_engine : Engine, request : ContextId +) -> OpticalSpectrumReservationList: + context_uuid = context_get_uuid(request, allow_random=False, allow_default=True) + + def callback(session : Session) -> List[Dict]: + obj_list : List[OpticalSpectrumReservationModel] = session.query(OpticalSpectrumReservationModel)\ + .filter_by(context_uuid=context_uuid).all() + return [obj.dump() for obj in obj_list] + + reservations = run_transaction(sessionmaker(bind=db_engine), callback) + return OpticalSpectrumReservationList(reservations=reservations) + + +def _set_status( + db_engine : Engine, request : OpticalSpectrumReservationId, status : int, + service_uuid : Optional[str] = None, connection_uuid : Optional[str] = None +) -> OpticalSpectrumReservationId: + context_uuid = context_get_uuid(request.context_id, allow_random=False, allow_default=True) + reservation_uuid = _reservation_get_uuid(request) + now = _now() + + def callback(session : Session) -> Dict: + obj : Optional[OpticalSpectrumReservationModel] = session.query(OpticalSpectrumReservationModel)\ + .filter_by(context_uuid=context_uuid, reservation_uuid=reservation_uuid).one_or_none() + if obj is None: + raise NotFoundException('OpticalSpectrumReservation', reservation_uuid) + obj.status = status + obj.updated_at = now + if service_uuid is not None: + obj.service_uuid = service_uuid + if connection_uuid is not None: + obj.connection_uuid = connection_uuid + return obj.dump_id() + + reservation_id = run_transaction(sessionmaker(bind=db_engine), callback) + return OpticalSpectrumReservationId(**reservation_id) + + +def optical_spectrum_reservation_consume( + db_engine : Engine, request : OpticalSpectrumReservation +) -> OpticalSpectrumReservationId: + return _set_status( + db_engine, request.reservation_id, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED, + service_uuid=_service_uuid(request), connection_uuid=_connection_uuid(request) + ) + + +def optical_spectrum_reservation_release( + db_engine : Engine, request : OpticalSpectrumReservationId +) -> Empty: + _set_status( + db_engine, request, + OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED + ) + return Empty() diff --git a/src/context/service/database/models/OpticalSpectrumReservationModel.py b/src/context/service/database/models/OpticalSpectrumReservationModel.py new file mode 100644 index 000000000..557af3373 --- /dev/null +++ b/src/context/service/database/models/OpticalSpectrumReservationModel.py @@ -0,0 +1,93 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +from typing import Dict, List, Optional +from sqlalchemy import CheckConstraint, Column, DateTime, ForeignKey, Integer, String +from sqlalchemy.dialects.postgresql import UUID +from ._Base import _Base + + +class OpticalSpectrumReservationModel(_Base): + __tablename__ = 'optical_spectrum_reservation' + + reservation_uuid = Column(UUID(as_uuid=False), primary_key=True) + context_uuid = Column(ForeignKey('context.context_uuid', ondelete='CASCADE'), nullable=False, index=True) + topology_uuid = Column(UUID(as_uuid=False), nullable=False, index=True) + optical_link_uuids = Column(String, nullable=False) + band = Column(String, nullable=False) + n_start = Column(Integer, nullable=False) + n_end = Column(Integer, nullable=False) + required_slots = Column(Integer, nullable=False) + service_uuid = Column(UUID(as_uuid=False), nullable=True, index=True) + connection_uuid = Column(UUID(as_uuid=False), nullable=True, index=True) + owner_id = Column(String, nullable=True) + correlation_id = Column(String, nullable=True) + status = Column(Integer, nullable=False) + created_at = Column(DateTime, nullable=False) + updated_at = Column(DateTime, nullable=False) + expires_at = Column(DateTime, nullable=True) + + __table_args__ = ( + CheckConstraint(n_start >= 0, name='check_n_start_value'), + CheckConstraint(n_end >= n_start, name='check_n_end_value'), + CheckConstraint(required_slots >= 0, name='check_required_slots_value'), + ) + + def get_optical_link_uuids(self) -> List[str]: + return json.loads(self.optical_link_uuids) + + def dump_id(self) -> Dict: + return { + 'context_id': {'context_uuid': {'uuid': self.context_uuid}}, + 'reservation_uuid': {'uuid': self.reservation_uuid}, + } + + def _dump_optional_timestamp(self, value) -> Optional[Dict]: + if value is None: + return None + return {'timestamp': value.timestamp()} + + def dump(self) -> Dict: + result = { + 'reservation_id': self.dump_id(), + 'topology_id': { + 'context_id': {'context_uuid': {'uuid': self.context_uuid}}, + 'topology_uuid': {'uuid': self.topology_uuid}, + }, + 'optical_link_ids': [ + {'link_uuid': {'uuid': optical_link_uuid}} + for optical_link_uuid in self.get_optical_link_uuids() + ], + 'band': self.band, + 'n_start': self.n_start, + 'n_end': self.n_end, + 'required_slots': self.required_slots, + 'owner_id': self.owner_id or '', + 'correlation_id': self.correlation_id or '', + 'status': self.status, + 'created_at': {'timestamp': self.created_at.timestamp()}, + 'updated_at': {'timestamp': self.updated_at.timestamp()}, + } + if self.service_uuid is not None: + result['service_id'] = { + 'context_id': {'context_uuid': {'uuid': self.context_uuid}}, + 'service_uuid': {'uuid': self.service_uuid}, + } + if self.connection_uuid is not None: + result['connection_id'] = {'connection_uuid': {'uuid': self.connection_uuid}} + expires_at = self._dump_optional_timestamp(self.expires_at) + if expires_at is not None: + result['expires_at'] = expires_at + return result diff --git a/src/context/tests/test_optical_spectrum_reservation.py b/src/context/tests/test_optical_spectrum_reservation.py new file mode 100644 index 000000000..9dfa606c5 --- /dev/null +++ b/src/context/tests/test_optical_spectrum_reservation.py @@ -0,0 +1,201 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import datetime, grpc, pytest +from sqlalchemy.orm import sessionmaker +from common.proto.context_pb2 import ( + Context, ContextId, LinkId, OpticalSpectrumReservation, OpticalSpectrumReservationId, + OpticalSpectrumReservationStatusEnum, ServiceId, Topology, TopologyId +) +from common.tools.object_factory.Context import json_context, json_context_id +from common.tools.object_factory.Link import json_link_id +from common.tools.object_factory.Service import json_service_id +from common.tools.object_factory.Topology import json_topology, json_topology_id +from context.client.ContextClient import ContextClient +from context.service.database.uuids.Context import context_get_uuid +from context.service.database.uuids.Link import link_get_uuid +from context.service.database.uuids.Service import service_get_uuid +from context.service.database.uuids.Topology import topology_get_uuid +from context.service.database.models.OpticalLinkModel import OpticalLinkModel +from context.service.database.models.TopologyModel import TopologyOpticalLinkModel + + +CONTEXT_ID = json_context_id('spectrum-admin') +TOPOLOGY_ID = json_topology_id('spectrum-topology', context_id=CONTEXT_ID) +LINK_1_ID = json_link_id('roadm-a-roadm-b') +LINK_2_ID = json_link_id('roadm-b-roadm-c') + + +def _slot_map(available_slots): + return {str(slot_index): 1 for slot_index in available_slots} + + +def _set_context_topology(context_client : ContextClient) -> None: + context_client.SetContext(Context(**json_context('spectrum-admin', name='spectrum-admin'))) + context_client.SetTopology(Topology(**json_topology('spectrum-topology', context_id=CONTEXT_ID))) + + +def _set_optical_link(context_db_mb, link_name : str, available_slots=None, topology_id=None): + if available_slots is None: + available_slots = range(0, 80) + if topology_id is None: + topology_id = TOPOLOGY_ID + + link_id = LinkId(**json_link_id(link_name)) + link_uuid = link_get_uuid(link_id, allow_random=False) + _, topology_uuid = topology_get_uuid(TopologyId(**topology_id), allow_random=False) + now = datetime.datetime.now(datetime.timezone.utc) + + db_engine, _ = context_db_mb + Session = sessionmaker(bind=db_engine) + with Session() as session: + optical_link = session.query(OpticalLinkModel).filter_by(opticallink_uuid=link_uuid).one_or_none() + if optical_link is None: + optical_link = OpticalLinkModel( + opticallink_uuid=link_uuid, + name=link_name, + created_at=now, + ) + session.add(optical_link) + optical_link.updated_at = now + optical_link.length = 1 + optical_link.src_port = 'src' + optical_link.dst_port = 'dst' + optical_link.local_peer_port = 'local' + optical_link.remote_peer_port = 'remote' + optical_link.used = False + optical_link.c_slots = _slot_map(available_slots) + optical_link.l_slots = {} + optical_link.s_slots = {} + + topology_link = session.query(TopologyOpticalLinkModel)\ + .filter_by(topology_uuid=topology_uuid, optical_link_uuid=link_uuid).one_or_none() + if topology_link is None: + session.add(TopologyOpticalLinkModel(topology_uuid=topology_uuid, optical_link_uuid=link_uuid)) + session.commit() + + return link_id + + +def _reservation(name, n_start, n_end, link_ids=None, topology_id=None): + if link_ids is None: + link_ids = [LINK_1_ID, LINK_2_ID] + if topology_id is None: + topology_id = TOPOLOGY_ID + return OpticalSpectrumReservation( + reservation_id=OpticalSpectrumReservationId( + context_id=ContextId(**CONTEXT_ID), + reservation_uuid={'uuid': name}, + ), + topology_id=topology_id, + optical_link_ids=[LinkId(**link_id) for link_id in link_ids], + band='c_slots', + n_start=n_start, + n_end=n_end, + required_slots=(n_end - n_start + 1), + owner_id='pytest', + correlation_id=name, + ) + + +def test_optical_spectrum_reservation_lifecycle(context_client : ContextClient, context_db_mb) -> None: + _set_context_topology(context_client) + link_1_id = _set_optical_link(context_db_mb, 'roadm-a-roadm-b') + link_2_id = _set_optical_link(context_db_mb, 'roadm-b-roadm-c') + + context_uuid = context_get_uuid(ContextId(**CONTEXT_ID), allow_random=False) + _, topology_uuid = topology_get_uuid(Topology(**json_topology('spectrum-topology', context_id=CONTEXT_ID)).topology_id) + link_1_uuid = link_get_uuid(link_1_id, allow_random=False) + link_2_uuid = link_get_uuid(link_2_id, allow_random=False) + + reservation = _reservation('reservation-a', 10, 25) + reservation_id = context_client.SetOpticalSpectrumReservation(reservation) + + stored = context_client.GetOpticalSpectrumReservation(reservation_id) + assert stored.reservation_id.context_id.context_uuid.uuid == context_uuid + assert stored.topology_id.topology_uuid.uuid == topology_uuid + assert stored.band == 'c_slots' + assert stored.n_start == 10 + assert stored.n_end == 25 + assert stored.required_slots == 16 + assert stored.status == OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED + assert {link_id.link_uuid.uuid for link_id in stored.optical_link_ids} == {link_1_uuid, link_2_uuid} + + reservations = context_client.ListOpticalSpectrumReservations(ContextId(**CONTEXT_ID)) + assert len(reservations.reservations) == 1 + + with pytest.raises(grpc.RpcError) as e: + context_client.SetOpticalSpectrumReservation(_reservation('reservation-overlap', 20, 30)) + assert e.value.code() == grpc.StatusCode.ALREADY_EXISTS + + non_overlapping_id = context_client.SetOpticalSpectrumReservation(_reservation('reservation-b', 26, 41)) + non_overlapping = context_client.GetOpticalSpectrumReservation(non_overlapping_id) + assert non_overlapping.status == OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED + + service_id = ServiceId(**json_service_id('optical-service-a', context_id=CONTEXT_ID)) + stored.service_id.CopyFrom(service_id) + consumed_id = context_client.ConsumeOpticalSpectrumReservation(stored) + consumed = context_client.GetOpticalSpectrumReservation(consumed_id) + _, service_uuid = service_get_uuid(service_id, allow_random=False) + assert consumed.status == OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED + assert consumed.service_id.service_uuid.uuid == service_uuid + + context_client.ReleaseOpticalSpectrumReservation(consumed_id) + released = context_client.GetOpticalSpectrumReservation(consumed_id) + assert released.status == OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED + + replacement_id = context_client.SetOpticalSpectrumReservation(_reservation('reservation-replacement', 10, 25)) + replacement = context_client.GetOpticalSpectrumReservation(replacement_id) + assert replacement.status == OpticalSpectrumReservationStatusEnum.OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED + + +def test_optical_spectrum_reservation_rejects_missing_optical_link(context_client : ContextClient) -> None: + _set_context_topology(context_client) + + with pytest.raises(grpc.RpcError) as e: + context_client.SetOpticalSpectrumReservation(_reservation( + 'reservation-missing-link', 10, 25, link_ids=[json_link_id('missing-optical-link')] + )) + assert e.value.code() == grpc.StatusCode.NOT_FOUND + + +def test_optical_spectrum_reservation_rejects_link_outside_topology(context_client : ContextClient, context_db_mb) -> None: + _set_context_topology(context_client) + context_client.SetTopology(Topology(**json_topology('other-topology', context_id=CONTEXT_ID))) + link_id = _set_optical_link(context_db_mb, 'roadm-outside-topology') + other_topology_id = json_topology_id('other-topology', context_id=CONTEXT_ID) + + with pytest.raises(grpc.RpcError) as e: + context_client.SetOpticalSpectrumReservation(_reservation( + 'reservation-outside-topology', 10, 25, + link_ids=[{'link_uuid': {'uuid': link_id.link_uuid.uuid}}], + topology_id=other_topology_id, + )) + assert e.value.code() == grpc.StatusCode.INVALID_ARGUMENT + + +def test_optical_spectrum_reservation_rejects_occupied_optical_link_slot( + context_client : ContextClient, context_db_mb +) -> None: + _set_context_topology(context_client) + link_id = _set_optical_link( + context_db_mb, 'roadm-occupied-slots', available_slots=list(range(0, 12)) + list(range(13, 80)) + ) + + with pytest.raises(grpc.RpcError) as e: + context_client.SetOpticalSpectrumReservation(_reservation( + 'reservation-occupied-slot', 10, 25, + link_ids=[{'link_uuid': {'uuid': link_id.link_uuid.uuid}}], + )) + assert e.value.code() == grpc.StatusCode.ALREADY_EXISTS diff --git a/src/dbscanserving/.gitlab-ci.yml b/src/dbscanserving/.gitlab-ci.yml index 3f8df7a7a..6ef981133 100644 --- a/src/dbscanserving/.gitlab-ci.yml +++ b/src/dbscanserving/.gitlab-ci.yml @@ -20,6 +20,7 @@ build dbscanserving: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test dbscanserving: needs: - build dbscanserving before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME container is not in the system"; fi diff --git a/src/device/.gitlab-ci.yml b/src/device/.gitlab-ci.yml index 1de42de6d..878332d9c 100644 --- a/src/device/.gitlab-ci.yml +++ b/src/device/.gitlab-ci.yml @@ -20,6 +20,7 @@ build device: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker ps -aq | xargs -r docker rm -f - containerlab destroy --all --cleanup || true @@ -50,6 +51,7 @@ unit_test device: needs: - build device before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - > if docker network list | grep teraflowbridge; then diff --git a/src/device/client/DeviceClient.py b/src/device/client/DeviceClient.py index b15589ac0..549e9a5a3 100644 --- a/src/device/client/DeviceClient.py +++ b/src/device/client/DeviceClient.py @@ -113,3 +113,11 @@ class DeviceClient: response = self.stub.SSETelemetrySubscribe(request) LOGGER.debug('SSETelemetrySubscribe result: {:s}'.format(grpc_message_to_json_string(response))) return response + + @RETRY_DECORATOR + def UpdateDeviceInventory(self, request : DeviceId) -> Empty: + LOGGER.debug('UpdateDeviceInventory request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.UpdateDeviceInventory(request) + LOGGER.debug('UpdateDeviceInventory result: {:s}'.format(grpc_message_to_json_string(response))) + return response + diff --git a/src/device/service/DeviceServiceServicerImpl.py b/src/device/service/DeviceServiceServicerImpl.py index 13bcc18e5..9f85f38ba 100644 --- a/src/device/service/DeviceServiceServicerImpl.py +++ b/src/device/service/DeviceServiceServicerImpl.py @@ -21,7 +21,7 @@ from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, safe_a from common.method_wrappers.ServiceExceptions import NotFoundException, OperationFailedException from common.proto.context_pb2 import ( Device, DeviceConfig, DeviceDriverEnum, DeviceId, DeviceOperationalStatusEnum, Empty, Link, - OpticalConfig, OpticalConfigId + OpticalConfig, OpticalConfigId, ConfigActionEnum ) from common.proto.device_pb2 import MonitoringSettings from common.proto.device_pb2_grpc import DeviceServiceServicer @@ -37,7 +37,7 @@ from .Tools import ( check_connect_rules, check_no_endpoints, compute_rules_to_add_delete, configure_rules, deconfigure_rules, get_device_controller_uuid, populate_config_rules, populate_endpoint_monitoring_resources, populate_endpoints, populate_initial_config_rules, - subscribe_kpi, unsubscribe_kpi, update_endpoints + subscribe_kpi, unsubscribe_kpi, update_endpoints, update_sap_id, _raw_config_rules_to_grpc ) LOGGER = logging.getLogger(__name__) @@ -55,6 +55,7 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): self.monitoring_loops = monitoring_loops self.mutex_queues = MutexQueues() LOGGER.debug('Servicer Created') + self.sap_id =0 @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) def AddDevice(self, request : Device, context : grpc.ServicerContext) -> DeviceId: @@ -93,6 +94,9 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): device_uuid = device.device_id.device_uuid.uuid device_name = device.name + update_sap_id(device, self.sap_id) + self.sap_id += 1 + t2 = time.time() self.mutex_queues.add_alias(device_uuid, device_name) @@ -441,3 +445,61 @@ class DeviceServiceServicerImpl(DeviceServiceServicer): ) return SSEMonitoringSubscriptionResponse() + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def UpdateDeviceInventory(self, request : DeviceId, context : grpc.ServicerContext) -> Empty: + device_uuid = request.device_uuid.uuid + self.mutex_queues.wait_my_turn(device_uuid) + try: + context_client = ContextClient() + device = get_device(context_client, device_uuid, rw_copy=True) + if device is None: + raise NotFoundException('Device', device_uuid) + + driver : _Driver = get_driver(self.driver_instance_cache, device) + if driver is None: + msg = ERROR_MISSING_DRIVER.format(device_uuid=str(device_uuid)) + raise OperationFailedException('UpdateDeviceInventory', extra_details=msg) + + # Clear and populate endpoints again from the driver + del device.device_endpoints[:] + new_sub_devices = dict() + new_sub_links = dict() + sorted_sub_device_uuids = list() + new_optical_configs = dict() + errors = populate_endpoints( + device, driver, self.monitoring_loops, new_sub_devices, sorted_sub_device_uuids, + new_sub_links, new_optical_configs + ) + if len(errors) > 0: + raise OperationFailedException('UpdateDeviceInventory', extra_details=errors) + + from device.service.driver_api._Driver import RESOURCE_INVENTORY + results_getconfig = driver.GetConfig([RESOURCE_INVENTORY]) + + # Filter out existing /inventory rules to prevent duplicates or leftovers + new_rules = [] + for rule in device.device_config.config_rules: + if rule.WhichOneof('config_rule') == 'custom': + if '/inventory' in rule.custom.resource_key: + continue + new_rules.append(rule) + del device.device_config.config_rules[:] + device.device_config.config_rules.extend(new_rules) + + # Convert new inventory rules and update device config + errors = _raw_config_rules_to_grpc( + device_uuid, device.device_config, 'Error getting inventory resource {resource_key} on device {device_uuid}: {error}', + ConfigActionEnum.CONFIGACTION_SET, results_getconfig + ) + + if len(errors) > 0: + raise OperationFailedException('UpdateDeviceInventory', extra_details=errors) + + context_client.SetDevice(device) + context_client.close() + return Empty() + except Exception as e: + LOGGER.exception('Error updating inventory of device {:s}'.format(str(device_uuid))) + raise e + + diff --git a/src/device/service/Tools.py b/src/device/service/Tools.py index 7cedfbbef..90cd38b90 100644 --- a/src/device/service/Tools.py +++ b/src/device/service/Tools.py @@ -719,3 +719,23 @@ def extract_resources(config : dict, device : Device) -> list[list[dict], dict]: resources.append({'resource_key': 'upper-frequency', 'value': upper_frequency}) return [resources, conditions] + +def update_sap_id(device: Device, sap_id: int) -> None: + + found = False + for config_rule in device.device_config.config_rules: + if config_rule.WhichOneof('config_rule') == 'custom' and config_rule.custom.resource_key == '_connect/settings': + try: + settings = json.loads(config_rule.custom.resource_value) + except ValueError: + settings = {} + settings['sap_id'] = str(sap_id) + config_rule.custom.resource_value = json.dumps(settings) + found = True + break + if not found: + new_rule = device.device_config.config_rules.add() + new_rule.action = ConfigActionEnum.CONFIGACTION_SET + new_rule.custom.resource_key = '_connect/settings' + settings = {'sap_id': str(sap_id)} + new_rule.custom.resource_value = json.dumps(settings) diff --git a/src/device/service/drivers/openconfig/OpenConfigDriver.py b/src/device/service/drivers/openconfig/OpenConfigDriver.py index 7c5276dbe..a77ea2118 100644 --- a/src/device/service/drivers/openconfig/OpenConfigDriver.py +++ b/src/device/service/drivers/openconfig/OpenConfigDriver.py @@ -294,6 +294,7 @@ class OpenConfigDriver(_Driver): self.__out_samples = queue.Queue() self.__netconf_handler = NetconfSessionHandler(self.address, self.port, **(self.settings)) self.__samples_cache = SamplesCache(self.__netconf_handler, self.__logger) + self.sap_id = 0 # Initialize sap_id to zero def Connect(self) -> bool: with self.__lock: @@ -340,6 +341,7 @@ class OpenConfigDriver(_Driver): MSG = 'Exception retrieving {:s}: {:s}' self.__logger.exception(MSG.format(str_resource_name, str(resource_key))) results.append((resource_key, e)) # if validation fails, store the exception + self.sap_id += 1 return results @metered_subclass_method(METRICS_POOL) diff --git a/src/device/service/drivers/openconfig/templates/Interfaces.py b/src/device/service/drivers/openconfig/templates/Interfaces.py index 151e72a89..934bf2ebd 100644 --- a/src/device/service/drivers/openconfig/templates/Interfaces.py +++ b/src/device/service/drivers/openconfig/templates/Interfaces.py @@ -26,6 +26,7 @@ XPATH_IPV6ADDRESSES = ".//ociip:ipv6/ociip:addresses/ociip:address" def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]: response = [] + sap_interface_counter = 0 for xml_interface in xml_data.xpath(XPATH_INTERFACES, namespaces=NAMESPACES): #LOGGER.info('xml_interface = {:s}'.format(str(ET.tostring(xml_interface)))) @@ -44,6 +45,12 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]: if interface_name is None or interface_name.text is None: continue add_value_from_tag(interface, 'name', interface_name) + sap_interface = ET.Element('dummy') + sap_interface.text =str(sap_interface_counter) + aux =str(sap_interface_counter) + add_value_from_tag(interface, 'sap_id', sap_interface) + sap_interface_counter += 1 + # Get the type of interface according to the vendor's type if 'ianaift:' in interface_type.text: interface_type.text = interface_type.text.replace('ianaift:', '') #ADVA @@ -57,6 +64,8 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]: interface_description = xml_interface.find('oci:config/oci:description', namespaces=NAMESPACES) add_value_from_tag(interface, 'description', interface_description) + sap_subinterface_counter = 65 + for xml_subinterface in xml_interface.xpath(XPATH_SUBINTERFACES, namespaces=NAMESPACES): #LOGGER.info('xml_subinterface = {:s}'.format(str(ET.tostring(xml_subinterface)))) @@ -74,6 +83,12 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]: vlan_id = xml_subinterface.find('ocv:vlan/ocv:match/ocv:single-tagged/ocv:config/ocv:vlan-id', namespaces=NAMESPACES) add_value_from_tag(subinterface, 'vlan_id', vlan_id, cast=int) + sap_subinterface = ET.Element('dummy') + value = (aux + chr(sap_subinterface_counter)) + sap_subinterface.text = value + add_value_from_tag(subinterface, 'sap_id', sap_subinterface) + sap_subinterface_counter += 1 + # TODO: implement support for multiple IP addresses per subinterface #ipv4_addresses = [] for xml_ipv4_address in xml_subinterface.xpath(XPATH_IPV4ADDRESSES, namespaces=NAMESPACES): diff --git a/src/dlt/.gitlab-ci.yml b/src/dlt/.gitlab-ci.yml index 8ecc64810..dd6a172d7 100644 --- a/src/dlt/.gitlab-ci.yml +++ b/src/dlt/.gitlab-ci.yml @@ -20,6 +20,7 @@ build dlt: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # This first build tags the builder resulting image to prevent being removed by dangling image removal command @@ -60,6 +61,7 @@ unit test dlt-gateway: needs: - build dlt before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep ${IMAGE_NAME}-connector; then docker rm -f ${IMAGE_NAME}-connector; else echo "${IMAGE_NAME}-connector image is not in the system"; fi @@ -109,6 +111,7 @@ unit test dlt-connector: needs: - build dlt before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create --driver=bridge teraflowbridge; fi - if docker container ls | grep ${IMAGE_NAME}-connector; then docker rm -f ${IMAGE_NAME}-connector; else echo "${IMAGE_NAME}-connector image is not in the system"; fi diff --git a/src/e2e_orchestrator/.gitlab-ci.yml b/src/e2e_orchestrator/.gitlab-ci.yml index 2dfde3fe2..cb3b23629 100644 --- a/src/e2e_orchestrator/.gitlab-ci.yml +++ b/src/e2e_orchestrator/.gitlab-ci.yml @@ -20,6 +20,7 @@ build e2e_orchestrator: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/e2e_orchestrator/Dockerfile b/src/e2e_orchestrator/Dockerfile index 847e75ed4..3751c02a8 100644 --- a/src/e2e_orchestrator/Dockerfile +++ b/src/e2e_orchestrator/Dockerfile @@ -82,6 +82,9 @@ COPY src/context/client/. context/client/ COPY src/context/service/database/uuids/. context/service/database/uuids/ COPY src/service/__init__.py service/__init__.py COPY src/service/client/. service/client/ +COPY src/pathcomp/__init__.py pathcomp/__init__.py +COPY src/pathcomp/frontend/__init__.py pathcomp/frontend/__init__.py +COPY src/pathcomp/frontend/client/. pathcomp/frontend/client/ COPY src/e2e_orchestrator/. e2e_orchestrator/ # Start the service diff --git a/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py b/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py index ead3aeb83..7e8732787 100644 --- a/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py +++ b/src/e2e_orchestrator/service/E2EOrchestratorServiceServicerImpl.py @@ -19,6 +19,9 @@ from common.proto.context_pb2 import Empty, Connection, EndPointId from common.proto.e2eorchestrator_pb2_grpc import E2EOrchestratorServiceServicer from context.client.ContextClient import ContextClient from context.service.database.uuids.EndPoint import endpoint_get_uuid +from common.proto.context_pb2 import ServiceTypeEnum +from pathcomp.frontend.client.PathCompClient import PathCompClient +from common.proto.pathcomp_pb2 import PathCompRequest LOGGER = logging.getLogger(__name__) @@ -33,6 +36,18 @@ class E2EOrchestratorServiceServicerImpl(E2EOrchestratorServiceServicer): def Compute( self, request: E2EOrchestratorRequest, context: grpc.ServicerContext ) -> E2EOrchestratorReply: + if request.service.service_type == ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY: + LOGGER.info("E2E Orchestrator: Detected OPTICAL_CONNECTIVITY service. Calling PathComp.") + pathcomp_client = PathCompClient() + pathcomp_req = PathCompRequest() + pathcomp_req.services.append(request.service) + pathcomp_reply = pathcomp_client.Compute(pathcomp_req) + + e2e_reply = E2EOrchestratorReply() + e2e_reply.services.extend(pathcomp_reply.services) + e2e_reply.connections.extend(pathcomp_reply.connections) + return e2e_reply + endpoints_ids = [ endpoint_get_uuid(endpoint_id)[2] for endpoint_id in request.service.service_endpoint_ids diff --git a/src/forecaster/.gitlab-ci.yml b/src/forecaster/.gitlab-ci.yml index 1af09a5eb..7d6434fea 100644 --- a/src/forecaster/.gitlab-ci.yml +++ b/src/forecaster/.gitlab-ci.yml @@ -20,6 +20,7 @@ build forecaster: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test forecaster: needs: - build forecaster before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi diff --git a/src/gitlab-ci.yml_generator.py b/src/gitlab-ci.yml_generator.py index 465b77ecc..ef1489a84 100644 --- a/src/gitlab-ci.yml_generator.py +++ b/src/gitlab-ci.yml_generator.py @@ -46,6 +46,7 @@ build {microservice}: IMAGE_TAG: '{tag}' # tag of the container image (production, development, etc) stage: build before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile ./src/ @@ -73,6 +74,7 @@ unit test {microservice}: needs: - build {microservice} before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep influxdb; then docker rm -f influxdb; else echo "influxdb image is not in the system"; fi diff --git a/src/interdomain/.gitlab-ci.yml b/src/interdomain/.gitlab-ci.yml index 766e810bb..e98452b3e 100644 --- a/src/interdomain/.gitlab-ci.yml +++ b/src/interdomain/.gitlab-ci.yml @@ -20,6 +20,7 @@ build interdomain: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit test interdomain: needs: - build interdomain before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi diff --git a/src/kpi_manager/.gitlab-ci.yml b/src/kpi_manager/.gitlab-ci.yml index 79cce1607..3ec75744d 100644 --- a/src/kpi_manager/.gitlab-ci.yml +++ b/src/kpi_manager/.gitlab-ci.yml @@ -20,6 +20,7 @@ build kpi-manager: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test kpi-manager: needs: - build kpi-manager before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep crdb; then docker rm -f crdb; else echo "CockroachDB container is not in the system"; fi diff --git a/src/kpi_value_api/.gitlab-ci.yml b/src/kpi_value_api/.gitlab-ci.yml index b0f4b73af..500d8b4ce 100644 --- a/src/kpi_value_api/.gitlab-ci.yml +++ b/src/kpi_value_api/.gitlab-ci.yml @@ -20,6 +20,7 @@ build kpi-value-api: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test kpi-value-api: needs: - build kpi-value-api before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME container is not in the system"; fi diff --git a/src/kpi_value_writer/.gitlab-ci.yml b/src/kpi_value_writer/.gitlab-ci.yml index b19e227bf..f605d7098 100644 --- a/src/kpi_value_writer/.gitlab-ci.yml +++ b/src/kpi_value_writer/.gitlab-ci.yml @@ -20,6 +20,7 @@ build kpi-value-writer: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test kpi-value-writer: needs: - build kpi-value-writer before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME container is not in the system"; fi diff --git a/src/l3_attackmitigator/.gitlab-ci.yml b/src/l3_attackmitigator/.gitlab-ci.yml index c81aec520..672462f33 100644 --- a/src/l3_attackmitigator/.gitlab-ci.yml +++ b/src/l3_attackmitigator/.gitlab-ci.yml @@ -20,6 +20,7 @@ build l3_attackmitigator: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit test l3_attackmitigator: needs: - build l3_attackmitigator before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi diff --git a/src/l3_centralizedattackdetector/.gitlab-ci.yml b/src/l3_centralizedattackdetector/.gitlab-ci.yml index cfe0bfdf1..0fca91b5b 100644 --- a/src/l3_centralizedattackdetector/.gitlab-ci.yml +++ b/src/l3_centralizedattackdetector/.gitlab-ci.yml @@ -20,6 +20,7 @@ build l3_centralizedattackdetector: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit test l3_centralizedattackdetector: needs: - build l3_centralizedattackdetector before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi diff --git a/src/l3_distributedattackdetector/.gitlab-ci.yml b/src/l3_distributedattackdetector/.gitlab-ci.yml index e283af3a2..ed9ad3bfd 100644 --- a/src/l3_distributedattackdetector/.gitlab-ci.yml +++ b/src/l3_distributedattackdetector/.gitlab-ci.yml @@ -20,6 +20,7 @@ build l3_distributedattackdetector: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit test l3_distributedattackdetector: needs: - build l3_distributedattackdetector before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi diff --git a/src/load_generator/.gitlab-ci.yml b/src/load_generator/.gitlab-ci.yml index ef0815460..308b3161e 100644 --- a/src/load_generator/.gitlab-ci.yml +++ b/src/load_generator/.gitlab-ci.yml @@ -20,6 +20,7 @@ build load_generator: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/monitoring/.gitlab-ci.yml b/src/monitoring/.gitlab-ci.yml index 072a526da..486daba87 100644 --- a/src/monitoring/.gitlab-ci.yml +++ b/src/monitoring/.gitlab-ci.yml @@ -20,6 +20,7 @@ build monitoring: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test monitoring: needs: - build monitoring before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep questdb; then docker rm -f questdb; else echo "questdb image is not in the system"; fi diff --git a/src/nbi/.gitlab-ci.yml b/src/nbi/.gitlab-ci.yml index 4095fee28..af5e3043f 100644 --- a/src/nbi/.gitlab-ci.yml +++ b/src/nbi/.gitlab-ci.yml @@ -20,6 +20,7 @@ build nbi: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -49,6 +50,7 @@ unit_test nbi: - build nbi - build mock_tfs_nbi_dependencies before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker ps -aq | xargs -r docker rm -f - > diff --git a/src/nbi/Dockerfile b/src/nbi/Dockerfile index 4587678c9..4198b06cb 100644 --- a/src/nbi/Dockerfile +++ b/src/nbi/Dockerfile @@ -92,6 +92,10 @@ COPY src/slice/__init__.py slice/__init__.py COPY src/slice/client/. slice/client/ COPY src/vnt_manager/__init__.py vnt_manager/__init__.py COPY src/vnt_manager/client/. vnt_manager/client/ + +COPY src/e2e_orchestrator/. e2e_orchestrator/__init__.py +COPY src/e2e_orchestrator/client/. e2e_orchestrator/client/ + RUN mkdir -p /var/teraflow/tests/tools COPY src/tests/tools/mock_osm/. tests/tools/mock_osm/ COPY src/nbi/. nbi/ diff --git a/src/nbi/service/app.py b/src/nbi/service/app.py index b5b83a610..f5c7ac6b5 100644 --- a/src/nbi/service/app.py +++ b/src/nbi/service/app.py @@ -40,6 +40,7 @@ from .ietf_l2vpn import register_ietf_l2vpn from .ietf_l3vpn import register_ietf_l3vpn from .ietf_network import register_ietf_network from .ietf_network_slice import register_ietf_nss +from .ietf_sap_topology import register_ietf_sap_topology from .ipowdm import register_ipowdm from .optical_slice import register_optical_slice from .osm_nbi import register_osm_api @@ -100,6 +101,7 @@ register_ietf_l2vpn (nbi_app) register_ietf_l3vpn (nbi_app) register_ietf_network (nbi_app) register_ietf_nss (nbi_app) +register_ietf_sap_topology(nbi_app) register_optical_slice (nbi_app) register_osm_api (nbi_app) register_qkd_app (nbi_app) diff --git a/src/nbi/service/ietf_sap_topology/NameMapping.py b/src/nbi/service/ietf_sap_topology/NameMapping.py new file mode 100644 index 000000000..18b9321c1 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/NameMapping.py @@ -0,0 +1,48 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Dict, Tuple + +from common.proto.context_pb2 import Device, DeviceId, EndPoint, EndPointId + + +class NameMappings: + def __init__(self) -> None: + self._device_uuid_to_name : Dict[str, str] = dict() + self._endpoint_uuid_to_name : Dict[Tuple[str, str], str] = dict() + + def store_device_name(self, device : Device) -> None: + device_uuid = device.device_id.device_uuid.uuid + device_name = device.name + self._device_uuid_to_name[device_uuid] = device_name + self._device_uuid_to_name[device_name] = device_name + + def store_endpoint_name(self, device : Device, endpoint : EndPoint) -> None: + device_uuid = device.device_id.device_uuid.uuid + device_name = device.name + endpoint_uuid = endpoint.endpoint_id.endpoint_uuid.uuid + endpoint_name = endpoint.name + self._endpoint_uuid_to_name[(device_uuid, endpoint_uuid)] = endpoint_name + self._endpoint_uuid_to_name[(device_name, endpoint_uuid)] = endpoint_name + self._endpoint_uuid_to_name[(device_uuid, endpoint_name)] = endpoint_name + self._endpoint_uuid_to_name[(device_name, endpoint_name)] = endpoint_name + + def get_device_name(self, device_id : DeviceId) -> str: + device_uuid = device_id.device_uuid.uuid + return self._device_uuid_to_name.get(device_uuid, device_uuid) + + def get_endpoint_name(self, endpoint_id : EndPointId) -> str: + device_uuid = endpoint_id.device_id.device_uuid.uuid + endpoint_uuid = endpoint_id.endpoint_uuid.uuid + return self._endpoint_uuid_to_name.get((device_uuid, endpoint_uuid), endpoint_uuid) diff --git a/src/nbi/service/ietf_sap_topology/NetworkTypeEnum.py b/src/nbi/service/ietf_sap_topology/NetworkTypeEnum.py new file mode 100644 index 000000000..e03bb1368 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/NetworkTypeEnum.py @@ -0,0 +1,23 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from enum import Enum +from typing import Optional + +class NetworkTypeEnum(Enum): + TE_OTN_TOPOLOGY = 'otn' + TE_ETH_TRAN_TOPOLOGY = 'eth-tran' + +def get_network_topology_type(topology_id : str) -> Optional[NetworkTypeEnum]: + return NetworkTypeEnum._value2member_map_.get(topology_id) diff --git a/src/nbi/service/ietf_sap_topology/Networks.py b/src/nbi/service/ietf_sap_topology/Networks.py new file mode 100644 index 000000000..c69516d6d --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/Networks.py @@ -0,0 +1,86 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import enum +import logging + +from common.proto.context_pb2 import ContextId, Empty +from common.Settings import get_setting +from common.tools.context_queries.Topology import get_topology_details +from common.tools.object_factory.Context import json_context_id +from context.client.ContextClient import ContextClient +from flask import request +from flask.json import jsonify +from flask_restful import Resource +from nbi.service._tools.Authentication import HTTP_AUTH +from nbi.service._tools.HttpStatusCodes import HTTP_OK, HTTP_SERVERERROR + +from .YangHandler import YangHandler + +LOGGER = logging.getLogger(__name__) + +TE_TOPOLOGY_NAMES = [ + 'providerId-10-clientId-0-topologyId-1', + 'providerId-10-clientId-0-topologyId-2' +] + +class Renderer(enum.Enum): + LIBYANG = 'LIBYANG' + PYANGBIND = 'PYANGBIND' + +DEFAULT_RENDERER = Renderer.LIBYANG +USE_RENDERER = get_setting('IETF_NETWORK_RENDERER', default=DEFAULT_RENDERER.value) + + +class Networks(Resource): + @HTTP_AUTH.login_required + def get(self): + LOGGER.info('Request: {:s}'.format(str(request))) + topology_id = '' + try: + context_client = ContextClient() + + if USE_RENDERER == Renderer.LIBYANG.value: + yang_handler = YangHandler() + json_response = [] + + contexts = context_client.ListContexts(Empty()).contexts + context_names = [context.name for context in contexts] + LOGGER.info(f'Contexts detected: {context_names}') + + for context_name in context_names: + topologies = context_client.ListTopologies(ContextId(**json_context_id(context_name))).topologies + topology_names = [topology.name for topology in topologies] + LOGGER.info(f'Topologies detected for context {context_name}: {topology_names}') + + for topology_name in topology_names: + topology_details = get_topology_details(context_client, topology_name, context_name) + if topology_details is None: + raise Exception(f'Topology({context_name}/{topology_name}) not found') + + network_reply = yang_handler.compose_network(topology_name, topology_details) + json_response.append(network_reply) + + yang_handler.destroy() + else: + raise Exception('Unsupported Renderer: {:s}'.format(str(USE_RENDERER))) + + response = jsonify(json_response) + response.status_code = HTTP_OK + + except Exception as e: # pylint: disable=broad-except + LOGGER.exception('Something went wrong Retrieving Topology({:s})'.format(str(topology_id))) + response = jsonify({'error': str(e)}) + response.status_code = HTTP_SERVERERROR + return response diff --git a/src/nbi/service/ietf_sap_topology/SAP_Topology.py b/src/nbi/service/ietf_sap_topology/SAP_Topology.py new file mode 100644 index 000000000..b4c9b18ae --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/SAP_Topology.py @@ -0,0 +1,88 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import enum +import logging + +from flask import request +from flask.json import jsonify +from flask_restful import Resource + +from common.proto.context_pb2 import ContextId, Empty +from common.Settings import get_setting +from common.tools.context_queries.Topology import get_topology_details +from common.tools.object_factory.Context import json_context_id +from context.client.ContextClient import ContextClient +from nbi.service._tools.Authentication import HTTP_AUTH +from nbi.service._tools.HttpStatusCodes import HTTP_OK, HTTP_SERVERERROR + +from .YangHandler import YangHandler + +LOGGER = logging.getLogger(__name__) + +TE_TOPOLOGY_NAMES = [ + 'providerId-10-clientId-0-topologyId-1', + 'providerId-10-clientId-0-topologyId-2' +] + +class Renderer(enum.Enum): + LIBYANG = 'LIBYANG' + PYANGBIND = 'PYANGBIND' + +DEFAULT_RENDERER = Renderer.LIBYANG +USE_RENDERER = get_setting('IETF_NETWORK_RENDERER', default=DEFAULT_RENDERER.value) + + +class SAP_Topology(Resource): + @HTTP_AUTH.login_required + def get(self): + LOGGER.info('Request: {:s}'.format(str(request))) + topology_id = '' + try: + context_client = ContextClient() + + + if USE_RENDERER == Renderer.LIBYANG.value: + yang_handler = YangHandler() + json_response = [] + + contexts = context_client.ListContexts(Empty()).contexts + context_names = [context.name for context in contexts] + LOGGER.info(f'Contexts detected: {context_names}') + + for context_name in context_names: + topologies = context_client.ListTopologies(ContextId(**json_context_id(context_name))).topologies + topology_names = [topology.name for topology in topologies] + LOGGER.info(f'Topologies detected for context {context_name}: {topology_names}') + + for topology_name in topology_names: + topology_details = get_topology_details(context_client, topology_name, context_name) + if topology_details is None: + raise Exception(f'Topology({context_name}/{topology_name}) not found') + + network_reply = yang_handler.compose_network(topology_name, topology_details) + json_response.append(network_reply) + + yang_handler.destroy() + else: + raise Exception('Unsupported Renderer: {:s}'.format(str(USE_RENDERER))) + + response = jsonify(json_response) + response.status_code = HTTP_OK + + except Exception as e: # pylint: disable=broad-except + LOGGER.exception('Something went wrong Retrieving Topology({:s})'.format(str(topology_id))) + response = jsonify({'error': str(e)}) + response.status_code = HTTP_SERVERERROR + return response diff --git a/src/nbi/service/ietf_sap_topology/YangHandler.py b/src/nbi/service/ietf_sap_topology/YangHandler.py new file mode 100644 index 000000000..6fae359c1 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/YangHandler.py @@ -0,0 +1,177 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import hashlib +import json +import logging +import os +import re +from typing import Any + +import libyang +from common.proto.context_pb2 import Device, DeviceId, Link, TopologyDetails +from common.tools.object_factory.Device import json_device_id +from context.client.ContextClient import ContextClient + +from .NameMapping import NameMappings + +LOGGER = logging.getLogger(__name__) + +YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') +YANG_MODULES = ['ietf-network', 'ietf-network-topology', 'ietf-sap-ntw', 'ietf-vpn-common'] + +class YangHandler: + def __init__(self) -> None: + self._yang_context = libyang.Context(YANG_DIR) + for yang_module_name in YANG_MODULES: + LOGGER.info('Loading module: {:s}'.format(str(yang_module_name))) + self._yang_context.load_module(yang_module_name).feature_enable_all() + + def compose_network(self, te_topology_name: str, topology_details: TopologyDetails) -> dict: + networks = self._yang_context.create_data_path('/ietf-network:networks') + + network = networks.create_path(f'network[network-id="{te_topology_name}"]') + network.create_path('network-id', te_topology_name) + + # Add supporting-network pointing to urn:tfs:network:admin + supporting_network_id = "urn:tfs:network:admin" + supporting_nw = network.create_path(f'supporting-network[network-ref="{supporting_network_id}"]') + supporting_nw.create_path('network-ref', supporting_network_id) + + network_types = network.create_path('network-types') + sap_network = network_types.create_path('ietf-sap-ntw:sap-network') + + available_services = [ + "ietf-vpn-common:l3vpn", + "ietf-vpn-common:vpls", + "ietf-vpn-common:vpws", + "ietf-vpn-common:vpws-evpn", + "ietf-vpn-common:mpls-evpn", + "ietf-vpn-common:vxlan-evpn", + "ietf-vpn-common:pbb-evpn", + "ietf-sap-ntw:network-slice", + "ietf-sap-ntw:virtual-network", + "ietf-sap-ntw:enhanced-vpn", + "ietf-sap-ntw:sdwan", + "ietf-sap-ntw:basic-connectivity" + ] + service = available_services[0] #TO DO: get services from config + if service in available_services: + sap_network.create_path('service-type', service) + + connected_tps = set() + name_mappings = NameMappings() + + LOGGER.info(f"Processing topology_details: {len(topology_details.devices)} devices, {len(topology_details.links)} links.") + + if topology_details.links: + for link in topology_details.links: + source_name = name_mappings.get_endpoint_name(link.link_endpoint_ids[0]) + dest_name = name_mappings.get_endpoint_name(link.link_endpoint_ids[-1]) + connected_tps.add(source_name) + connected_tps.add(dest_name) + + if topology_details.devices: + for device in topology_details.devices: + self.compose_node(device, name_mappings, network, connected_tps) + + return json.loads(networks.print_mem('json')) + + def compose_node(self, dev: Device, name_mappings: NameMappings, network: Any, connected_tps: set) -> None: + device_name = dev.name + name_mappings.store_device_name(dev) + + context_client = ContextClient() + device = context_client.GetDevice(DeviceId(**json_device_id(device_name))) + + for config in device.device_config.config_rules: + if config.WhichOneof('config_rule') == 'custom' and config.custom.resource_key == '_connect/settings': + try: + settings_data = json.loads(config.custom.resource_value) + sap_device = settings_data.get('sap_id') + except ValueError: + sap_device = "ERROR" + break + sap_device = "SAP"+ str(sap_device) + + node = network.create_path(f'node[node-id="{sap_device}"]') + node.create_path('node-id', sap_device) + + # Add supporting-node pointing to urn:tfs:network:admin and device node name (obfuscated with SHA-1) + supporting_network_id = "urn:tfs:network:admin" + hashed_dev = hashlib.sha1(device_name.encode('utf-8')).hexdigest() + supporting_node_id = f"urn:tfs:node:{hashed_dev}" + supporting_nd = node.create_path(f'supporting-node[network-ref="{supporting_network_id}"][node-ref="{supporting_node_id}"]') + supporting_nd.create_path('network-ref', supporting_network_id) + supporting_nd.create_path('node-ref', supporting_node_id) + + for endpoint in device.device_endpoints: + name_mappings.store_endpoint_name(dev, endpoint) + + self._process_device_config(device, node, connected_tps, sap_device) + + def _process_device_config(self, device: Device, node: Any, connected_tps: set, sap_device: str) -> None: + sap_device = sap_device + for config in device.device_config.config_rules: + if config.WhichOneof('config_rule') != 'custom' or '/interface[' not in config.custom.resource_key: + continue + # Extract interface_name from key: e.g. "/interface[eth-1/0/10.41]" -> "eth-1/0/10.41" + match = re.search(r'/interface\[([^\]]+)\]', config.custom.resource_key) + if not match: + continue + interface_name = match.group(1) + + for endpoint in device.device_endpoints: + endpoint_name = endpoint.name + if endpoint.endpoint_id.endpoint_uuid.uuid in connected_tps: + continue + if f'/interface[{endpoint_name}]' in config.custom.resource_key or f'/interface[{endpoint_name}.' in config.custom.resource_key: + self._create_termination_point(node, sap_device, config.custom.resource_value, interface_name) + + def _create_termination_point(self, node: Any, sap_device: str, resource_value: str, interface_name: str) -> None: + config_data = json.loads(resource_value) + ip_addresses = self._extract_ip_addresses(config_data) + if ip_addresses: + #tp = node.create_path(f'ietf-network-topology:termination-point[tp-id="{interface_name}"]') + service = node.create_path(f'ietf-sap-ntw:service[service-type="ietf-vpn-common:l3vpn"]') + + # Proprietary obfuscated ID of the interface name: + hashed_if = hashlib.sha1(interface_name.encode('utf-8')).hexdigest() + final_sap_id = f"{sap_device}-{hashed_if}" + + sap = service.create_path(f'sap[sap-id="{final_sap_id}"]') + + # Add parent-termination-point pointing to the physical tp-id (obfuscated with SHA-1) + parent_tp = f"urn:tfs:tp:{hashed_if}" + sap.create_path('parent-termination-point', parent_tp) + # sap.create_path('peer-sap-id', "NOT_IMPLEMENTED") # OPTIONAL FIELD + sap_status = sap.create_path('sap-status') + sap_status.create_path('status', "ietf-vpn-common:op-up") + service_status = sap.create_path('service-status') + admin_status = service_status.create_path('admin-status') + oper_status = service_status.create_path('oper-status') + admin_status.create_path('status', "ietf-vpn-common:admin-up") # TO DO: Dynamic verification needed + oper_status.create_path('status', "ietf-vpn-common:op-up") # TO DO: Dynamic verification needed + + @staticmethod + def _extract_ip_addresses(resource_value: dict) -> list: + ip_addresses = [] + if 'address_ip' in resource_value: + ip_addresses.append(resource_value['address_ip']) + if 'address_ipv6' in resource_value: + ip_addresses.append(resource_value['address_ipv6']) + return ip_addresses + + def destroy(self) -> None: + self._yang_context.destroy() diff --git a/src/nbi/service/ietf_sap_topology/__init__.py b/src/nbi/service/ietf_sap_topology/__init__.py new file mode 100644 index 000000000..e29bbfd86 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/__init__.py @@ -0,0 +1,39 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# RFC 8795 - YANG Data Model for Traffic Engineering (TE) Topologies +# Ref: https://datatracker.ietf.org/doc/html/rfc8795 + +# RFC 8776 - Common YANG Data Types for Traffic Engineering +# Ref: https://datatracker.ietf.org/doc/html/rfc8776 + +# RFC 8345 - A YANG Data Model for Network Topologies +# Ref: https://datatracker.ietf.org/doc/html/rfc8345 + +# RFC 6991 - Common YANG Data Types +# Ref: https://datatracker.ietf.org/doc/html/rfc6991 + +# RFC draft-ietf-ccamp-eth-client-te-topo-yang-05 - A YANG Data Model for Ethernet TE Topology +# Ref: https://datatracker.ietf.org/doc/draft-ietf-ccamp-eth-client-te-topo-yang/ + +# RFC draft-ietf-ccamp-client-signal-yang-10 - A YANG Data Model for Transport Network Client Signals +# Ref: https://datatracker.ietf.org/doc/draft-ietf-ccamp-client-signal-yang/ + +from nbi.service.NbiApplication import NbiApplication +from .SAP_Topology import SAP_Topology + +URL_PREFIX = '/restconf/data/ietf-network:networks' + +def register_ietf_sap_topology(nbi_app : NbiApplication): + nbi_app.add_rest_api_resource(SAP_Topology, URL_PREFIX + '/sap') diff --git a/src/nbi/service/ietf_sap_topology/build-yang-bindings.sh b/src/nbi/service/ietf_sap_topology/build-yang-bindings.sh new file mode 100755 index 000000000..bef81ff23 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/build-yang-bindings.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +BASE_PATH=~/tfs-ctrl/src/nbi/service/rest_server/nbi_plugins/ietf_network +IETF_MODELS_PATH=${BASE_PATH}/yang + +cd ${BASE_PATH} +export PYBINDPLUGIN=`/usr/bin/env python -c 'import pyangbind; import os; print ("{}/plugin".format(os.path.dirname(pyangbind.__file__)))'` + +rm -rf bindings + +# -p ${OC_HERCULES_MODELS_PATH}/ +# --split-class-dir openconfig_hercules +# --presence +pyang --plugindir $PYBINDPLUGIN -p ${IETF_MODELS_PATH}/ -f pybind --split-class-dir bindings \ + ${IETF_MODELS_PATH}/ietf-network-topology@2018-02-26.yang \ + ${IETF_MODELS_PATH}/ietf-network@2018-02-26.yang \ + ${IETF_MODELS_PATH}/ietf-te-topology@2020-08-06.yang \ + ${IETF_MODELS_PATH}/ietf-otn-topology@2023-07-06.yang \ + ${IETF_MODELS_PATH}/ietf-eth-te-topology@2023-09-28.yang \ + ${IETF_MODELS_PATH}/ietf-vpn-common@2022-02-11.yang \ + ${IETF_MODELS_PATH}/ietf-sap-ntw@2023-06-20.yang diff --git a/src/nbi/service/ietf_sap_topology/yang/iana-routing-types@2017-12-04.yang b/src/nbi/service/ietf_sap_topology/yang/iana-routing-types@2017-12-04.yang new file mode 100644 index 000000000..250cba4b6 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/iana-routing-types@2017-12-04.yang @@ -0,0 +1,473 @@ + module iana-routing-types { + namespace "urn:ietf:params:xml:ns:yang:iana-routing-types"; + prefix iana-rt-types; + + organization + "IANA"; + contact + "Internet Assigned Numbers Authority + + Postal: ICANN + 12025 Waterfront Drive, Suite 300 + Los Angeles, CA 90094-2536 + United States of America + Tel: +1 310 301 5800 + "; + + description + "This module contains a collection of YANG data types + considered defined by IANA and used for routing + protocols. + + Copyright (c) 2017 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8294; see + the RFC itself for full legal notices."; + + revision 2017-12-04 { + description "Initial revision."; + reference + "RFC 8294: Common YANG Data Types for the Routing Area. + Section 4."; + } + + /*** Collection of IANA types related to routing ***/ + /*** IANA Address Family enumeration ***/ + + typedef address-family { + type enumeration { + enum ipv4 { + value 1; + description + "IPv4 Address Family."; + } + + enum ipv6 { + value 2; + description + "IPv6 Address Family."; + } + + enum nsap { + value 3; + description + "OSI Network Service Access Point (NSAP) Address Family."; + } + + enum hdlc { + value 4; + description + "High-Level Data Link Control (HDLC) Address Family."; + } + + enum bbn1822 { + value 5; + description + "Bolt, Beranek, and Newman Report 1822 (BBN 1822) + Address Family."; + } + + enum ieee802 { + value 6; + description + "IEEE 802 Committee Address Family + (aka Media Access Control (MAC) address)."; + } + + enum e163 { + value 7; + description + "ITU-T E.163 Address Family."; + } + + enum e164 { + value 8; + description + "ITU-T E.164 (Switched Multimegabit Data Service (SMDS), + Frame Relay, ATM) Address Family."; + } + + enum f69 { + value 9; + description + "ITU-T F.69 (Telex) Address Family."; + } + + enum x121 { + value 10; + description + "ITU-T X.121 (X.25, Frame Relay) Address Family."; + } + + enum ipx { + value 11; + description + "Novell Internetwork Packet Exchange (IPX) + Address Family."; + } + + enum appletalk { + value 12; + description + "Apple AppleTalk Address Family."; + } + + enum decnet-iv { + value 13; + description + "Digital Equipment DECnet Phase IV Address Family."; + } + + enum vines { + value 14; + description + "Banyan Vines Address Family."; + } + + enum e164-nsap { + value 15; + description + "ITU-T E.164 with NSAP sub-address Address Family."; + } + + enum dns { + value 16; + description + "Domain Name System (DNS) Address Family."; + } + + enum distinguished-name { + value 17; + description + "Distinguished Name Address Family."; + } + + enum as-num { + value 18; + description + "Autonomous System (AS) Number Address Family."; + } + + enum xtp-v4 { + value 19; + description + "Xpress Transport Protocol (XTP) over IPv4 + Address Family."; + } + + enum xtp-v6 { + value 20; + description + "XTP over IPv6 Address Family."; + } + + enum xtp-native { + value 21; + description + "XTP native mode Address Family."; + } + + enum fc-port { + value 22; + description + "Fibre Channel (FC) World-Wide Port Name Address Family."; + } + + enum fc-node { + value 23; + description + "FC World-Wide Node Name Address Family."; + } + + enum gwid { + value 24; + description + "ATM Gateway Identifier (GWID) Number Address Family."; + } + + enum l2vpn { + value 25; + description + "Layer 2 VPN (L2VPN) Address Family."; + } + + enum mpls-tp-section-eid { + value 26; + description + "MPLS Transport Profile (MPLS-TP) Section Endpoint + Identifier Address Family."; + } + + enum mpls-tp-lsp-eid { + value 27; + description + "MPLS-TP Label Switched Path (LSP) Endpoint Identifier + Address Family."; + } + + enum mpls-tp-pwe-eid { + value 28; + description + "MPLS-TP Pseudowire Endpoint Identifier Address Family."; + } + + enum mt-v4 { + value 29; + description + "Multi-Topology IPv4 Address Family."; + } + + enum mt-v6 { + value 30; + description + "Multi-Topology IPv6 Address Family."; + } + + enum eigrp-common-sf { + value 16384; + description + "Enhanced Interior Gateway Routing Protocol (EIGRP) + Common Service Family Address Family."; + } + + enum eigrp-v4-sf { + value 16385; + description + "EIGRP IPv4 Service Family Address Family."; + } + + enum eigrp-v6-sf { + value 16386; + description + "EIGRP IPv6 Service Family Address Family."; + } + + enum lcaf { + value 16387; + description + "Locator/ID Separation Protocol (LISP) + Canonical Address Format (LCAF) Address Family."; + } + + enum bgp-ls { + value 16388; + description + "Border Gateway Protocol - Link State (BGP-LS) + Address Family."; + } + + enum mac-48 { + value 16389; + description + "IEEE 48-bit MAC Address Family."; + } + + enum mac-64 { + value 16390; + description + "IEEE 64-bit MAC Address Family."; + } + + enum trill-oui { + value 16391; + description + "Transparent Interconnection of Lots of Links (TRILL) + IEEE Organizationally Unique Identifier (OUI) + Address Family."; + } + + enum trill-mac-24 { + value 16392; + description + "TRILL final 3 octets of 48-bit MAC Address Family."; + } + + enum trill-mac-40 { + value 16393; + description + "TRILL final 5 octets of 64-bit MAC Address Family."; + } + + enum ipv6-64 { + value 16394; + description + "First 8 octets (64 bits) of IPv6 address + Address Family."; + } + + enum trill-rbridge-port-id { + value 16395; + description + "TRILL Routing Bridge (RBridge) Port ID Address Family."; + } + + enum trill-nickname { + value 16396; + description + "TRILL Nickname Address Family."; + } + } + + description + "Enumeration containing all the IANA-defined + Address Families."; + + } + + /*** Subsequent Address Family Identifiers (SAFIs) ***/ + /*** for multiprotocol BGP enumeration ***/ + + typedef bgp-safi { + type enumeration { + enum unicast-safi { + value 1; + description + "Unicast SAFI."; + } + + enum multicast-safi { + value 2; + description + "Multicast SAFI."; + } + + enum labeled-unicast-safi { + value 4; + description + "Labeled Unicast SAFI."; + } + + enum multicast-vpn-safi { + value 5; + description + "Multicast VPN SAFI."; + } + + enum pseudowire-safi { + value 6; + description + "Multi-segment Pseudowire VPN SAFI."; + } + + enum tunnel-encap-safi { + value 7; + description + "Tunnel Encap SAFI."; + } + + enum mcast-vpls-safi { + value 8; + description + "Multicast Virtual Private LAN Service (VPLS) SAFI."; + } + + enum tunnel-safi { + value 64; + description + "Tunnel SAFI."; + } + + enum vpls-safi { + value 65; + description + "VPLS SAFI."; + } + + enum mdt-safi { + value 66; + description + "Multicast Distribution Tree (MDT) SAFI."; + } + + enum v4-over-v6-safi { + value 67; + description + "IPv4 over IPv6 SAFI."; + } + + enum v6-over-v4-safi { + value 68; + description + "IPv6 over IPv4 SAFI."; + } + + enum l1-vpn-auto-discovery-safi { + value 69; + description + "Layer 1 VPN Auto-Discovery SAFI."; + } + + enum evpn-safi { + value 70; + description + "Ethernet VPN (EVPN) SAFI."; + } + + enum bgp-ls-safi { + value 71; + description + "BGP-LS SAFI."; + } + + enum bgp-ls-vpn-safi { + value 72; + description + "BGP-LS VPN SAFI."; + } + + enum sr-te-safi { + value 73; + description + "Segment Routing - Traffic Engineering (SR-TE) SAFI."; + } + + enum labeled-vpn-safi { + value 128; + description + "MPLS Labeled VPN SAFI."; + } + + enum multicast-mpls-vpn-safi { + value 129; + description + "Multicast for BGP/MPLS IP VPN SAFI."; + } + + enum route-target-safi { + value 132; + description + "Route Target SAFI."; + } + + enum ipv4-flow-spec-safi { + value 133; + description + "IPv4 Flow Specification SAFI."; + } + + enum vpnv4-flow-spec-safi { + value 134; + description + "IPv4 VPN Flow Specification SAFI."; + } + + enum vpn-auto-discovery-safi { + value 140; + description + "VPN Auto-Discovery SAFI."; + } + } + description + "Enumeration for BGP SAFI."; + reference + "RFC 4760: Multiprotocol Extensions for BGP-4."; + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-ac-ntw@2024-05-15.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-ac-ntw@2024-05-15.yang new file mode 100644 index 000000000..f48e4d767 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-ac-ntw@2024-05-15.yang @@ -0,0 +1,2019 @@ +module ietf-ac-ntw { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-ac-ntw"; + prefix ac-ntw; + + import ietf-vpn-common { + prefix vpn-common; + reference + "RFC 9181: A Common YANG Data Model for Layer 2 and Layer 3 + VPNs"; + } + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types, Section 4"; + } + import ietf-key-chain { + prefix key-chain; + reference + "RFC 8177: YANG Data Model for Key Chains"; + } + import ietf-routing-types { + prefix rt-types; + reference + "RFC 8294: Common YANG Data Types for the Routing Area"; + } + import ietf-routing-policy { + prefix rt-pol; + reference + "RFC 9067: A YANG Data Model for Routing Policy"; + } + import ietf-interfaces { + prefix if; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + import ieee802-dot1q-types { + prefix dot1q-types; + reference + "IEEE Std 802.1Qcp: Bridges and Bridged Networks-- + Amendment 30: YANG Data Model"; + } + import ietf-network { + prefix nw; + reference + "RFC 8345: A YANG Data Model for Network Topologies, + Section 6.1"; + } + import ietf-sap-ntw { + prefix sap; + reference + "RFC 9408: A YANG Network Model for Service Attachment + Points (SAPs)"; + } + import ietf-ac-common { + prefix ac-common; + reference + "RFC CCCC: A Common YANG Data Model for Attachment Circuits"; + } + import ietf-ac-svc { + prefix ac-svc; + reference + "RFC SSSS: YANG Data Models for Bearers and 'Attachment + Circuits'-as-a-Service (ACaaS)"; + } + + organization + "IETF OPSAWG (Operations and Management Area Working Group)"; + contact + "WG Web: + WG List: + + Editor: Mohamed Boucadair + + Author: Richard Roberts + + Author: Oscar Gonzalez de Dios + + Author: Samier Barguil + + Author: Bo Wu + "; + description + "This YANG module defines a YANG network model for the management + of attachment circuits. + + Copyright (c) 2024 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Revised BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX; see the + RFC itself for full legal notices."; + + revision 2024-05-15 { + description + "Initial revision."; + reference + "RFC XXXX: A YANG Network Data Model for Attachment Circuits"; + } + + // References + + /* A set of groupings to ease referencing cross-modules */ + + grouping attachment-circuit-reference { + description + "This grouping can be used to reference an attachment circuit + in a specific node."; + leaf ac-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]/nw:node[nw:node-id=current()/../" + + "node-ref]/ac-ntw:ac/ac-ntw:name"; + require-instance false; + } + description + "An absolute reference to an attachment circuit."; + } + uses nw:node-ref; + } + + grouping attachment-circuit-references { + description + "This grouping can be used to reference a list of attachment + circuits in a specific node."; + leaf-list ac-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]/nw:node[nw:node-id=current()/../" + + "node-ref]/ac-ntw:ac/ac-ntw:name"; + require-instance false; + } + description + "An absolute reference to an attachment circuit."; + } + uses nw:node-ref; + } + + grouping ac-profile-reference { + description + "This grouping can be used to reference an attachment circuit + profile."; + leaf ac-profile-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]/ac-ntw:ac-profile/ac-ntw:name"; + require-instance false; + } + description + "An absolute reference to an attachment circuit."; + } + uses nw:network-ref; + } + + grouping encryption-profile-reference { + description + "This grouping can be used to reference encryption + profile."; + leaf encryption-profile-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]" + + "/ac-ntw:specific-provisioning-profiles" + + "/ac-ntw:valid-provider-identifiers" + + "/ac-ntw:encryption-profile-identifier/ac-ntw:id"; + require-instance false; + } + description + "An absolute reference to an encryption profile."; + } + uses nw:network-ref; + } + + grouping qos-profile-reference { + description + "This grouping can be used to reference a QoS profile."; + leaf qos-profile-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]" + + "/ac-ntw:specific-provisioning-profiles" + + "/ac-ntw:valid-provider-identifiers" + + "/ac-ntw:qos-profile-identifier/ac-ntw:id"; + require-instance false; + } + description + "An absolute reference to a QoS profile."; + } + uses nw:network-ref; + } + + grouping failure-detection-profile-reference { + description + "This grouping can be used to reference a failure detection + profile."; + leaf failure-detection-profile-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]" + + "/ac-ntw:specific-provisioning-profiles" + + "/ac-ntw:valid-provider-identifiers" + + "/ac-ntw:failure-detection-profile-identifier/ac-ntw:id"; + require-instance false; + } + description + "An absolute reference to a failure detection profile."; + } + uses nw:network-ref; + } + + grouping forwarding-profile-reference { + description + "This grouping can be used to reference a forwarding profile."; + leaf forwarding-profile-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]" + + "/ac-ntw:specific-provisioning-profiles" + + "/ac-ntw:valid-provider-identifiers" + + "/ac-ntw:forwarding-profile-identifier/ac-ntw:id"; + require-instance false; + } + description + "An absolute reference to a forwarding profile."; + } + uses nw:network-ref; + } + + grouping routing-profile-reference { + description + "This grouping can be used to reference a routing profile."; + leaf routing-profile-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../" + + "network-ref]" + + "/ac-ntw:specific-provisioning-profiles" + + "/ac-ntw:valid-provider-identifiers" + + "/ac-ntw:routing-profile-identifier/ac-ntw:id"; + require-instance false; + } + description + "An absolute reference to a routing profile."; + } + uses nw:network-ref; + } + + // L2 conenction + + grouping l2-connection { + description + "Defines Layer 2 protocols and parameters that are required to + enable AC connectivity on the network side."; + container encapsulation { + description + "Container for Layer 2 encapsulation."; + leaf encap-type { + type identityref { + base vpn-common:encapsulation-type; + } + description + "Tagged interface type."; + } + container dot1q { + when "derived-from-or-self(../encap-type, " + + "'vpn-common:dot1q')" { + description + "Only applies when the type of the tagged interface is + 'dot1q'."; + } + description + "Tagged interface."; + uses ac-common:dot1q; + container tag-operations { + description + "Sets the tag manipulation policy for this AC. It defines + a set of tag manipulations that allow for the insertion, + removal, or rewriting of 802.1Q VLAN tags. These + operations are indicated for the CE-PE direction. + By default, tag operations are symmetric. As such, the + reverse tag operation is assumed on the PE-CE + direction."; + choice op-choice { + description + "Selects the tag rewriting policy for an AC."; + leaf pop { + type empty; + description + "Pop the outer tag."; + } + leaf push { + type empty; + description + "Pushes one or two tags defined by the tag-1 and + tag-2 leaves. It is assumed that, absent any + policy, the default value of 0 will be used for + the PCP setting."; + } + leaf translate { + type empty; + description + "Translates the outer tag to one or two tags. PCP + bits are preserved."; + } + } + leaf tag-1 { + when 'not(../pop)'; + type dot1q-types:vlanid; + description + "A first tag to be used for push or translate + operations. This tag will be used as the outermost tag + as a result of the tag operation."; + } + leaf tag-1-type { + type dot1q-types:dot1q-tag-type; + default "dot1q-types:s-vlan"; + description + "Specifies a specific 802.1Q tag type of tag-1."; + } + leaf tag-2 { + when '(../translate)'; + type dot1q-types:vlanid; + description + "A second tag to be used for translation."; + } + leaf tag-2-type { + type dot1q-types:dot1q-tag-type; + default "dot1q-types:c-vlan"; + description + "Specifies a specific 802.1Q tag type of tag-2."; + } + } + } + container priority-tagged { + when "derived-from-or-self(../encap-type, " + + "'vpn-common:priority-tagged')" { + description + "Only applies when the type of the tagged interface is + 'priority-tagged'."; + } + description + "Priority tagged container."; + uses ac-common:priority-tagged; + } + container qinq { + when "derived-from-or-self(../encap-type, " + + "'vpn-common:qinq')" { + description + "Only applies when the type of the tagged interface is + 'QinQ'."; + } + description + "Includes QinQ parameters."; + uses ac-common:qinq; + container tag-operations { + description + "Sets the tag manipulation policy for this AC. It defines + a set of tag manipulations that allow for the insertion, + removal, or rewriting of 802.1Q VLAN tags. These + operations are indicated for the CE-PE direction. + By default, tag operations are symmetric. As such, the + reverse tag operation is assumed on the PE-CE + direction."; + choice op-choice { + description + "Selects the tag rewriting policy for a AC."; + leaf pop { + type uint8 { + range "1|2"; + } + description + "Pops one or two tags as a function of the indicated + pop value."; + } + leaf push { + type empty; + description + "Pushes one or two tags defined by the tag-1 and + tag-2 leaves. It is assumed that, absent any + policy, the default value of 0 will be used for + PCP setting."; + } + leaf translate { + type uint8 { + range "1|2"; + } + description + "Translates one or two outer tags. PCP bits are + preserved. The following operations are supported: + + - translate 1 with tag-1 leaf is provided: only the + outermost tag is translated to the value in tag-1. + + - translate 2 with both tag-1 and tag-2 leaves are + provided: both outer and inner tags are translated + to the values in tag-1 and tag-2, respectively. + + - translate 2 with tag-1 leaf is provided: the + outer tag is popped while the inner tag is + translated to the value in tag-1."; + } + } + leaf tag-1 { + when 'not(../pop)'; + type dot1q-types:vlanid; + description + "A first tag to be used for push or translate + operations. This tag will be used as the outermost tag + as a result of the tag operation."; + } + leaf tag-1-type { + type dot1q-types:dot1q-tag-type; + default "dot1q-types:s-vlan"; + description + "Specifies a specific 802.1Q tag type of tag-1."; + } + leaf tag-2 { + when 'not(../pop)'; + type dot1q-types:vlanid; + description + "A second tag to be used for push or translate + operations."; + } + leaf tag-2-type { + type dot1q-types:dot1q-tag-type; + default "dot1q-types:c-vlan"; + description + "Specifies a specific 802.1Q tag type of tag-2."; + } + } + } + } + choice l2-service { + description + "The Layer 2 connectivity service can be provided by + indicating a pointer to an L2VPN or by specifying a Layer 2 + tunnel service."; + container l2-tunnel-service { + description + "Defines a Layer 2 tunnel termination."; + uses ac-common:l2-tunnel-service; + } + case l2vpn { + leaf l2vpn-id { + type vpn-common:vpn-id; + description + "Indicates the L2VPN service associated with an + Integrated Routing and Bridging (IRB) interface."; + } + } + } + } + + grouping l2-connection-if-ref { + description + "Specifies Layer 2 connection paramters with interface + references."; + uses l2-connection; + leaf l2-termination-point { + type string; + description + "Specifies a reference to a local Layer 2 termination point, + such as a Layer 2 sub-interface."; + } + leaf local-bridge-reference { + type string; + description + "Specifies a local bridge reference to accommodate, e.g., + implementations that require internal bridging. + A reference may be a local bridge domain."; + } + leaf bearer-reference { + if-feature "ac-common:server-assigned-reference"; + type string; + description + "This is an internal reference for the service provider to + identify the bearer associated with this AC."; + } + container lag-interface { + if-feature "vpn-common:lag-interface"; + description + "Container for configuration of Link Aggregation Group (LAG) + interface attributes."; + leaf lag-interface-id { + type string; + description + "LAG interface identifier."; + } + container member-link-list { + description + "Container for the member link list."; + list member-link { + key "name"; + description + "Member link."; + leaf name { + type string; + description + "Member link name."; + } + } + } + } + } + + // IPv4 connection groupings + + grouping ipv4-connection { + description + "IPv4-specific parameters."; + leaf local-address { + type inet:ipv4-address; + description + "The IP address used at the provider's interface."; + } + uses ac-common:ipv4-allocation-type; + choice allocation-type { + description + "Choice of the IPv4 address allocation."; + case dynamic { + description + "When the addresses are allocated by DHCP or other + dynamic means local to the infrastructure."; + choice address-assign { + description + "A choice for how IPv4 addresses are assigned."; + case number { + leaf number-of-dynamic-address { + type uint16; + description + "Specifies the number of IP addresses to be + assigned to the customer on this access."; + } + } + case explicit { + container customer-addresses { + description + "Container for customer addresses to be allocated + using DHCP."; + list address-pool { + key "pool-id"; + description + "Describes IP addresses to be dyncamically + allocated. + + When only 'start-address' is present, it + represents a single address. + + When both 'start-address' and 'end-address' are + specified, it implies a range inclusive of both + addresses."; + leaf pool-id { + type string; + description + "A pool identifier for the address range from + 'start-address' to 'end-address'."; + } + leaf start-address { + type inet:ipv4-address; + mandatory true; + description + "Indicates the first address in the pool."; + } + leaf end-address { + type inet:ipv4-address; + description + "Indicates the last address in the pool."; + } + } + } + } + } + choice provider-dhcp { + description + "Parameters related to DHCP-allocated addresses. + IP addresses are allocated by DHCP, which is provided + by the operator."; + leaf dhcp-service-type { + type enumeration { + enum server { + description + "Local DHCP server."; + } + enum relay { + description + "Local DHCP relay. DHCP requests are relayed to a + provider's server."; + } + } + description + "Indicates the type of DHCP service to be enabled on + this access."; + } + choice service-type { + description + "Choice based on the DHCP service type."; + case relay { + description + "Container for a list of the provider's DHCP servers + (i.e., 'dhcp-service-type' is set to 'relay')."; + leaf-list server-ip-address { + type inet:ipv4-address; + description + "IPv4 addresses of the provider's DHCP server, for + use by the local DHCP relay."; + } + } + } + } + choice dhcp-relay { + description + "The DHCP relay is provided by the operator."; + container customer-dhcp-servers { + description + "Container for a list of the customer's DHCP servers."; + leaf-list server-ip-address { + type inet:ipv4-address; + description + "IPv4 addresses of the customer's DHCP server."; + } + } + } + } + case static-addresses { + description + "Lists the IPv4 addresses that are used."; + list address { + key "address-id"; + ordered-by user; + description + "Lists the IPv4 addresses that are used. The first + address of the list is the primary address of the + connection."; + leaf address-id { + type string; + description + "An identifier of the static IPv4 address."; + } + leaf customer-address { + type inet:ipv4-address; + description + "An IPv4 address of the customer side."; + } + uses failure-detection-profile-reference; + } + } + } + } + + grouping ipv6-connection { + description + "IPv6-specific parameters."; + leaf local-address { + type inet:ipv6-address; + description + "IPv6 address of the provider side."; + } + uses ac-common:ipv6-allocation-type; + choice allocation-type { + description + "Choice of the IPv6 address allocation."; + case dynamic { + description + "When the addresses are allocated by DHCP or other + dynamic means local to the infrastructure."; + choice address-assign { + description + "A choice for how IPv6 addresses are assigned."; + case number { + leaf number-of-dynamic-address { + type uint16; + description + "Specifies the number of IP addresses to be + assigned to the customer on this access."; + } + } + case explicit { + container customer-addresses { + description + "Container for customer addresses to be allocated + using DHCP."; + list address-pool { + key "pool-id"; + description + "Describes IP addresses to be dyncamically + allocated. + + When only 'start-address' is present, it + represents a single address. + + When both 'start-address' and 'end-address' are + specified, it implies a range inclusive of both + addresses."; + leaf pool-id { + type string; + description + "A pool identifier for the address range from + 'start-address' to 'end-address'."; + } + leaf start-address { + type inet:ipv6-address; + mandatory true; + description + "Indicates the first address in the pool."; + } + leaf end-address { + type inet:ipv6-address; + description + "Indicates the last address in the pool."; + } + } + } + } + } + choice provider-dhcp { + description + "Parameters related to DHCP-allocated addresses. + IP addresses are allocated by DHCP, which is provided + by the operator."; + leaf dhcp-service-type { + type enumeration { + enum server { + description + "Local DHCP server."; + } + enum relay { + description + "Local DHCP relay. DHCP requests are relayed to + a provider's server."; + } + } + description + "Indicates the type of DHCP service to + be enabled on this access."; + } + choice service-type { + description + "Choice based on the DHCP service type."; + case relay { + description + "Container for a list of the provider's DHCP servers + (i.e., 'dhcp-service-type' is set to 'relay')."; + leaf-list server-ip-address { + type inet:ipv6-address; + description + "IPv6 addresses of the provider's DHCP server, for + use by the local DHCP relay."; + } + } + } + } + choice dhcp-relay { + description + "The DHCP relay is provided by the operator."; + container customer-dhcp-servers { + description + "Container for a list of the customer's DHCP servers."; + leaf-list server-ip-address { + type inet:ipv6-address; + description + "IPv6 addresses of the customer's DHCP server."; + } + } + } + } + case static-addresses { + description + "Lists the IPv4 addresses that are used."; + list address { + key "address-id"; + ordered-by user; + description + "Lists the IPv6 addresses that are used. The first + address of the list is the primary address of + the connection."; + leaf address-id { + type string; + description + "An identifier of the static IPv4 address."; + } + leaf customer-address { + type inet:ipv6-address; + description + "An IPv6 address of the customer side."; + } + uses failure-detection-profile-reference; + } + } + } + } + + grouping ip-connection { + description + "Defines IP connection parameters."; + leaf l3-termination-point { + type string; + description + "Specifies a reference to a local Layer 3 termination point, + such as a bridge domain interface."; + } + container ipv4 { + if-feature "vpn-common:ipv4"; + description + "IPv4-specific parameters."; + uses ipv4-connection; + } + container ipv6 { + if-feature "vpn-common:ipv6"; + description + "IPv6-specific parameters."; + uses ipv6-connection; + } + } + + /* Routing */ + //BGP base parameters + + grouping bgp-base { + description + "Configuration specific to BGP."; + leaf description { + type string; + description + "Includes a description of the BGP session. This description + is meant to be used for diagnostic purposes. The semantic + of the description is local to an implementation."; + } + uses rt-pol:apply-policy-group; + leaf local-as { + type inet:as-number; + description + "Indicates a local AS Number (ASN), if an ASN distinct from + the ASN configured at the AC level is needed."; + } + leaf peer-as { + type inet:as-number; + mandatory true; + description + "Indicates the customer's ASN when the customer requests BGP + routing."; + } + leaf address-family { + type identityref { + base vpn-common:address-family; + } + description + "This node contains the address families to be activated. + 'dual-stack' means that both IPv4 and IPv6 will be + activated."; + } + leaf role { + type identityref { + base ac-common:bgp-role; + } + description + "Specifies the BGP role (provider, customer, peer, etc.)."; + } + leaf multihop { + type uint8; + description + "Describes the number of IP hops allowed between a given BGP + neighbor and the PE."; + } + leaf as-override { + type boolean; + description + "Defines whether ASN override is enabled, i.e., replacing the + ASN of the customer specified in the AS_PATH attribute with + the local ASN."; + } + leaf allow-own-as { + type uint8; + description + "If set, specifies the maximum number of occurrences of the + provider's ASN that are permitted within the AS_PATH + before it is rejected."; + } + leaf prepend-global-as { + type boolean; + description + "In some situations, the ASN that is provided at the node + level may be distinct from the ASN configured at the AC. + When such ASNs are provided, they are both prepended to the + BGP route updates for this AC. To disable that behavior, + 'prepend-global-as' must be set to 'false'. In such a + case, the ASN that is provided at the node level is not + prepended to the BGP route updates for this access."; + } + leaf send-default-route { + type boolean; + description + "Defines whether default routes can be advertised to a peer. + If set, the default routes are advertised to a peer."; + } + leaf site-of-origin { + when "derived-from-or-self(../address-family, " + + "'vpn-common:ipv4' or 'vpn-common:dual-stack')" { + description + "Only applies if IPv4 is activated."; + } + type rt-types:route-origin; + description + "The Site of Origin attribute is encoded as a Route Origin + Extended Community. It is meant to uniquely identify the + set of routes learned from a site via a particular AC and + is used to prevent routing loops."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs), + Section 7"; + } + leaf ipv6-site-of-origin { + when "derived-from-or-self(../address-family, " + + "'vpn-common:ipv6' or 'vpn-common:dual-stack')" { + description + "Only applies if IPv6 is activated."; + } + type rt-types:ipv6-route-origin; + description + "The IPv6 Site of Origin attribute is encoded as an IPv6 + Route Origin Extended Community. It is meant to uniquely + identify the set of routes learned from a site."; + reference + "RFC 5701: IPv6 Address Specific BGP Extended Community + Attribute"; + } + list redistribute-connected { + key "address-family"; + description + "Indicates, per address family, the policy to follow for + connected routes."; + leaf address-family { + type identityref { + base vpn-common:address-family; + } + description + "Indicates the address family."; + } + leaf enabled { + type boolean; + description + "Enables the redistribution of connected routes."; + } + } + container bgp-max-prefix { + description + "Controls the behavior when a prefix maximum is reached."; + leaf max-prefix { + type uint32; + description + "Indicates the maximum number of BGP prefixes allowed in + the BGP session. + + It allows control of how many prefixes can be received + from a neighbor. + + If the limit is exceeded, the action indicated in + 'violate-action' will be followed."; + reference + "RFC 4271: A Border Gateway Protocol 4 (BGP-4), + Section 8.2.2"; + } + leaf warning-threshold { + type decimal64 { + fraction-digits 5; + range "0..100"; + } + units "percent"; + description + "When this value is reached, a warning notification will be + triggered."; + } + leaf violate-action { + type enumeration { + enum warning { + description + "Only a warning message is sent to the peer when the + limit is exceeded."; + } + enum discard-extra-paths { + description + "Discards extra paths when the limit is exceeded."; + } + enum restart { + description + "The BGP session restarts after the indicated time + interval."; + } + } + description + "If the BGP neighbor 'max-prefix' limit is reached, the + action indicated in 'violate-action' will be followed."; + } + leaf restart-timer { + type uint32; + units "seconds"; + description + "Time interval after which the BGP session will be + reestablished."; + } + } + container bgp-timers { + description + "Includes two BGP timers."; + leaf keepalive { + type uint16 { + range "0..21845"; + } + units "seconds"; + description + "This timer indicates the KEEPALIVE messages' frequency + between a PE and a BGP peer. + + If set to '0', it indicates that KEEPALIVE messages are + disabled. + + It is suggested that the maximum time between KEEPALIVE + messages be one-third of the Hold Time interval."; + reference + "RFC 4271: A Border Gateway Protocol 4 (BGP-4), + Section 4.4"; + } + leaf hold-time { + type uint16 { + range "0 | 3..65535"; + } + units "seconds"; + description + "Indicates the maximum number of seconds that may elapse + between the receipt of successive KEEPALIVE and/or UPDATE + messages from the peer. + + The Hold Time must be either zero or at least three + seconds."; + reference + "RFC 4271: A Border Gateway Protocol 4 (BGP-4), + Section 4.2"; + } + } + } + + grouping bgp-base-peer-group { + description + "Grouping for a basic BGP peer group."; + leaf name { + type string; + description + "Name of the BGP peer-group"; + } + uses bgp-base; + } + + grouping bgp-base-peer-group-list { + description + "Grouping for a list of basic BGP peer groups."; + list peer-group { + key "name"; + description + "List of BGP peer groups uniquely identified by a name."; + uses bgp-base-peer-group; + } + } + + grouping bgp-peer-group { + description + "Grouping for BGP peer group."; + leaf name { + type string; + description + "Name of the BGP peer-group"; + } + leaf local-address { + type union { + type inet:ip-address; + type if:interface-ref; + } + description + "Sets the local IP address to use for the BGP + transport session. This may be expressed as either + an IP address or a reference to an interface."; + } + uses bgp-base; + uses ac-common:bgp-authentication; + } + + grouping bgp-peer-group-list { + description + "Grouping for a list of BGP peer groups."; + list peer-group { + key "name"; + description + "List of BGP peer groups uniquely identified by a name."; + uses bgp-peer-group; + } + } + + // RIP base parameters + + grouping rip-base { + description + "Configuration specific to RIP routing."; + leaf address-family { + type identityref { + base vpn-common:address-family; + } + description + "Indicates whether IPv4, IPv6, or both address families are + to be activated."; + } + container timers { + description + "Indicates the RIP timers."; + reference + "RFC 2080: RIPng for IPv6 + RFC 2453: RIP Version 2"; + leaf update-interval { + type uint16 { + range "1..32767"; + } + units "seconds"; + description + "Indicates the RIP update time, i.e., the amount of time + for which RIP updates are sent."; + } + leaf invalid-interval { + type uint16 { + range "1..32767"; + } + units "seconds"; + description + "The interval before a route is declared invalid after no + updates are received. This value is at least three times + the value for the 'update-interval' argument."; + } + leaf holddown-interval { + type uint16 { + range "1..32767"; + } + units "seconds"; + description + "Specifies the interval before better routes are + released."; + } + leaf flush-interval { + type uint16 { + range "1..32767"; + } + units "seconds"; + description + "Indicates the RIP flush timer, i.e., the amount of time + that must elapse before a route is removed from the + routing table."; + } + } + leaf default-metric { + type uint8 { + range "0..16"; + } + description + "Sets the default metric."; + } + } + + // routing profile + + grouping routing-profile { + description + "Defines routing protocols."; + list routing-protocol { + key "id"; + description + "List of routing protocols used on the AC."; + leaf id { + type string; + description + "Unique identifier for the routing protocol."; + } + leaf type { + type identityref { + base vpn-common:routing-protocol-type; + } + description + "Type of routing protocol."; + } + container bgp { + when "derived-from-or-self(../type, " + + "'vpn-common:bgp-routing')" { + description + "Only applies when the protocol is BGP."; + } + if-feature "vpn-common:rtg-bgp"; + description + "Configuration specific to BGP."; + container peer-groups { + description + "Lists a set of BGP peer groups."; + uses bgp-base-peer-group-list; + } + } + container ospf { + when "derived-from-or-self(../type, " + + "'vpn-common:ospf-routing')" { + description + "Only applies when the protocol is OSPF."; + } + if-feature "vpn-common:rtg-ospf"; + description + "Configuration specific to OSPF."; + uses ac-common:ospf-basic; + leaf max-lsa { + type uint32 { + range "1..4294967294"; + } + description + "Maximum number of allowed Link State Advertisements + (LSAs) that the OSPF instance will accept."; + } + leaf passive { + type boolean; + description + "Enables when set to true a passive interface. It is + active when set to false. A passive interface's prefix + will be advertised, but no neighbor adjacencies will be + formed on the interface."; + } + } + container isis { + when "derived-from-or-self(../type, " + + "'vpn-common:isis-routing')" { + description + "Only applies when the protocol is IS-IS."; + } + if-feature "vpn-common:rtg-isis"; + description + "Configuration specific to IS-IS."; + uses ac-common:isis-basic; + leaf level { + type identityref { + base vpn-common:isis-level; + } + description + "Can be 'level-1', 'level-2', or 'level-1-2'."; + reference + "RFC 9181: A Common YANG Data Model for Layer 2 + and Layer 3 VPNs"; + } + leaf metric { + type uint32 { + range "0 .. 16777215"; + } + description + "Metric of the AC. It is used in the routing state + calculation and path selection."; + } + leaf passive { + type boolean; + description + "When set to false, the interface is active. In such + mode, the interface sends or receives IS-IS protocol + control packets. + + When set to true, the interface is passive. That is, + it suppresses the sending of IS-IS updates through the + specified interface."; + } + } + container rip { + when "derived-from-or-self(../type, " + + "'vpn-common:rip-routing')" { + description + "Only applies when the protocol is RIP."; + } + if-feature "vpn-common:rtg-rip"; + description + "Configuration specific to RIP routing."; + uses rip-base; + } + container vrrp { + when "derived-from-or-self(../type, " + + "'vpn-common:vrrp-routing')" { + description + "Only applies when the protocol is the Virtual Router + Redundancy Protocol (VRRP)."; + } + if-feature "vpn-common:rtg-vrrp"; + description + "Configuration specific to VRRP."; + reference + "RFC 9568: Virtual Router Redundancy Protocol (VRRP) + Version 3 for IPv4 and IPv6"; + leaf address-family { + type identityref { + base vpn-common:address-family; + } + description + "Indicates whether IPv4, IPv6, or both address families + are to be enabled."; + } + leaf ping-reply { + type boolean; + description + "Controls whether the VRRP speaker should reply to ping + requests."; + } + } + } + } + + grouping routing { + description + "Defines routing protocols."; + list routing-protocol { + key "id"; + description + "List of routing protocols used on the AC."; + leaf id { + type string; + description + "Unique identifier for the routing protocol."; + } + leaf type { + type identityref { + base vpn-common:routing-protocol-type; + } + description + "Type of routing protocol."; + } + list routing-profile { + key "routing-profile-ref"; + description + "Routing profiles."; + uses routing-profile-reference; + leaf type { + type identityref { + base vpn-common:ie-type; + } + description + "Import, export, or both."; + } + } + container static { + when "derived-from-or-self(../type, " + + "'vpn-common:static-routing')" { + description + "Only applies when the protocol is a static routing + protocol."; + } + description + "Configuration specific to static routing."; + container cascaded-lan-prefixes { + description + "LAN prefixes from the customer."; + list ipv4-lan-prefix { + if-feature "vpn-common:ipv4"; + key "lan next-hop"; + description + "List of LAN prefixes for the site."; + uses ac-common:ipv4-static-rtg-entry; + uses bfd-routing; + leaf preference { + type uint32; + description + "Indicates the preference associated with the static + route."; + } + uses ac-common:service-status; + } + list ipv6-lan-prefix { + if-feature "vpn-common:ipv6"; + key "lan next-hop"; + description + "List of LAN prefixes for the site."; + uses ac-common:ipv6-static-rtg-entry; + uses bfd-routing; + leaf preference { + type uint32; + description + "Indicates the preference associated with the static + route."; + } + uses ac-common:service-status; + } + } + } + container bgp { + when "derived-from-or-self(../type, " + + "'vpn-common:bgp-routing')" { + description + "Only applies when the protocol is BGP."; + } + if-feature "vpn-common:rtg-bgp"; + description + "Configuration specific to BGP."; + container peer-groups { + description + "Configuration for BGP peer-groups"; + uses bgp-peer-group-list; + } + list neighbor { + key "remote-address"; + description + "List of BGP neighbors."; + leaf remote-address { + type inet:ip-address; + description + "The remote IP address of this entry's BGP peer."; + } + leaf local-address { + type union { + type inet:ip-address; + type if:interface-ref; + } + description + "Sets the local IP address to use for + the BGP transport session. This may be + expressed as either an IP address or a + reference to an interface."; + } + leaf peer-group { + type leafref { + path "../../peer-groups/peer-group/name"; + } + description + "The peer-group with which this neighbor is + associated."; + } + uses bgp-base; + uses bfd-routing; + uses ac-common:bgp-authentication; + uses ac-common:service-status; + } + } + container ospf { + when "derived-from-or-self(../type, " + + "'vpn-common:ospf-routing')" { + description + "Only applies when the protocol is OSPF."; + } + if-feature "vpn-common:rtg-ospf"; + description + "Configuration specific to OSPF."; + uses ac-common:ospf-basic; + container sham-links { + if-feature "vpn-common:rtg-ospf-sham-link"; + description + "List of sham links."; + reference + "RFC 4577: OSPF as the Provider/Customer Edge Protocol + for BGP/MPLS IP Virtual Private Networks + (VPNs), Section 4.2.7 + RFC 6565: OSPFv3 as a Provider Edge to Customer Edge + (PE-CE) Routing Protocol, Section 5"; + list sham-link { + key "target-site"; + description + "Creates a sham link with another + site."; + leaf target-site { + type string; + description + "Target site for the sham link connection. The site + is referred to by its identifier."; + } + leaf metric { + type uint16; + description + "Metric of the sham link. It is used in the routing + state calculation and path selection."; + reference + "RFC 4577: OSPF as the Provider/Customer Edge + Protocol for BGP/MPLS IP Virtual Private + Networks (VPNs), Section 4.2.7.3 + RFC 6565: OSPFv3 as a Provider Edge to Customer Edge + (PE-CE) Routing Protocol, Section 5.2"; + } + } + } + leaf max-lsa { + type uint32 { + range "1..4294967294"; + } + description + "Maximum number of allowed Link State Advertisements + (LSAs) that the OSPF instance will accept."; + } + leaf passive { + type boolean; + description + "Enables when set to true a passive interface. It is + active when set to false. A passive interface's prefix + will be advertised, but no neighbor adjacencies will be + formed on the interface."; + } + uses ac-common:ospf-authentication; + uses ac-common:service-status; + } + container isis { + when "derived-from-or-self(../type, " + + "'vpn-common:isis-routing')" { + description + "Only applies when the protocol is IS-IS."; + } + if-feature "vpn-common:rtg-isis"; + description + "Configuration specific to IS-IS."; + uses ac-common:isis-basic; + leaf level { + type identityref { + base vpn-common:isis-level; + } + description + "Can be 'level-1', 'level-2', or 'level-1-2'."; + reference + "RFC 9181: A Common YANG Data Model for Layer 2 and + Layer 3 VPNs"; + } + leaf metric { + type uint32 { + range "0 .. 16777215"; + } + description + "Metric of the AC. It is used in the routing state + calculation and path selection."; + } + leaf passive { + type boolean; + description + "When set to false, the interface is active. In such + mode, the interface sends or receives IS-IS protocol + control packets. + + When set to true, the interface is passive. That is, + it suppresses the sending of IS-IS updates through the + specified interface."; + } + uses ac-common:isis-authentication; + uses ac-common:service-status; + } + container rip { + when "derived-from-or-self(../type, " + + "'vpn-common:rip-routing')" { + description + "Only applies when the protocol is RIP. + For IPv4, the model assumes that RIP + version 2 is used."; + } + if-feature "vpn-common:rtg-rip"; + description + "Configuration specific to RIP routing."; + uses rip-base; + uses ac-common:rip-authentication; + uses ac-common:service-status; + } + container vrrp { + when "derived-from-or-self(../type, " + + "'vpn-common:vrrp-routing')" { + description + "Only applies when the protocol is the VRRP."; + } + if-feature "vpn-common:rtg-vrrp"; + description + "Configuration specific to VRRP."; + reference + "RFC 9568: Virtual Router Redundancy Protocol (VRRP) + Version 3 for IPv4 and IPv6"; + leaf address-family { + type identityref { + base vpn-common:address-family; + } + description + "Indicates whether IPv4, IPv6, or both address families + are to be enabled."; + } + leaf vrrp-group { + type uint8 { + range "1..255"; + } + description + "Includes the VRRP group identifier."; + } + leaf backup-peer { + type inet:ip-address; + description + "Indicates the IP address of the peer."; + } + leaf-list virtual-ip-address { + type inet:ip-address; + description + "Virtual IP addresses for a single VRRP + group."; + reference + "RFC 9568: Virtual Router Redundancy Protocol (VRRP) + Version 3 for IPv4 and IPv6, Sections 1.2 + and 1.3"; + } + leaf priority { + type uint8 { + range "1..254"; + } + description + "Sets the local priority of the VRRP speaker."; + } + leaf ping-reply { + type boolean; + description + "Controls whether the VRRP speaker should reply to ping + requests."; + } + uses ac-common:service-status; + } + } + } + + // OAM + + grouping bfd { + description + "Grouping for BFD."; + leaf session-type { + type identityref { + base vpn-common:bfd-session-type; + } + description + "Specifies the BFD session type."; + } + leaf desired-min-tx-interval { + type uint32; + units "microseconds"; + description + "The minimum interval between transmissions of BFD Control + packets, as desired by the operator."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD), + Section 6.8.7"; + } + leaf required-min-rx-interval { + type uint32; + units "microseconds"; + description + "The minimum interval between received BFD Control packets + that the PE should support."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD), + Section 6.8.7"; + } + leaf local-multiplier { + type uint8 { + range "1..255"; + } + description + "Specifies the detection multiplier that is transmitted to a + BFD peer. + + The detection interval for the receiving BFD peer is + calculated by multiplying the value of the negotiated + transmission interval by the received detection multiplier + value."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD), + Section 6.8.7"; + } + leaf holdtime { + type uint32; + units "milliseconds"; + description + "Expected BFD holdtime. + + The customer may impose some fixed values for the holdtime + period if the provider allows the customer to use this + function."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD), + Section 6.8.18"; + } + } + + grouping bfd-routing { + description + "Defines a basic BFD grouping for routing configuration."; + container bfd { + if-feature "vpn-common:bfd"; + description + "BFD control for this nighbor."; + leaf enabled { + type boolean; + description + "Enables BFD if set to true. BFD is disabled of set to + false."; + } + uses failure-detection-profile-reference; + } + } + + // OAM + + grouping oam { + description + "Defines the Operations, Administration, and Maintenance + (OAM) mechanisms used."; + container bfd { + if-feature "vpn-common:bfd"; + description + "Container for BFD."; + list session { + key "dest-addr"; + description + "List of IP sessions."; + leaf dest-addr { + type inet:ip-address; + description + "IP address of the peer."; + } + leaf source-address { + type union { + type inet:ip-address; + type if:interface-ref; + } + description + "Sets the local IP address to use for the BFD + session. This may be expressed as either + an IP address or a reference to an interface."; + } + uses failure-detection-profile-reference; + uses bfd; + container authentication { + presence "Enables BFD authentication"; + description + "Parameters for BFD authentication."; + leaf key-chain { + type key-chain:key-chain-ref; + description + "Name of the key chain."; + } + leaf meticulous { + type boolean; + description + "Enables meticulous mode."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD), + Section 6.7"; + } + } + uses ac-common:service-status; + } + } + } + + // security + + grouping security { + description + "Security parameters for an AC."; + container encryption { + if-feature "vpn-common:encryption"; + description + "Container for AC encryption."; + leaf enabled { + type boolean; + description + "If set to 'true', traffic encryption on the connection is + required. Otherwise, it is disabled."; + } + leaf layer { + when "../enabled = 'true'" { + description + "Included only when encryption is enabled."; + } + type enumeration { + enum layer2 { + description + "Encryption occurs at Layer 2."; + } + enum layer3 { + description + "Encryption occurs at Layer 3. For example, IPsec + may be used when a customer requests Layer 3 + encryption."; + } + } + description + "Indicates the layer on which encryption is applied."; + } + } + container encryption-profile { + when "../encryption/enabled = 'true'" { + description + "Indicates the layer on which encryption is enabled."; + } + description + "Container for the encryption profile."; + choice profile { + description + "Choice for the encryption profile."; + case provider-profile { + uses encryption-profile-reference; + } + case customer-profile { + leaf customer-key-chain { + type key-chain:key-chain-ref; + description + "Customer-supplied key chain."; + } + } + } + } + } + + // AC profile + + grouping ac-profile { + description + "Grouping for attachment circuit profiles."; + container routing-protocols { + description + "Defines routing protocols."; + uses routing-profile; + } + container oam { + description + "Defines the OAM mechanisms used for the AC profile."; + container bfd { + if-feature "vpn-common:bfd"; + description + "Container for BFD."; + uses bfd; + } + } + } + + // Parent and Child ACs + + grouping ac-hierarchy { + description + "Container for parent and child AC references."; + container parent-ref { + description + "Specifies the parent AC that is inherited by an AC. + Parent ACs are used, e.g., in contexts where multiple + CEs are terminating the same AC, but some specific + information is required for each peer SAP."; + uses ac-ntw:attachment-circuit-reference; + } + container child-ref { + config false; + description + "Specifies a child AC that relies upon a parent AC."; + uses ac-ntw:attachment-circuit-references; + } + } + + // AC network provisioning + + grouping ac { + description + "Grouping for attachment circuits."; + leaf description { + type string; + description + "Associates a description with an AC."; + } + container l2-connection { + if-feature "ac-common:layer2-ac"; + description + "Defines Layer 2 protocols and parameters that are required + to enable AC connectivity."; + uses l2-connection-if-ref; + } + container ip-connection { + if-feature "ac-common:layer3-ac"; + description + "Defines IP connection parameters."; + uses ip-connection; + } + container routing-protocols { + description + "Defines routing protocols."; + uses routing; + } + container oam { + description + "Defines the OAM mechanisms used for the AC."; + uses oam; + } + container security { + description + "AC-specific security parameters."; + uses security; + } + container service { + description + "AC-specific bandwith parameters."; + leaf mtu { + type uint32; + units "bytes"; + description + "Layer 2 MTU."; + } + uses ac-svc:bandwidth; + container qos { + if-feature "vpn-common:qos"; + description + "QoS configuration."; + container qos-profiles { + description + "QoS profile configuration."; + list qos-profile { + key "qos-profile-ref"; + description + "Points to a QoS profile."; + uses qos-profile-reference; + leaf direction { + type identityref { + base vpn-common:qos-profile-direction; + } + description + "The direction to which the QoS profile + is applied."; + } + } + } + } + container access-control-list { + description + "Container for the Access Control List (ACL)."; + container acl-profiles { + description + "ACL profile configuration."; + list acl-profile { + key "forwarding-profile-ref"; + description + "Points to an ACL profile."; + uses forwarding-profile-reference; + } + } + } + } + } + + augment "/nw:networks/nw:network" { + description + "Add a list of profiles."; + container specific-provisioning-profiles { + description + "Contains a set of valid profiles to reference in the AC + activation."; + uses ac-common:ac-profile-cfg; + } + list ac-profile { + key "name"; + description + "Specifies a list of AC profiles."; + leaf name { + type string; + description + "Name of the AC."; + } + uses ac-ntw:ac-profile; + } + } + + augment "/nw:networks/nw:network/nw:node" { + when '../nw:network-types/sap:sap-network' { + description + "Augmentation parameters apply only for SAP networks."; + } + description + "Augments nodes with AC provisioning details."; + list ac { + key "name"; + description + "List of ACs."; + leaf name { + type string; + description + "A name that identifies the AC locally."; + } + leaf svc-ref { + type ac-svc:attachment-circuit-reference; + description + "A reference to the AC as exposed at the service level."; + } + list profile { + key "ac-profile-ref"; + description + "List of AC profiles."; + uses ac-profile-reference; + } + uses ac-hierarchy; + leaf-list peer-sap-id { + type string; + description + "One or more peer SAPs can be indicated."; + } + uses ac-common:redundancy-group; + uses ac-common:service-status; + uses ac-ntw:ac; + } + } + + augment "/nw:networks/nw:network/nw:node" + + "/sap:service/sap:sap" { + when '../../../nw:network-types/sap:sap-network' { + description + "Augmentation parameters apply only for SAP networks."; + } + description + "Augments SAPs with AC provisioning details."; + list ac { + key "ac-ref"; + description + "Specifies the ACs that are terminated by the SAP."; + uses ac-ntw:attachment-circuit-reference; + } + } +} \ No newline at end of file diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-eth-te-topology@2023-09-28.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-eth-te-topology@2023-09-28.yang new file mode 100644 index 000000000..b182f7f5a --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-eth-te-topology@2023-09-28.yang @@ -0,0 +1,2275 @@ + module ietf-eth-te-topology { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-eth-te-topology"; + prefix "etht"; + + import ietf-network { + prefix "nw"; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + + import ietf-network-topology { + prefix "nt"; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + + import ietf-te-topology { + prefix "tet"; + reference + "RFC 8795: YANG Data Model for Traffic Engineering + (TE) Topologies"; + } + + import ietf-yang-types { + prefix "yang"; + reference + "RFC 6991: Common YANG Data Types"; + } + + import ietf-eth-tran-types { + prefix "etht-types"; + reference + "RFC YYYY: A YANG Data Model for Transport Network Client + Signals"; + } + // RFC Ed.: replace YYYY with actual RFC number, update date + // information and remove this note + + organization + "IETF CCAMP Working Group"; + contact + "WG Web: + WG List: + + Editor: Haomian Zheng + + + Editor: Italo Busi + + + Editor: Aihua Guo + + + Editor: Yunbin Xu + + + Editor: Yang Zhao + + + Editor: Xufeng Liu + "; + + description + "This module defines a YANG data model for describing + layer-2 Ethernet transport topologies. The model fully + conforms to the Network Management Datastore + Architecture (NMDA). + + Copyright (c) 2023 IETF Trust and the persons identified + as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Revised BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here."; + + revision 2023-09-28 { + description + "Initial Revision"; + reference + "RFC XXXX: A YANG Data Model for Ethernet TE Topology"; + // RFC Ed.: replace XXXX with actual RFC number, update date + // information and remove this note + } + + /* + * Groupings + */ + + grouping label-range-info { + description + "Ethernet technology-specific label range related + information with a presence container indicating that the + label range is an Ethernet technology-specific label range. + + This grouping SHOULD be used together with the + eth-label and eth-label-step groupings to provide Ethernet + technology-specific label information to the models which + use the label-restriction-info grouping defined in the module + ietf-te-types."; + + container ethernet-label-range { + presence + "Indicates the label range is an Ethernet label range. + + This container must not be present if there are other + presence containers or attributes indicating another type + of label range."; + description + "Ethernet-specific label range related information."; + + uses etht-types:eth-label-restriction; + } + } + + grouping eth-tran-topology-type { + description + "Identifies the Ethernet Transport topology type"; + + container eth-tran-topology { + presence "indicates a topology type of + Ethernet Transport Network."; + description "Eth transport topology type"; + } + } + + grouping ltp-bandwidth-profiles { + description + "A grouping which represents the bandwidth profile(s) + for the ETH LTP."; + + choice direction { + description + "Whether the bandwidth profiles are symmetrical or + asymmetrical"; + case symmetrical { + description + "The same bandwidth profile is used to describe the ingress + and the egress bandwidth profile."; + + container ingress-egress-bandwidth-profile { + description + "The bandwith profile used in the ingress and egress + direction."; + uses etht-types:etht-bandwidth-profiles; + } + } + case asymmetrical { + description + "Different ingress and egress bandwidth profiles + can be specified."; + container ingress-bandwidth-profile { + description + "The bandwidth profile used in the ingress direction."; + uses etht-types:etht-bandwidth-profiles; + } + container egress-bandwidth-profile { + description + "The bandwidth profile used in the egress direction."; + uses etht-types:etht-bandwidth-profiles; + } + } + } + } + grouping eth-ltp-attributes { + description + "Ethernet transport Link Termination Point (LTP) attributes"; + + leaf ltp-mac-address { + type yang:mac-address; + description + "The MAC address of the Ethernet LTP."; + } + leaf port-vlan-id { + type etht-types:vlanid; + description + "The Port VLAN ID of the Ethernet LTP."; + reference + "IEEE 802.1Q: Virtual Bridged Local Area Networks"; + } + leaf maximum-frame-size { + type uint16 { + range "64 .. 65535"; + } + description + "Maximum frame size"; + reference + "IEEE 802.1Q: Virtual Bridged Local Area Networks"; + } + uses ltp-bandwidth-profiles; + } + + grouping svc-vlan-classification { + description + "Grouping defining the capabilities for VLAN classification."; + + leaf-list supported-tag-types { + type etht-types:eth-tag-classify; + description + "List of VLAN tag types that can be used for the VLAN + classification. In case VLAN classification is not + supported, the list is empty."; + } + leaf vlan-bundling { + type boolean; + description + "In case VLAN classification is supported, indicates whether + VLAN bundling classification is also supported."; + reference + "MEF 10.3: Ethernet Services Attributes Phase 3"; + } + leaf vlan-range { + type etht-types:vid-range-type; + description + "In case VLAN classification is supported, indicates the + of available VLAN ID values."; + } + } + + grouping svc-vlan-push { + description + "Grouping defining the capabilities for VLAN push or swap + operations."; + + leaf-list supported-tag-types { + type etht-types:eth-tag-type; + description + "List of VLAN tag types that can be used to push or swap a + VLAN tag. In case VLAN push/swap is not supported, the list + is empty."; + reference + "IEEE 802.1Q: Virtual Bridged Local Area Networks"; + } + leaf vlan-range { + type etht-types:vid-range-type; + description + "In case VLAN push/swap operation is supported, the range + of available VLAN ID values."; + } + } + + grouping eth-svc-attributes { + description + "Ethernet Link Termination Point (LTP) service attributes."; + + container supported-classification { + description + "Service classification capability supported by the + Ethernet Link Termination Point (LTP)."; + + leaf port-classification { + type boolean; + description + "Indicates that the ETH LTP support port-based service + classification."; + } + container vlan-classification { + description + "Service classification capabilities based on the VLAN + tag(s) supported by the ETH LTP."; + leaf vlan-tag-classification { + type boolean; + description + "Indicates that the ETH LTP supports VLAN service + classification."; + } + container outer-tag { + description + "Service classification capabilities based on the outer + VLAN tag, supported by the ETH LTP."; + uses svc-vlan-classification; + } + container second-tag { + description + "Service classification capabilities based on the second + VLAN tag, supported by the ETH LTP."; + leaf second-tag-classification { + type boolean; + must ". = 'false' or " + + "../../vlan-tag-classification = 'true'" { + description + "VLAN service classification based on the second + VLAN tag can be supported only when VLAN service + classification"; + } + description + "Indicates that the ETH LTP support VLAN service + classification based on the second VLAN tag."; + } + uses svc-vlan-classification; + } + } + } + + container supported-vlan-operations { + description + "Reports the VLAN operations supported by the ETH LTP."; + + leaf asymmetrical-operations { + type boolean; + description + "Indicates whether the ETH LTP supports also asymmetrical + VLAN operations.It is assumed that symmetrical VLAN + operations are alwyas supported."; + } + leaf transparent-vlan-operations { + type boolean; + description + "Indicates that the ETH LTP supports transparent + operations."; + } + container vlan-pop { + description + "Indicates VLAN pop or swap operations capabilities."; + + leaf vlan-pop-operations { + type boolean; + description + "Indicates that the ETH LTP supports VLAN pop or + swap operations."; + } + leaf max-pop-tags { + type uint8 { + range "1..2"; + } + description + "Indicates the maximum number of tags that can be + popped/swapped."; + } + } + container vlan-push { + description + "Indicates VLAN push or swap operations capabilities."; + + leaf vlan-push-operation { + type boolean; + description + "Indicates that the ETH LTP supports VLAN push or + swap operations."; + } + container outer-tag { + description + "Indicates the supported VLAN operation capabilities + on the outer VLAN tag."; + uses svc-vlan-push; + } + container second-tag { + description + "Indicates the supported VLAN operation capabilities + on the second VLAN tag."; + leaf push-second-tag { + type boolean; + description + "Indicates that the ETH LTP supports VLAN push or swap + operations for the second VLAN tag."; + } + uses svc-vlan-push; + } + } + } + } + + /* + * Data nodes + */ + + augment "/nw:networks/nw:network/nw:network-types/" + + "tet:te-topology" { + description + "Augment network types to include ETH transport newtork"; + + uses eth-tran-topology-type; + } + + augment "/nw:networks/nw:network/nw:node/tet:te" + + "/tet:te-node-attributes" { + when "../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description "Augment only for Ethernet transport network."; + } + description "Augment TE node attributes."; + container eth-node { + presence "The TE node is an Ethernet node."; + description + "Presence container used only to indicate that the TE node + is an Ethernet node."; + } + } + + augment "/nw:networks/nw:network/nt:link" { + when "../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description "Augment only for Ethernet transport network."; + } + description "Augment link configuration"; + + container eth-svc { + presence + "When present, indicates that the Link supports Ethernet + client signals."; + description + "Presence container used only to indicate that the link + supports Ethernet client signals."; + } + } + + augment "/nw:networks/nw:network/nw:node/nt:termination-point" { + when "../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description "Augment only for Ethernet transport network."; + } + description + "Augment ETH LTP attributes"; + + container eth-svc { + presence + "When present, indicates that the Link Termination Point + (LTP) supports Ethernet client signals."; + description + "ETH LTP Service attributes."; + + uses eth-svc-attributes; + } + container eth-link-tp { + description + "Attributes of the Ethernet Link Termination Point (LTP)."; + uses eth-ltp-attributes; + } + } + + /* + * Augment TE bandwidth + */ + + augment "/nw:networks/nw:network/nw:node/nt:termination-point/" + + "tet:te/" + + "tet:interface-switching-capability/tet:max-lsp-bandwidth/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment maximum LSP TE bandwidth for the link termination + point (LTP)."; + case eth { + uses etht-types:eth-bandwidth; + } + } + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE bandwidth path constraints of the TE node + connectivity matrices."; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE bandwidth path constraints of the + connectivity matrix entry."; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE bandwidth path constraints of the TE node + connectivity matrices information source."; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE bandwidth path constraints of the + connectivity matrix entry information source"; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:client-layer-adaptation/tet:switching-capability/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment client TE bandwidth of the tunnel termination point + (TTP)"; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/tet:path-constraints/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE bandwidth path constraints for the TTP + Local Link Connectivities."; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/tet:path-constraints/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE bandwidth path constraints for the TTP + Local Link Connectivity entry."; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:interface-switching-capability/tet:max-lsp-bandwidth/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment maximum LSP TE bandwidth for the TE link."; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:max-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment maximum TE bandwidth for the TE link"; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:max-resv-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment maximum reservable TE bandwidth for the TE link"; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:unreserved-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment unreserved TE bandwidth for the TE Link"; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:interface-switching-capability/" + + "tet:max-lsp-bandwidth/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment maximum LSP TE bandwidth for the TE link + information source"; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:max-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment maximum TE bandwidth for the TE link + information source"; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:max-resv-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment maximum reservable TE bandwidth for the TE link + information-source"; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:unreserved-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment unreserved TE bandwidth of the TE link + information source"; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:interface-switching-capability/" + + "tet:max-lsp-bandwidth/" + + "tet:te-bandwidth/tet:technology" { + description + "Augment maximum LSP TE bandwidth of the TE link + template"; + case eth { + uses etht-types:eth-bandwidth; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:max-link-bandwidth/" + + "tet:te-bandwidth" { + description + "Augment maximum TE bandwidth the TE link template"; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:max-resv-link-bandwidth/" + + "tet:te-bandwidth" { + description + "Augment maximum reservable TE bandwidth for the TE link + template."; + uses etht-types:eth-bandwidth; + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:unreserved-bandwidth/" + + "tet:te-bandwidth" { + description + "Augment unreserved TE bandwidth the TE link template"; + uses etht-types:eth-bandwidth; + } + + /* + * Augment TE label range information + */ + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the TE node + connectivity matrices."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the source LTP + of the connectivity matrix entry."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the destination LTP + of the connectivity matrix entry."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the TE node + connectivity matrices information source."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the source LTP + of the connectivity matrix entry information source."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the destination LTP + of the connectivity matrix entry information source."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the TTP + Local Link Connectivities."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the TTP + Local Link Connectivity entry."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the TE link."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range information for the TE link + information source."; + uses label-range-info; + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction" { + description + "Augment TE label range information for the TE link template."; + uses label-range-info; + } + + /* + * Augment TE label. + */ + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the TE node + connectivity matrices"; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/" + + "tet:label-restriction/tet:label-end/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the TE node + connectivity matrices"; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/" + + "tet:label-restriction/tet:label-step/" + + "tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the TE node + connectivity matrices"; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:underlay/tet:primary-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay primary path of the + TE node connectivity matrices"; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:underlay/tet:backup-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay backup path of the + TE node connectivity matrices"; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TE node connectivity + matrices"; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TE node connectivity + matrices"; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the TE node connectivity matrices"; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the source LTP + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the source LTP + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/" + + "tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the source LTP + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the destination LTP + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the destination LTP + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/" + + "tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the destination LTP + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:primary-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:backup-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:optimizations/" + + "tet:algorithm/tet:metric/tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:optimizations/" + + "tet:algorithm/tet:metric/tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the connectivity matrix entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the TE node connectivity + matrices information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the TE node connectivity + matrices information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the TE node connectivity + matrices information source."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TE node connectivity matrices of the information + source entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TE node connectivity matrices of the information + source entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TE node connectivity matrices + information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TE node connectivity matrices + information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the TE node connectivity matrices information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the source LTP + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label; + } + } + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the source LTP + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the source LTP + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the destination LTP + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the destination LTP + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the destination LTP + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the connectivity matrix entry + information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the connectivity matrix entry + information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the connectivity matrix entry information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the TTP + Local Link Connectivities."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/" + + "tet:te-label/tet:technology"{ + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the TTP + Local Link Connectivities."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/" + + "tet:technology"{ + when "../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the TTP + Local Link Connectivities."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TTP Local Link Connectivities."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TTP Local Link Connectivities."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TTP Local Link + Connectivities."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TTP Local Link + Connectivities."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the TTP Local Link Connectivities."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the TTP + Local Link Connectivity entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the TTP + Local Link Connectivity entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the TTP + Local Link Connectivity entry."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TTP Local Link Connectivity entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TTP Local Link Connectivity entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TTP Local Link + Connectivity entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TTP Local Link + Connectivity entry."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the TTP Local Link Connectivity entry."; + case eth { + uses etht-types:eth-label; + } + } + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TE link."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TE link."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the TE link."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the TE link."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the TE link."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range start for the TE link + information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range end for the TE link + information source."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "etht:eth-tran-topology" { + description + "Augmentation parameters apply only for networks with + Ethernet topology type."; + } + description + "Augment TE label range step for the TE link + information source."; + case eth { + uses etht-types:eth-label-step; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + description + "Augment TE label hop for the underlay primary path + of the TE link template."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + description + "Augment TE label hop for the underlay backup path + of the TE link template."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + description + "Augment TE label range start for the TE link template."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + description + "Augment TE label range end for the TE link template."; + case eth { + uses etht-types:eth-label; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + description + "Augment TE label range step for the TE link template."; + case eth { + uses etht-types:eth-label-step; + } + } + + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-service@2023-10-23.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-service@2023-10-23.yang new file mode 100644 index 000000000..222066adf --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-service@2023-10-23.yang @@ -0,0 +1,1004 @@ + module ietf-eth-tran-service { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-eth-tran-service"; + + prefix "ethtsvc"; + import ietf-yang-types { + prefix "yang"; + reference "RFC 6991 - Common YANG Data Types"; + } + + import ietf-network { + prefix "nw"; + reference "RFC8345 - A YANG Data Model for Network Topologies"; + } + + import ietf-network-topology { + prefix "nt"; + reference "RFC8345 - A YANG Data Model for Network Topologies"; + } + + import ietf-te-types { + prefix "te-types"; + reference "RFC 8776 - Traffic Engineering Common YANG Types"; + } + + import ietf-eth-tran-types { + prefix "etht-types"; + reference "RFC XXXX - A YANG Data Model for Transport + Network Client Signals"; + } + + import ietf-routing-types { + prefix "rt-types"; + reference "RFC 8294 - Common YANG Data Types for the + Routing Area"; + + } + + import ietf-te { + prefix "te"; + reference "RFC YYYY - A YANG Data Model for Traffic + Engineering Tunnels and Interfaces"; + } + + organization + "Internet Engineering Task Force (IETF) CCAMP WG"; + contact + " + WG List: + + ID-draft editor: + Haomian Zheng (zhenghaomian@huawei.com); + Italo Busi (italo.busi@huawei.com); + Aihua Guo (aihuaguo.ietf@gmail.com); + Anton Snitser (antons@sedonasys.com);0 + Francesco Lazzeri (francesco.lazzeri@ericsson.com); + Yunbin Xu (xuyunbin@caict.ac.cn); + Yang Zhao (zhaoyangyjy@chinamobile.com); + Xufeng Liu (xufeng.liu.ietf@gmail.com); + Giuseppe Fioccola (giuseppe.fioccola@huawei.com); + Chaode Yu (yuchaode@huawei.com) + "; + + description + "This module defines a YANG data model for describing + the Ethernet services. The model fully conforms to the + Network Management Datastore Architecture (NMDA). + + Copyright (c) 2021 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices."; + + revision 2023-10-23 { + description + "version -04 as an WG document"; + reference + "draft-ietf-ccamp-client-signal-yang"; + } + + /* + * Groupings + */ + + grouping vlan-classification { + description + "A grouping which represents classification + on an 802.1Q VLAN tag."; + + leaf tag-type { + type etht-types:eth-tag-classify; + description + "The tag type used for VLAN classification."; + } + choice individual-bundling-vlan { + description + "VLAN based classification can be individual + or bundling."; + + case individual-vlan { + leaf vlan-value { + type etht-types:vlanid; + description + "VLAN ID value."; + } + } + + case vlan-bundling { + leaf vlan-range { + type etht-types:vid-range-type; + description + "List of VLAN ID values."; + } + } + } + } + + grouping vlan-write { + description + "A grouping which represents push/pop operations + of an 802.1Q VLAN tag."; + + leaf tag-type { + type etht-types:eth-tag-type; + description + "The VLAN tag type to push/swap."; + } + leaf vlan-value { + type etht-types:vlanid; + description + "The VLAN ID value to push/swap."; + } + /* + * To be added: this attribute is used when: + * a) the ETH service has only one CoS (as in current version) + * b) as a default when a mapping between a given CoS value + * and the PCP value is not defined (in future versions) + */ + leaf default-pcp { + type uint8 { + range "0..7"; + } + description + "The default Priority Code Point (PCP) value to push/swap"; + } + } + + grouping vlan-operations { + description + "A grouping which represents VLAN operations."; + + leaf pop-tags { + type uint8 { + range "1..2"; + } + description + "The number of VLAN tags to pop (or swap if used in + conjunction with push-tags)"; + } + container push-tags { + description + "The VLAN tags to push (or swap if used in + conjunction with pop-tags)"; + + container outer-tag { + presence + "Indicates existence of the outermost VLAN tag to + push/swap"; + + description + "The outermost VLAN tag to push/swap."; + + uses vlan-write; + } + container second-tag { + must + '../outer-tag/tag-type = "etht-types:s-vlan-tag-type" and ' + + 'tag-type = "etht-types:c-vlan-tag-type"' + { + + error-message + " + When pushing/swapping two tags, the outermost tag must + be specified and of S-VLAN type and the second + outermost tag must be of C-VLAN tag type. + "; + description + " + For IEEE 802.1Q interoperability, when pushing/swapping + two tags, it is required that the outermost tag exists + and is an S-VLAN, and the second outermost tag is a + C-VLAN. + "; + } + + presence + "Indicates existence of a second outermost VLAN tag to + push/swap"; + + description + "The second outermost VLAN tag to push/swap."; + uses vlan-write; + } + } + } + + grouping named-or-value-bandwidth-profile { + description + "A grouping to configure a bandwdith profile either by + referencing a named bandwidth profile or by + configuring the values of the bandwidth profile attributes."; + choice style { + description + "Whether the bandwidth profile is named or defined by value"; + + case named { + description + "Named bandwidth profile."; + leaf bandwidth-profile-name { + type leafref { + path "/ethtsvc:etht-svc/ethtsvc:globals/" + + "ethtsvc:named-bandwidth-profiles/" + + "ethtsvc:bandwidth-profile-name"; + } + description + "Name of the bandwidth profile."; + } + } + case value { + description + "Bandwidth profile configured by value."; + uses etht-types:etht-bandwidth-profiles; + } + } + } + + grouping bandwidth-profiles { + description + "A grouping which represent bandwidth profile configuration."; + + choice direction { + description + "Whether the bandwidth profiles are symmetrical or + asymmetrical"; + case symmetrical { + description + "The same bandwidth profile is used to describe both + the ingress and the egress bandwidth profile."; + container ingress-egress-bandwidth-profile { + description + "The bandwdith profile used in both directions."; + uses named-or-value-bandwidth-profile; + } + } + case asymmetrical { + description + "Ingress and egress bandwidth profiles can be specified."; + container ingress-bandwidth-profile { + description + "The bandwdith profile used in the ingress direction."; + uses named-or-value-bandwidth-profile; + } + container egress-bandwidth-profile { + description + "The bandwdith profile used in the egress direction."; + uses named-or-value-bandwidth-profile; + } + } + } + } + + grouping etht-svc-access-parameters { + description + "ETH services access parameters"; + + leaf access-node-id { + type te-types:te-node-id; + description + "The identifier of the access node in + the ETH TE topology."; + } + + leaf access-node-uri { + type nw:node-id; + description + "The identifier of the access node in the network."; + } + + leaf access-ltp-id { + type te-types:te-tp-id; + description + "The TE link termination point identifier, used + together with access-node-id to identify the + access LTP."; + } + + leaf access-ltp-uri { + type nt:tp-id; + description + "The link termination point identifier in network topology, + used together with access-node-uri to identify the + access LTP."; + } + + leaf access-role { + type identityref { + base etht-types:access-role; + } + description + "Indicate the role of access, e.g., working or protection. "; + } + + container pm-config { + uses pm-config-grouping; + description + "This grouping is used to set the threshold value for + performance monitoring. "; + } + + container state { + config false; + description + "The state is used to monitor the status of service. "; + leaf operational-state { + type identityref { + base te-types:tunnel-state-type; + } + description + "Indicating the operational state of client signal. "; + } + leaf provisioning-state { + type identityref { + base te-types:lsp-state-type; + } + description + "Indicating the provisional state of client signal, + especially when there is a change, i.e., revise, create. "; + } + } + + leaf performance { + type identityref { + base etht-types:performance; + } + config false; + description + "Performance Monitoring for the service. "; + } + + } + + grouping etht-svc-tunnel-parameters { + description + "ETH services tunnel parameters."; + choice technology { + description + "Service multiplexing is optional and flexible."; + + case native-ethernet { + /* + placeholder to support proprietary multiplexing + (for further discussion) + */ + list eth-tunnels { + key name; + description + "ETH Tunnel list in native Ethernet scenario."; + uses tunnels-grouping; + } + } + + case frame-base { + list otn-tunnels { + key name; + description + "OTN Tunnel list in Frame-based scenario."; + uses tunnels-grouping; + } + } + + case mpls-tp { + container pw { + description + "Pseudowire information for Ethernet over MPLS-TP."; + uses pw-segment-grouping; + } + } + } + + /* + * Open issue: can we constraints it to be used only with mp services? + */ + leaf src-split-horizon-group { + type string; + description + "Identify a split horizon group at the Tunnel source TTP"; + } + leaf dst-split-horizon-group { + type string; + description + "Identify a split horizon group at the Tunnel destination TTP"; + } + } + + grouping etht-svc-pm-threshold-config { + description + "Configuraiton parameters for Ethernet service PM thresholds."; + + leaf sending-rate-high { + type uint64; + description + "High threshold of packet sending rate in kbps."; + } + leaf sending-rate-low { + type uint64; + description + "Low threshold of packet sending rate in kbps."; + } + leaf receiving-rate-high { + type uint64; + description + "High threshold of packet receiving rate in kbps."; + } + leaf receiving-rate-low { + type uint64; + description + "Low threshold of packet receiving rate in kbps."; + } + } + + grouping etht-svc-pm-stats { + description + "Ethernet service PM statistics."; + + leaf sending-rate-too-high { + type uint32; + description + "Counter that indicates the number of times the + sending rate is above the high threshold"; + } + leaf sending-rate-too-low { + type uint32; + description + "Counter that indicates the number of times the + sending rate is below the low threshold"; + } + leaf receiving-rate-too-high { + type uint32; + description + "Counter that indicates the number of times the + receiving rate is above the high threshold"; + } + leaf receiving-rate-too-low { + type uint32; + description + "Counter that indicates the number of times the + receiving rate is below the low threshold"; + } + } + + grouping etht-svc-instance-config { + description + "Configuraiton parameters for Ethernet services."; + + leaf etht-svc-name { + type string; + description + "Name of the ETH service."; + } + + leaf etht-svc-title { + type string; + description + "The Identifier of the ETH service."; + } + + leaf user-label { + type string; + description + "Alias of the ETH service."; + } + + leaf etht-svc-descr { + type string; + description + "Description of the ETH service."; + } + + leaf etht-svc-customer { + type string; + description + "Customer of the ETH service."; + } + + leaf etht-svc-type { + type etht-types:service-type; + description + "Type of ETH service (p2p, mp2mp or rmp)."; + /* Add default as p2p */ + } + + leaf etht-svc-lifecycle { + type etht-types:lifecycle-status; + description + "Lifecycle state of ETH service."; + /* Add default as installed */ + } + uses te-types:te-topology-identifier; + + uses resilience-grouping; + list etht-svc-end-points { + key etht-svc-end-point-name; + description + "The logical end point for the ETH service. "; + uses etht-svc-end-point-grouping; + } + + container alarm-shreshold { + description "threshold configuration for the E2E client signal"; + uses alarm-shreshold-grouping; + } + + container underlay { + description + "The unterlay tunnel information that carrying the + ETH service. "; + uses etht-svc-tunnel-parameters; + } + + leaf admin-status { + type identityref { + base te-types:tunnel-admin-state-type; + } + default te-types:tunnel-admin-state-up; + description "ETH service administrative state."; + } + } + + grouping etht-svc-instance-state { + description + "State parameters for Ethernet services."; + + leaf operational-state { + type identityref { + base te-types:tunnel-state-type; + } + default te-types:tunnel-state-up; + description "ETH service operational state."; + } + leaf provisioning-state { + type identityref { + base te-types:lsp-state-type; + } + description "ETH service provisioning state."; + } + leaf creation-time { + type yang:date-and-time; + description + "Time of ETH service creation."; + } + leaf last-updated-time { + type yang:date-and-time; + description + "Time of ETH service last update."; + } + + leaf created-by { + type string; + description + "The client signal is created by whom, + can be a system or staff ID."; + } + leaf last-updated-by { + type string; + description + "The client signal is last updated by whom, + can be a system or staff ID."; + } + leaf owned-by { + type string; + description + "The client signal is last updated by whom, + can be a system ID."; + } + container pm-state { + description + "PM data of E2E Ethernet service"; + uses pm-state-grouping; + } + container error-info { + description "error messages of configuration"; + uses error-info-grouping; + } + } + + grouping pm-state-grouping { + leaf latency { + description + "latency value of the E2E Ethernet service"; + type uint32; + units microsecond; + } + } + + grouping error-info-grouping { + leaf error-code { + description "error code"; + type uint16; + } + + leaf error-description { + description "detail message of error"; + type string; + } + + leaf error-timestamp { + description "the date and time error is happened"; + type yang:date-and-time; + } + } + + grouping alarm-shreshold-grouping { + leaf latency-threshold { + description "a threshold for the E2E client signal service's + latency. Once the latency value exceed this threshold, an alarm + should be triggered."; + type uint32; + units microsecond; + } + } + + /* + * Data nodes + */ + + container etht-svc { + description + "ETH services."; + + container globals { + description + "Globals Ethernet configuration data container"; + list named-bandwidth-profiles { + key bandwidth-profile-name; + description + "List of named bandwidth profiles used by + Ethernet services."; + + leaf bandwidth-profile-name { + type string; + description + "Name of the bandwidth profile."; + } + uses etht-types:etht-bandwidth-profiles; + } + } + list etht-svc-instances { + key etht-svc-name; + description + "The list of p2p ETH service instances"; + + uses etht-svc-instance-config; + + container state { + config false; + description + "Ethernet Service states."; + + uses etht-svc-instance-state; + } + } + } + + grouping resilience-grouping { + description + "Grouping for resilience configuration. "; + container resilience { + description + "To configure the data plane protection parameters, + currently a placeholder only, future candidate attributes + include, Revert, WTR, Hold-off Timer, ..."; + uses te:protection-restoration-properties; + } + } + + grouping etht-svc-end-point-grouping { + description + "Grouping for the end point configuration."; + leaf etht-svc-end-point-name { + type string; + description + "The name of the logical end point of ETH service. "; + } + + leaf etht-svc-end-point-id { + type string; + description + "The identifier of the logical end point of ETH service."; + } + + leaf etht-svc-end-point-descr { + type string; + description + "The description of the logical end point of ETH service. "; + } + + leaf topology-role { + type identityref { + base etht-types:topology-role; + } + description + "Indicating the underlay topology role, + e.g., hub,spoke, any-to-any "; + } + + container resilience { + description + "Placeholder for resilience configuration, for future study. "; + } + + list etht-svc-access-points { + key access-point-id; + min-elements "1"; + /* + Open Issue: + Is it possible to limit the max-elements only for p2p services? + max-elements "2"; + */ + description + "List of the ETH trasport services access point instances."; + + leaf access-point-id { + type string; + description + "ID of the service access point instance"; + } + uses etht-svc-access-parameters; + } + + leaf service-classification-type { + type identityref { + base etht-types:service-classification-type; + } + description + "Service classification type."; + } + + choice service-classification { + description + "Access classification can be port-based or + VLAN based."; + case port-classification { + /* no additional information */ + } + + case vlan-classification { + container outer-tag { + presence "The outermost VLAN tag exists"; + description + "Classifies traffic using the outermost VLAN tag."; + + uses vlan-classification; + } + container second-tag { + must + '../outer-tag/tag-type = "etht-types:classify-s-vlan" and ' + + 'tag-type = "etht-types:classify-c-vlan"' + { + error-message + " + When matching two tags, the outermost tag must be + specified and of S-VLAN type and the second + outermost tag must be of C-VLAN tag type. + "; + description + " + For IEEE 802.1Q interoperability, when matching two + tags, it is required that the outermost tag exists + and is an S-VLAN, and the second outermost tag is a + C-VLAN. + "; + } + presence "The second outermost VLAN tag exists"; + + description + "Classifies traffic using the second outermost VLAN tag."; + + uses vlan-classification; + } + } + } + + /* + * Open issue: can we constraints it to be used only with mp services? + */ + leaf split-horizon-group { + type string; + description "Identify a split horizon group"; + } + uses bandwidth-profiles; + + container vlan-operations { + description + "Configuration of VLAN operations."; + choice direction { + description + "Whether the VLAN operations are symmetrical or + asymmetrical"; + case symmetrical { + container symmetrical-operation { + uses vlan-operations; + description + "Symmetrical operations. + Expressed in the ingress direction, but + the reverse operation is applied to egress traffic"; + } + } + case asymmetrical { + container asymmetrical-operation { + description "Asymmetrical operations"; + container ingress { + uses vlan-operations; + description "Ingress operations"; + } + container egress { + uses vlan-operations; + description "Egress operations"; + } + } + } + } + } + } + + grouping pm-config-grouping { + description + "Grouping used for Performance Monitoring Configuration. "; + leaf pm-enable { + type boolean; + description + "Whether to enable the performance monitoring."; + } + + leaf sending-rate-high { + type uint64; + description + "The upperbound of sending rate."; + } + + leaf sending-rate-low { + type uint64; + description + "The lowerbound of sending rate."; + } + + leaf receiving-rate-high { + type uint64; + description + "The upperbound of receiving rate."; + } + + leaf receiving-rate-low { + type uint64; + description + "The lowerbound of receiving rate."; + } + } + + grouping pw-segment-grouping { + description + "Grouping used for PW configuration. "; + leaf pw-id { + type string; + description + "The Identifier information of pseudowire. "; + } + + leaf pw-name { + type string; + description + "The name information of pseudowire."; + } + + leaf transmit-label { + type rt-types:mpls-label; + description + "Transmit label information in PW. "; + } + + leaf receive-label { + type rt-types:mpls-label; + description + "Receive label information in PW. "; + } + leaf encapsulation-type { + type identityref { + base etht-types:encapsulation-type; + } + description + "The encapsulation type, raw or tag. "; + } + + leaf oper-status { + type identityref { + base te-types:tunnel-state-type; + } + config false; + description + "The operational state of the PW segment. "; + } + + container ingress-bandwidth-profile { + description + "Bandwidth Profile for ingress. "; + uses pw-segment-named-or-value-bandwidth-profile; + } + + list pw-paths { + key path-id; + description + "A list of pw paths. "; + + leaf path-id { + type uint8; + description + "The identifier of pw paths. "; + + } + + list tp-tunnels { + key name; + description + "Names of TP Tunnel underlay"; + leaf name { + type string; + description + "Names of TP Tunnel underlay"; + } + } + } + + } + grouping pw-segment-named-or-value-bandwidth-profile { + description + "A grouping to configure a bandwdith profile either by + referencing a named bandwidth profile or by + configuring the values of the bandwidth profile attributes."; + choice style { + description + "Whether the bandwidth profile is named or defined by value"; + case named { + description + "Named bandwidth profile."; + leaf bandwidth-profile-name { + type leafref { + path "/ethtsvc:etht-svc/ethtsvc:globals/" + + "ethtsvc:named-bandwidth-profiles/" + + "ethtsvc:bandwidth-profile-name"; + } + description + "Name of the bandwidth profile."; + } + } + case value { + description + "Bandwidth profile configured by value."; + uses etht-types:pw-segement-bandwidth-profile-grouping; + } + } + } + + grouping tunnels-grouping { + description + "A group of tunnels. "; + leaf name { + type leafref { + path "/te:te/te:tunnels/te:tunnel/te:name"; + require-instance false; + } + description "Dependency tunnel name"; + } + leaf encoding { + type identityref { + base te-types:lsp-encoding-types; + } + description "LSP encoding type"; + reference "RFC3945"; + } + leaf switching-type { + type identityref { + base te-types:switching-capabilities; + } + description "LSP switching type"; + reference "RFC3945"; + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-types@2023-10-23.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-types@2023-10-23.yang new file mode 100644 index 000000000..f46908b34 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-eth-tran-types@2023-10-23.yang @@ -0,0 +1,457 @@ + module ietf-eth-tran-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-eth-tran-types"; + + prefix "etht-types"; + + organization + "Internet Engineering Task Force (IETF) CCAMP WG"; + contact + " + WG List: + + ID-draft editor: + Haomian Zheng (zhenghaomian@huawei.com); + Italo Busi (italo.busi@huawei.com); + Aihua Guo (aihuaguo.ietf@gmail.com); + Anton Snitser (antons@sedonasys.com); + Francesco Lazzeri (francesco.lazzeri@ericsson.com); + Yunbin Xu (xuyunbin@caict.ac.cn); + Yang Zhao (zhaoyangyjy@chinamobile.com); + Xufeng Liu (xufeng.liu.ietf@gmail.com); + Giuseppe Fioccola (giuseppe.fioccola@huawei.com); + Chaode Yu (yuchaode@huawei.com) + "; + + description + "This module defines the ETH types. + The model fully conforms to the Network Management + Datastore Architecture (NMDA). + + Copyright (c) 2019 IETF Trust and the persons + identified as authors of the code. All rights reserved. + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices."; + + revision 2023-10-23 { + description + "version -05 as a WG draft"; + reference + "draft-ietf-ccamp-client-signal-yang"; + } + + /* + * Identities + */ + + identity eth-vlan-tag-type { + description + "ETH VLAN tag type."; + } + + identity c-vlan-tag-type { + base eth-vlan-tag-type; + description + "802.1Q Customer VLAN"; + } + + identity s-vlan-tag-type { + base eth-vlan-tag-type; + description + "802.1Q Service VLAN (QinQ)"; + } + + identity service-classification-type { + description + "Service classification."; + } + + identity port-classification { + base service-classification-type; + description + "Port classification."; + } + identity vlan-classification { + base service-classification-type; + description + "VLAN classification."; + } + + identity eth-vlan-tag-classify { + description + "VLAN tag classification."; + } + + identity classify-c-vlan { + base eth-vlan-tag-classify; + description + "Classify 802.1Q Customer VLAN tag. + Only C-tag type is accepted"; + } + + identity classify-s-vlan { + base eth-vlan-tag-classify; + description + "Classify 802.1Q Service VLAN (QinQ) tag. + Only S-tag type is accepted"; + } + + identity classify-s-or-c-vlan { + base eth-vlan-tag-classify; + description + "Classify S-VLAN or C-VLAN tag-classify. + Either tag is accepted"; + } + + identity bandwidth-profile-type-ir { + description + "Bandwidth Profile Types"; + } + + identity mef-10-bwp { + base bandwidth-profile-type-ir; + description + "MEF 10 Bandwidth Profile"; + } + + identity rfc-2697-bwp { + base bandwidth-profile-type-ir; + description + "RFC 2697 Bandwidth Profile"; + } + identity rfc-2698-bwp { + base bandwidth-profile-type-ir; + description + "RFC 2698 Bandwidth Profile"; + } + + identity rfc-4115-bwp { + base bandwidth-profile-type-ir; + description + "RFC 4115 Bandwidth Profile"; + } + + identity service-type-ir { + description + "Type of Ethernet service."; + } + + identity p2p-svc { + base service-type-ir; + description + "Ethernet point-to-point service (EPL, EVPL)."; + } + + identity rmp-svc { + base service-type-ir; + description + "Ethernet rooted-multitpoint service (E-TREE, EP-TREE)."; + } + + identity mp2mp-svc { + base service-type-ir; + description + "Ethernet multipoint-to-multitpoint service (E-LAN, EP-LAN)."; + } + + identity lifecycle-status-ir { + description + "Lifecycle Status."; + } + + identity installed { + base lifecycle-status-ir; + description + "Installed."; + } + + identity planned { + base lifecycle-status-ir; + description + "Planned."; + } + + identity pending-removal { + base lifecycle-status-ir; + description + "Pending Removal."; + } + + /* + * Type Definitions + */ + + typedef eth-tag-type { + type identityref { + base eth-vlan-tag-type; + } + description + "Identifies a specific ETH VLAN tag type."; + } + + typedef eth-tag-classify { + type identityref { + base eth-vlan-tag-classify; + } + description + "Identifies a specific VLAN tag classification."; + } + + typedef vlanid { + type uint16 { + range "1..4094"; + } + description + "The 12-bit VLAN-ID used in the VLAN Tag header."; + } + + typedef vid-range-type { + type string { + pattern "([1-9][0-9]{0,3}(-[1-9][0-9]{0,3})?" + + "(,[1-9][0-9]{0,3}(-[1-9][0-9]{0,3})?)*)"; + } + description + "A list of VLAN Ids, or non overlapping VLAN ranges, in + ascending order, between 1 and 4094. + This type is used to match an ordered list of VLAN Ids, or + contiguous ranges of VLAN Ids. Valid VLAN Ids must be in the + range 1 to 4094, and included in the list in non overlapping + ascending order. + + For example: 1,10-100,50,500-1000"; + } + + typedef bandwidth-profile-type { + type identityref { + base bandwidth-profile-type-ir; + } + description + "Identifies a specific Bandwidth Profile type."; + } + + typedef service-type { + type identityref { + base service-type-ir; + } + description + "Identifies the type of Ethernet service."; + } + + typedef lifecycle-status { + type identityref { + base lifecycle-status-ir; + } + description + "Identifies the lLifecycle Status ."; + } + + /* + * Grouping Definitions + */ + + grouping etht-bandwidth-profiles { + description + "Bandwidth profile configuration paramters."; + + leaf bandwidth-profile-type { + type etht-types:bandwidth-profile-type; + description + "The type of bandwidth profile."; + } + leaf CIR { + type uint64; + description + "Committed Information Rate in Kbps"; + } + leaf CBS { + type uint64; + description + "Committed Burst Size in in KBytes"; + } + leaf EIR { + type uint64; + /* Need to indicate that EIR is not supported by RFC 2697 + + must + '../bw-profile-type = "mef-10-bwp" or ' + + '../bw-profile-type = "rfc-2698-bwp" or ' + + '../bw-profile-type = "rfc-4115-bwp"' + + must + '../bw-profile-type != "rfc-2697-bwp"' + */ + description + "Excess Information Rate in Kbps + In case of RFC 2698, PIR = CIR + EIR"; + } + leaf EBS { + type uint64; + description + "Excess Burst Size in KBytes. + In case of RFC 2698, PBS = CBS + EBS"; + } + leaf color-aware { + type boolean; + description + "Indicates weather the color-mode is + color-aware or color-blind."; + } + leaf coupling-flag { + type boolean; + /* Need to indicate that Coupling Flag is defined only for MEF 10 + + must + '../bw-profile-type = "mef-10-bwp"' + */ + description + "Coupling Flag."; + } + } + + identity topology-role { + description + "The role of underlay topology: e.g., hub, spoke, + any-to-any."; + } + + identity resilience { + description + "Placeholder for resilience information in data plane, + for future study. "; + } + + identity access-role { + description + "Indicating whether the access is a working or protection access."; + } + + identity root-primary { + base access-role; + description + "Designates the primary root UNI of an E-Tree service, and may also + designates the UNI access role of E-LINE and E-LAN service."; + } + + identity root-backup { + base access-role; + description + "Designates the backup root UNI of an E-Tree service."; + } + + identity leaf-access { + base access-role; + description + "Designates the leaf UNI of an E-Tree service."; + } + + identity leaf-edge { + base access-role; + description ""; + } + + identity performance { + description + "Placeholder for performance information, for future study."; + } + + identity encapsulation-type { + description + "Indicating how the service is encapsulated (to PW), e.g, raw or tag. "; + } + grouping pw-segement-bandwidth-profile-grouping { + description + "bandwidth profile grouping for PW segment. "; + leaf bandwidth-profile-type { + type etht-types:bandwidth-profile-type; + description + "The type of bandwidth profile."; + } + leaf CIR { + type uint64; + description + "Committed Information Rate in Kbps"; + } + leaf CBS { + type uint64; + description + "Committed Burst Size in in KBytes"; + } + leaf EIR { + type uint64; + /* Need to indicate that EIR is not supported by RFC 2697 + + must + '../bw-profile-type = "mef-10-bwp" or ' + + '../bw-profile-type = "rfc-2698-bwp" or ' + + '../bw-profile-type = "rfc-4115-bwp"' + + must + '../bw-profile-type != "rfc-2697-bwp"' + */ + description + "Excess Information Rate in Kbps + In case of RFC 2698, PIR = CIR + EIR"; + } + leaf EBS { + type uint64; + description + "Excess Burst Size in KBytes. + In case of RFC 2698, PBS = CBS + EBS"; + } + } + grouping eth-bandwidth { + description + "Available bandwith for ethernet."; + leaf eth-bandwidth { + type uint64{ + range "0..10000000000"; + } + units "Kbps"; + description + "Available bandwith value expressed in kilobits per second"; + } + } + + grouping eth-label-restriction { + description + "Label Restriction for ethernet."; + leaf tag-type { + type etht-types:eth-tag-type; + description "VLAN tag type."; + } + leaf priority { + type uint8; + description "priority."; + } + } + grouping eth-label { + description + "Label for ethernet."; + leaf vlanid { + type etht-types:vlanid; + description + "VLAN tag id."; + } + } + + grouping eth-label-step { + description "Label step for Ethernet VLAN"; + leaf eth-step { + type uint16 { + range "1..4095"; + } + default 1; + description + "Label step which represent possible increments for + an Ethernet VLAN tag."; + reference + "IEEE 802.1ad: Provider Bridges."; + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-ethertypes@2019-03-04.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-ethertypes@2019-03-04.yang new file mode 100644 index 000000000..fd055074a --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-ethertypes@2019-03-04.yang @@ -0,0 +1,381 @@ +module ietf-ethertypes { + namespace "urn:ietf:params:xml:ns:yang:ietf-ethertypes"; + prefix ethertypes; + + organization + "IETF NETMOD (Network Modeling) Working Group."; + + contact + "WG Web: + WG List: + + Editor: Mahesh Jethanandani + "; + + description + "This module contains common definitions for the + Ethertype used by different modules. It is a + placeholder module, till such time that IEEE + starts a project to define these Ethertypes + and publishes a standard. + + At that time, this module can be deprecated. + + Copyright (c) 2019 IETF Trust and the persons identified as + the document authors. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8519; see + the RFC itself for full legal notices."; + + revision 2019-03-04 { + description + "Initial revision."; + reference + "RFC 8519: YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + typedef ethertype { + type union { + type uint16; + type enumeration { + enum ipv4 { + value 2048; + description + "Internet Protocol version 4 (IPv4) with a + hex value of 0x0800."; + reference + "RFC 791: Internet Protocol."; + } + enum arp { + value 2054; + description + "Address Resolution Protocol (ARP) with a + hex value of 0x0806."; + reference + "RFC 826: An Ethernet Address Resolution Protocol: Or + Converting Network Protocol Addresses to 48.bit + Ethernet Address for Transmission on Ethernet + Hardware."; + } + enum wlan { + value 2114; + description + "Wake-on-LAN. Hex value of 0x0842."; + } + enum trill { + value 8947; + description + "Transparent Interconnection of Lots of Links. + Hex value of 0x22F3."; + reference + "RFC 6325: Routing Bridges (RBridges): Base Protocol + Specification."; + } + enum srp { + value 8938; + description + "Stream Reservation Protocol. Hex value of + 0x22EA."; + reference + "IEEE 801.1Q-2011."; + } + enum decnet { + value 24579; + description + "DECnet Phase IV. Hex value of 0x6003."; + } + enum rarp { + value 32821; + description + "Reverse Address Resolution Protocol. + Hex value 0x8035."; + reference + "RFC 903: A Reverse Address Resolution Protocol."; + } + enum appletalk { + value 32923; + description + "Appletalk (Ethertalk). Hex value of 0x809B."; + } + enum aarp { + value 33011; + description + "Appletalk Address Resolution Protocol. Hex value + of 0x80F3."; + } + enum vlan { + value 33024; + description + "VLAN-tagged frame (IEEE 802.1Q) and Shortest Path + Bridging IEEE 802.1aq with Network-Network + Interface (NNI) compatibility. Hex value of + 0x8100."; + reference + "IEEE 802.1Q."; + } + enum ipx { + value 33079; + description + "Internetwork Packet Exchange (IPX). Hex value + of 0x8137."; + } + enum qnx { + value 33284; + description + "QNX Qnet. Hex value of 0x8204."; + } + enum ipv6 { + value 34525; + description + "Internet Protocol Version 6 (IPv6). Hex value + of 0x86DD."; + reference + "RFC 8200: Internet Protocol, Version 6 (IPv6) + Specification + RFC 8201: Path MTU Discovery for IP version 6."; + } + enum efc { + value 34824; + description + "Ethernet flow control using pause frames. + Hex value of 0x8808."; + reference + "IEEE 802.1Qbb."; + } + enum esp { + value 34825; + description + "Ethernet Slow Protocol. Hex value of 0x8809."; + reference + "IEEE 802.3-2015."; + } + enum cobranet { + value 34841; + description + "CobraNet. Hex value of 0x8819."; + } + enum mpls-unicast { + value 34887; + description + "Multiprotocol Label Switching (MPLS) unicast traffic. + Hex value of 0x8847."; + reference + "RFC 3031: Multiprotocol Label Switching Architecture."; + } + enum mpls-multicast { + value 34888; + description + "MPLS multicast traffic. Hex value of 0x8848."; + reference + "RFC 3031: Multiprotocol Label Switching Architecture."; + } + enum pppoe-discovery { + value 34915; + description + "Point-to-Point Protocol over Ethernet. Used during + the discovery process. Hex value of 0x8863."; + reference + "RFC 2516: A Method for Transmitting PPP Over Ethernet + (PPPoE)."; + } + enum pppoe-session { + value 34916; + description + "Point-to-Point Protocol over Ethernet. Used during + session stage. Hex value of 0x8864."; + reference + "RFC 2516: A Method for Transmitting PPP Over Ethernet + (PPPoE)."; + } + enum intel-ans { + value 34925; + description + "Intel Advanced Networking Services. Hex value of + 0x886D."; + } + enum jumbo-frames { + value 34928; + description + "Jumbo frames or Ethernet frames with more than + 1500 bytes of payload, up to 9000 bytes."; + } + enum homeplug { + value 34939; + description + "Family name for the various power line + communications. Hex value of 0x887B."; + } + enum eap { + value 34958; + description + "Ethernet Access Protocol (EAP) over LAN. Hex value + of 0x888E."; + reference + "IEEE 802.1X."; + } + enum profinet { + value 34962; + description + "PROcess FIeld Net (PROFINET). Hex value of 0x8892."; + } + enum hyperscsi { + value 34970; + description + "Small Computer System Interface (SCSI) over Ethernet. + Hex value of 0x889A."; + } + enum aoe { + value 34978; + description + "Advanced Technology Advancement (ATA) over Ethernet. + Hex value of 0x88A2."; + } + enum ethercat { + value 34980; + description + "Ethernet for Control Automation Technology (EtherCAT). + Hex value of 0x88A4."; + } + enum provider-bridging { + value 34984; + description + "Provider Bridging (802.1ad) and Shortest Path Bridging + (801.1aq). Hex value of 0x88A8."; + reference + "IEEE 802.1ad and IEEE 802.1aq)."; + } + enum ethernet-powerlink { + value 34987; + description + "Ethernet Powerlink. Hex value of 0x88AB."; + } + enum goose { + value 35000; + description + "Generic Object Oriented Substation Event (GOOSE). + Hex value of 0x88B8."; + reference + "IEC/ISO 8802-2 and 8802-3."; + } + enum gse { + value 35001; + description + "Generic Substation Events. Hex value of 88B9."; + reference + "IEC 61850."; + } + enum sv { + value 35002; + description + "Sampled Value Transmission. Hex value of 0x88BA."; + reference + "IEC 61850."; + } + enum lldp { + value 35020; + description + "Link Layer Discovery Protocol (LLDP). Hex value of + 0x88CC."; + reference + "IEEE 802.1AB."; + } + enum sercos { + value 35021; + description + "Sercos Interface. Hex value of 0x88CD."; + } + enum wsmp { + value 35036; + description + "WAVE Short Message Protocol (WSMP). Hex value of + 0x88DC."; + } + enum homeplug-av-mme { + value 35041; + description + "HomePlug AV Mobile Management Entity (MME). Hex value + of 88E1."; + } + enum mrp { + value 35043; + description + "Media Redundancy Protocol (MRP). Hex value of + 0x88E3."; + reference + "IEC 62439-2."; + } + enum macsec { + value 35045; + description + "MAC Security. Hex value of 0x88E5."; + reference + "IEEE 802.1AE."; + } + enum pbb { + value 35047; + description + "Provider Backbone Bridges (PBB). Hex value of + 0x88E7."; + reference + "IEEE 802.1ah."; + } + enum cfm { + value 35074; + description + "Connectivity Fault Management (CFM). Hex value of + 0x8902."; + reference + "IEEE 802.1ag."; + } + enum fcoe { + value 35078; + description + "Fiber Channel over Ethernet (FCoE). Hex value of + 0x8906."; + reference + "T11 FC-BB-5."; + } + enum fcoe-ip { + value 35092; + description + "FCoE Initialization Protocol. Hex value of 0x8914."; + } + enum roce { + value 35093; + description + "RDMA over Converged Ethernet (RoCE). Hex value of + 0x8915."; + } + enum tte { + value 35101; + description + "TTEthernet Protocol Control Frame (TTE). Hex value + of 0x891D."; + reference + "SAE AS6802."; + } + enum hsr { + value 35119; + description + "High-availability Seamless Redundancy (HSR). Hex + value of 0x892F."; + reference + "IEC 62439-3:2016."; + } + } + } + description + "The uint16 type placeholder is defined to enable + users to manage their own ethertypes not + covered by the module. Otherwise, the module contains + enum definitions for the more commonly used ethertypes."; + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-inet-types@2013-07-15.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-inet-types@2013-07-15.yang new file mode 100644 index 000000000..790bafc31 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-inet-types@2013-07-15.yang @@ -0,0 +1,459 @@ + module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + length "1..253"; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-l3-unicast-topology@2018-02-26.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-l3-unicast-topology@2018-02-26.yang new file mode 100644 index 000000000..39fcebd76 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-l3-unicast-topology@2018-02-26.yang @@ -0,0 +1,359 @@ +module ietf-l3-unicast-topology { + yang-version 1.1; + namespace + "urn:ietf:params:xml:ns:yang:ietf-l3-unicast-topology"; + prefix "l3t"; + import ietf-network { + prefix "nw"; + } + import ietf-network-topology { + prefix "nt"; + } + import ietf-inet-types { + prefix "inet"; + } + import ietf-routing-types { + prefix "rt-types"; + } + organization + "IETF I2RS (Interface to the Routing System) Working Group"; + contact + "WG Web: + WG List: + Editor: Alexander Clemm + + Editor: Jan Medved + + Editor: Robert Varga + + Editor: Xufeng Liu + + Editor: Nitin Bahadur + + Editor: Hariharan Ananthakrishnan + "; + description + "This module defines a model for Layer 3 Unicast + topologies. + + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of + RFC 8346; see the RFC itself for full legal notices."; + revision "2018-02-26" { + description + "Initial revision."; + reference + "RFC 8346: A YANG Data Model for Layer 3 Topologies"; + } + + identity flag-identity { + description "Base type for flags"; + } + + typedef l3-event-type { + type enumeration { + enum "add" { + description + "A Layer 3 node, link, prefix, or termination point has + been added"; + } + enum "remove" { + description + "A Layer 3 node, link, prefix, or termination point has + been removed"; + } + enum "update" { + description + "A Layer 3 node, link, prefix, or termination point has + been updated"; + } + } + description "Layer 3 event type for notifications"; + } + + typedef prefix-flag-type { + type identityref { + base "flag-identity"; + } + description "Prefix flag attributes"; + } + + typedef node-flag-type { + type identityref { + base "flag-identity"; + } + description "Node flag attributes"; + } + + typedef link-flag-type { + type identityref { + base "flag-identity"; + } + description "Link flag attributes"; + } + + typedef l3-flag-type { + type identityref { + base "flag-identity"; + } + description "L3 flag attributes"; + } + + grouping l3-prefix-attributes { + description + "L3 prefix attributes"; + leaf prefix { + type inet:ip-prefix; + description + "IP prefix value"; + } + leaf metric { + type uint32; + description + "Prefix metric"; + } + leaf-list flag { + type prefix-flag-type; + description + "Prefix flags"; + } + } + grouping l3-unicast-topology-type { + description "Identifies the topology type to be L3 Unicast."; + container l3-unicast-topology { + presence "indicates L3 Unicast topology"; + description + "The presence of the container node indicates L3 Unicast + topology"; + } + } + grouping l3-topology-attributes { + description "Topology scope attributes"; + container l3-topology-attributes { + description "Contains topology attributes"; + leaf name { + type string; + description + "Name of the topology"; + } + leaf-list flag { + type l3-flag-type; + description + "Topology flags"; + } + } + } + grouping l3-node-attributes { + description "L3 node scope attributes"; + container l3-node-attributes { + description + "Contains node attributes"; + leaf name { + type inet:domain-name; + description + "Node name"; + } + leaf-list flag { + type node-flag-type; + description + "Node flags"; + } + leaf-list router-id { + type rt-types:router-id; + description + "Router-id for the node"; + } + list prefix { + key "prefix"; + description + "A list of prefixes along with their attributes"; + uses l3-prefix-attributes; + } + } + } + grouping l3-link-attributes { + description + "L3 link scope attributes"; + container l3-link-attributes { + description + "Contains link attributes"; + leaf name { + type string; + description + "Link Name"; + } + leaf-list flag { + type link-flag-type; + description + "Link flags"; + } + leaf metric1 { + type uint64; + description + "Link Metric 1"; + } + leaf metric2 { + type uint64; + description + "Link Metric 2"; + } + } + } + grouping l3-termination-point-attributes { + description "L3 termination point scope attributes"; + container l3-termination-point-attributes { + description + "Contains termination point attributes"; + choice termination-point-type { + description + "Indicates the termination point type"; + case ip { + leaf-list ip-address { + type inet:ip-address; + description + "IPv4 or IPv6 address."; + } + } + case unnumbered { + leaf unnumbered-id { + type uint32; + description + "Unnumbered interface identifier. + The identifier will correspond to the ifIndex value + of the interface, i.e., the ifIndex value of the + ifEntry that represents the interface in + implementations where the Interfaces Group MIB + (RFC 2863) is supported."; + reference + "RFC 2863: The Interfaces Group MIB"; + } + } + case interface-name { + leaf interface-name { + type string; + description + "Name of the interface. The name can (but does not + have to) correspond to an interface reference of a + containing node's interface, i.e., the path name of a + corresponding interface data node on the containing + node reminiscent of data type interface-ref defined + in RFC 8343. It should be noted that data type + interface-ref of RFC 8343 cannot be used directly, + + as this data type is used to reference an interface + in a datastore of a single node in the network, not + to uniquely reference interfaces across a network."; + reference + "RFC 8343: A YANG Data Model for Interface Management"; + } + } + } + } + } + augment "/nw:networks/nw:network/nw:network-types" { + description + "Introduces new network type for L3 Unicast topology"; + uses l3-unicast-topology-type; + } + augment "/nw:networks/nw:network" { + when "nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description + "L3 Unicast for the network as a whole"; + uses l3-topology-attributes; + } + augment "/nw:networks/nw:network/nw:node" { + when "../nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description + "L3 Unicast node-level attributes "; + uses l3-node-attributes; + } + augment "/nw:networks/nw:network/nt:link" { + when "../nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description + "Augments topology link attributes"; + uses l3-link-attributes; + } + augment "/nw:networks/nw:network/nw:node/" + +"nt:termination-point" { + when "../../nw:network-types/l3t:l3-unicast-topology" { + description + "Augmentation parameters apply only for networks with + L3 Unicast topology"; + } + description "Augments topology termination point configuration"; + uses l3-termination-point-attributes; + } + notification l3-node-event { + description + "Notification event for L3 node"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nw:node-ref; + uses l3-unicast-topology-type; + uses l3-node-attributes; + } + notification l3-link-event { + description + "Notification event for L3 link"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nt:link-ref; + uses l3-unicast-topology-type; + uses l3-link-attributes; + } + notification l3-prefix-event { + description + "Notification event for L3 prefix"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nw:node-ref; + uses l3-unicast-topology-type; + container prefix { + description + "Contains L3 prefix attributes"; + uses l3-prefix-attributes; + } + } + notification termination-point-event { + description + "Notification event for L3 termination point"; + leaf l3-event-type { + type l3-event-type; + description + "Event type"; + } + uses nt:tp-ref; + uses l3-unicast-topology-type; + uses l3-termination-point-attributes; + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-layer1-types@2022-10-14.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-layer1-types@2022-10-14.yang new file mode 100644 index 000000000..188336931 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-layer1-types@2022-10-14.yang @@ -0,0 +1,1414 @@ + module ietf-layer1-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-layer1-types"; + prefix "l1-types"; + + import ietf-routing-types { + prefix rt-types; + reference + "RFC 8294: Common YANG Data Types for the Routing Area"; + } + + organization + "IETF CCAMP Working Group"; + contact + "WG Web: + WG List: + + Editor: Haomian Zheng + + + Editor: Italo Busi + "; + + description + "This module defines Layer 1 types. The model fully conforms + to the Network Management Datastore Architecture (NMDA). + + Copyright (c) 2022 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Revised BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + + + + + they appear in all capitals, as shown here."; + + revision "2022-10-14" { + description + "Initial Version"; + reference + "RFC XXXX: A YANG Data Model for Layer 1 Types"; + // RFC Editor: replace XXXX with actual RFC number, update date + // information and remove this note + } + + /* + * Identities + */ + + identity tributary-slot-granularity { + description + "Tributary Slot Granularity (TSG)"; + reference + "ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity tsg-1.25G { + base tributary-slot-granularity; + description + "1.25G tributary slot granularity"; + } + + identity tsg-2.5G { + base tributary-slot-granularity; + description + "2.5G tributary slot granularity"; + } + + identity tsg-5G { + base tributary-slot-granularity; + description + "5G tributary slot granularity"; + } + + identity odu-type { + description + "Base identity from which specific Optical Data Unit (ODU) + type is derived."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + + + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODU0 { + base odu-type; + description + "ODU0 type (1.24Gb/s)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODU1 { + base odu-type; + description + "ODU1 type (2.49Gb/s)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODU2 { + base odu-type; + description + "ODU2 type (10.03Gb/s)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODU2e { + base odu-type; + description + "ODU2e type (10.39Gb/s)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + + + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODU3 { + base odu-type; + description + "ODU3 type (40.31Gb/s)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODU4 { + base odu-type; + description + "ODU4 type (104.79Gb/s)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODUflex { + base odu-type; + description + "ODUflex type (flexible bit rate, not resizable). + + It could be used for any type of ODUflex, including + ODUflex(CBR), ODUflex(GFP), ODUflex(GFP,n,k), ODUflex(IMP,s), + ODUflex(IMP) and ODUflex(FlexE-aware)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ODUflex-resizable { + base odu-type; + description + "ODUflex protocol (flexible bit rate, resizable). + + + + + It could be used only for ODUflex(GFP,n,k)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity protocol { + description + "Base identity from which specific protocol is derived."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity Ethernet { + base protocol; + description + "Ethernet protocol."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity Fibre-Channel { + base protocol; + description + "Fibre-Channel (FC) protocol."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity SDH { + base protocol; + description + "SDH protocol."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity SONET { + base protocol; + description + "SONET protocol."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + + + + identity client-signal { + description + "Base identity from which specific Constant Bit Rate (CBR) + client signal is derived"; + } + + identity coding-func { + description + "Base identity from which specific coding function + is derived."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ETH-1Gb { + base client-signal; + description + "Client signal type of 1GbE"; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ETH-10Gb-LAN { + base client-signal; + description + "Client signal type of ETH-10Gb-LAN (10.3 Gb/s)"; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + IEEE 802.3-2018, Clause 49: IEEE Standard for Ethernet"; + } + + identity ETH-10Gb-WAN { + base client-signal; + description + "Client signal type of ETH-10Gb-WAN (9.95 Gb/s)"; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + + + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + IEEE 802.3-2018, Clause 50: IEEE Standard for Ethernet"; + } + + identity ETH-40Gb { + base client-signal; + description + "Client signal type of 40GbE"; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ETH-100Gb { + base client-signal; + description + "Client signal type of 100GbE"; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity STM-1 { + base client-signal; + base coding-func; + description + "Client signal type of STM-1; + STM-1 G.707 (N=1) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity STM-4 { + base client-signal; + + + + + base coding-func; + description + "Client signal type of STM-4; + STM-4 G.707 (N=4) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity STM-16 { + base client-signal; + base coding-func; + description + "Client signal type of STM-16; + STM-16 G.707 (N=16) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity STM-64 { + base client-signal; + base coding-func; + description + "Client signal type of STM-64; + STM-64 G.707 (N=64) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity STM-256 { + base client-signal; + + + + + base coding-func; + description + "Client signal type of STM-256; + STM-256 G.707 (N=256) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity OC-3 { + base client-signal; + base coding-func; + description + "Client signal type of OC3; + OC-3 GR-253-CORE (N=3) coding function."; + reference + "ANSI T1.105-1995: Synchronous Optical Network (SONET) + Basic Description including Multiplex Structure, Rates, + and Formats + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity OC-12 { + base client-signal; + base coding-func; + description + "Client signal type of OC12; + OC-12 GR-253-CORE (N=12) coding function."; + reference + "ANSI T1.105-1995: Synchronous Optical Network (SONET) + Basic Description including Multiplex Structure, Rates, + and Formats + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity OC-48 { + base client-signal; + base coding-func; + description + "Client signal type of OC48; + OC-48 GR-253-CORE (N=48) coding function."; + + + + + reference + "ANSI T1.105-1995: Synchronous Optical Network (SONET) + Basic Description including Multiplex Structure, Rates, + and Formats + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity OC-192 { + base client-signal; + base coding-func; + description + "Client signal type of OC192; + OC-192 GR-253-CORE (N=192) coding function."; + reference + "ANSI T1.105-1995: Synchronous Optical Network (SONET) + Basic Description including Multiplex Structure, Rates, + and Formats + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity OC-768 { + base client-signal; + base coding-func; + description + "Client signal type of OC768; + OC-768 GR-253-CORE (N=768) coding function."; + reference + "ANSI T1.105-1995: Synchronous Optical Network (SONET) + Basic Description including Multiplex Structure, Rates, + and Formats + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FC-100 { + base client-signal; + base coding-func; + description + "Client signal type of Fibre Channel FC-100; + FC-100 FC-FS-2 (1.0625 Gb/s) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + + + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FC-200 { + base client-signal; + base coding-func; + description + "Client signal type of Fibre Channel FC-200; + FC-200 FC-FS-2 (2.125 Gb/s) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FC-400 { + base client-signal; + base coding-func; + description + "Client signal type of Fibre Channel FC-400; + FC-400 FC-FS-2 (4.250 Gb/s) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FC-800 { + base client-signal; + base coding-func; + description + "Client signal type of Fibre Channel FC-800; + FC-800 FC-FS-2 (8.500 Gb/s) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + + + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FC-1200 { + base client-signal; + base coding-func; + description + "Client signal type of Fibre Channel FC-1200; + FC-1200 FC-10GFC (10.51875 Gb/s) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FC-1600 { + base client-signal; + base coding-func; + description + "Client signal type of Fibre Channel FC-1600; + FC-1600 FC-FS-3 (14.025 Gb/s) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FC-3200 { + base client-signal; + base coding-func; + description + "Client signal type of Fibre Channel FC-3200; + FC-3200 FC-FS-4 (28.05 Gb/s) coding function."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN) + + + + + MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FICON-4G { + base client-signal; + description + "Client signal type of Fibre Connection 4G"; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity FICON-8G { + base client-signal; + description + "Client signal type of Fibre Connection 8G"; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks + + ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + + identity ETH-1000X { + base coding-func; + description + "1000BASE-X PCS clause 36 coding function."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ETH-10GW { + base coding-func; + description + "10GBASE-W (WAN PHY) PCS clause 49 and WIS clause 50 + coding function."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ETH-10GR { + base coding-func; + description + "10GBASE-R (LAN PHY) PCS clause 49 coding function."; + + + + + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ETH-40GR { + base coding-func; + description + "40GBASE-R PCS clause 82 coding function."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ETH-100GR { + base coding-func; + description + "100GBASE-R PCS clause 82 coding function."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity optical-interface-func { + description + "Base identity from which optical-interface-function + is derived."; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity SX-PMD-1000 { + base optical-interface-func; + description + "SX-PMD-clause-38 Optical Interface function for + 1000BASE-X PCS-36"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity LX-PMD-1000 { + base optical-interface-func; + description + "LX-PMD-clause-38 Optical Interface function for + 1000BASE-X PCS-36"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity LX10-PMD-1000 { + base optical-interface-func; + + + + + description + "LX10-PMD-clause-59 Optical Interface function for + 1000BASE-X PCS-36"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity BX10-PMD-1000 { + base optical-interface-func; + description + "BX10-PMD-clause-59 Optical Interface function for + 1000BASE-X PCS-36"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity LW-PMD-10G { + base optical-interface-func; + description + "LW-PMD-clause-52 Optical Interface function for + 10GBASE-W PCS-49-WIS-50"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity EW-PMD-10G { + base optical-interface-func; + description + "EW-PMD-clause-52 Optical Interface function for + 10GBASE-W PCS-49-WIS-50"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity LR-PMD-10G { + base optical-interface-func; + description + "LR-PMD-clause-52 Optical Interface function for + 10GBASE-R PCS-49"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ER-PMD-10G { + base optical-interface-func; + description + "ER-PMD-clause-52 Optical Interface function for + 10GBASE-R PCS-49"; + + + + + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity LR4-PMD-40G { + base optical-interface-func; + description + "LR4-PMD-clause-87 Optical Interface function for + 40GBASE-R PCS-82"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ER4-PMD-40G { + base optical-interface-func; + description + "ER4-PMD-clause-87 Optical Interface function for + 40GBASE-R PCS-82"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity FR-PMD-40G { + base optical-interface-func; + description + "FR-PMD-clause-89 Optical Interface function for + 40GBASE-R PCS-82"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity LR4-PMD-100G { + base optical-interface-func; + description + "LR4-PMD-clause-88 Optical Interface function for + 100GBASE-R PCS-82"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + identity ER4-PMD-100G { + base optical-interface-func; + description + "ER4-PMD-clause-88 Optical Interface function for + 100GBASE-R PCS-82"; + reference + "MEF63: Subscriber Layer 1 Service Attributes"; + } + + + + + /* + * Typedefs + */ + + typedef otn-tpn { + type uint16 { + range "1..4095"; + } + description + "Tributary Port Number (TPN) for OTN. "; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks."; + } + + typedef otn-ts { + type uint16 { + range "1..4095"; + } + description + "Tributary Slot (TS) for OTN."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of Evolving + G.709 Optical Transport Networks."; + } + + typedef otn-label-range-type { + type enumeration { + enum trib-slot { + description + "Defines a range of OTN tributary slots (TS)."; + } + enum trib-port { + description + "Defines a range of OTN tributary ports (TPN)."; + } + } + description + "Defines the type of OTN label range: TS or TPN. "; + } + + typedef gfp-k { + type enumeration { + enum 2 { + description + "The ODU2.ts rate (1,249,177.230 kbit/s) is used + to compute the rate of an ODUflex(GFP,n,2). "; + } + + + + + enum 3 { + description + "The ODU3.ts rate (1,254,470.354 kbit/s) is used + to compute the rate of an ODUflex(GFP,n,3). "; + } + enum 4 { + description + "The ODU4.ts rate (1,301,467.133 kbit/s) is used + to compute the rate of an ODUflex(GFP,n,4). "; + } + } + description + "The ODUk.ts used to compute the rate of an ODUflex(GFP,n,k)"; + reference + "ITU-T G.709 v6.0 (06/2020), Table 7-8 and L.7: Interfaces for + the Optical Transport Network (OTN)"; + } + + typedef flexe-client-rate { + type union { + type uint16; + type enumeration { + enum "10G" { + description + "Represents a 10G FlexE Client signal (s=2)"; + } + enum "40G" { + description + "Represents a 40G FlexE Client signal (s=8)"; + } + } + } + description + "The FlexE Client signal rate (s x 5,156,250.000 kbit/s) + used to compute the rate of an ODUflex(IMP, s). + Valid values for s are s=2 (10G), s=4 (40G) and + s=5 x n (n x 25G). + In the first two cases an enumeration value + (either 10G or 40G) is used, while in the latter case + the value of n is used"; + reference + "ITU-T G.709 v6.0 (06/2020), Table 7-2: Interfaces for the + Optical Transport Network (OTN)"; + } + + typedef odtu-flex-type { + type enumeration { + enum "2" { + + + + + description + "The ODTU2.ts ODTU type."; + } + enum "3" { + description + "The ODTU3.ts ODTU type."; + } + enum "4" { + description + "The ODTU4.ts ODTU type."; + } + enum "Cn" { + description + "The ODTUCn.ts ODTU type."; + } + } + description + "The type of Optical Data Tributary Unit (ODTU), + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by an ODUflex LSP, according to + the (19-1a) and (20-1a) formulas defined in G.709."; + reference + "ITU-T G.709 v6.0 (06/2020), Table 7-7, clause 19.6 and + clause 20.5: Interfaces for the Optical Transport + Network (OTN)"; + } + + typedef bandwidth-scientific-notation { + type string { + pattern + '0(\.0?)?([eE](\+)?0?)?|' + + '[1-9](\.[0-9]{0,6})?[eE](\+)?(9[0-6]|[1-8][0-9]|0?[0-9])?'; + } + units "bps"; + description + "Bandwidth values, expressed using the scientific notation + in bits per second. + + The encoding format is the external decimal-significant + character sequences specified in IEEE 754 and ISO/IEC C99 + for 32-bit decimal floating-point numbers: + (-1)**(S) * 10**(Exponent) * (Significant), + where Significant uses 7 digits. + + An implementation for this representation MAY use decimal32 + or binary32. The range of the Exponent is from -95 to +96 + for decimal32, and from -38 to +38 for binary32. + As a bandwidth value, the format is restricted to be + + + + + normalized, non-negative, and non-fraction: + n.dddddde{+}dd, N.DDDDDDE{+}DD, 0e0 or 0E0, + where 'd' and 'D' are decimal digits; 'n' and 'N' are + non-zero decimal digits; 'e' and 'E' indicate a power of ten. + Some examples are 0e0, 1e10, and 9.953e9."; + reference + "IEEE Std 754-2008: IEEE Standard for Floating-Point + Arithmetic. + ISO/IEC C99: Information technology - Programming + Languages - C."; + } + + /* + * Groupings + */ + + grouping otn-link-bandwidth { + description + "Bandwidth attributes for OTN links"; + container otn { + description + "Bandwidth attributes for OTN links"; + list odulist { + key "odu-type"; + description + "OTN bandwidth definition"; + leaf odu-type { + type identityref { + base odu-type; + } + description "ODU type"; + } + leaf number { + type uint16; + description "Number of ODUs"; + } + leaf ts-number { + when 'derived-from-or-self(../odu-type,"ODUflex") or + derived-from-or-self(../odu-type, + "ODUflex-resizable")' { + description + "Applicable when odu-type is ODUflex or + ODUflex-resizable"; + } + type uint16 { + range "1..4095"; + } + description + + + + + "The number of Tributary Slots (TS) that + could be used by all the ODUflex LSPs."; + } + } + } + } + + grouping otn-path-bandwidth { + description + "Bandwidth attributes for OTN paths."; + container otn { + description + "Bandwidth attributes for OTN paths."; + leaf odu-type { + type identityref { + base odu-type; + } + description "ODU type"; + } + choice oduflex-type { + when 'derived-from-or-self(./odu-type,"ODUflex") or + derived-from-or-self(./odu-type, + "ODUflex-resizable")' { + description + "Applicable when odu-type is ODUflex or + ODUflex-resizable"; + } + description + "Types of ODUflex used to compute the ODUflex + nominal bit rate."; + reference + "ITU-T G.709 v6.0 (06/2020), Table 7-2: Interfaces for the + Optical Transport Network (OTN)"; + case generic { + leaf nominal-bit-rate { + type union { + type l1-types:bandwidth-scientific-notation; + type rt-types:bandwidth-ieee-float32; + } + mandatory true; + description + "Nominal ODUflex bit rate."; + } + } + case cbr { + leaf client-type { + type identityref { + base client-signal; + + + + + } + mandatory true; + description + "The type of Constant Bit Rate (CBR) client signal + of an ODUflex(CBR)."; + } + } + case gfp-n-k { + leaf gfp-n { + type uint8 { + range "1..80"; + } + mandatory true; + description + "The value of n for an ODUflex(GFP,n,k)."; + reference + "ITU-T G.709 v6.0 (06/2020), Tables 7-8 and L.7: + Interfaces for the Optical Transport Network (OTN)"; + } + leaf gfp-k { + type gfp-k; + description + "The value of k for an ODUflex(GFP,n,k). + + If omitted, it is calculated from the value of gfp-n + as described in Table 7-8 of G.709"; + reference + "ITU-T G.709 v6.0 (06/2020), Tables 7-8 and L.7: + Interfaces for the Optical Transport Network (OTN)"; + } + } + case flexe-client { + leaf flexe-client { + type flexe-client-rate; + mandatory true; + description + "The rate of the FlexE-client for an ODUflex(IMP,s)."; + } + } + case flexe-aware { + leaf flexe-aware-n { + type uint16; + mandatory true; + description + "The rate of FlexE-aware client signal + for ODUflex(FlexE-aware)"; + } + } + + + + + case packet { + leaf opuflex-payload-rate { + type union { + type l1-types:bandwidth-scientific-notation; + type rt-types:bandwidth-ieee-float32; + } + mandatory true; + description + "Either the GFP-F encapsulated packet client nominal + bit rate for an ODUflex(GFP) or the 64b/66b encoded + packet client nominal bit rate for an ODUflex(IMP)."; + } + } + } + } + } + + grouping otn-max-path-bandwidth { + description + "Maximum bandwidth attributes for OTN paths."; + container otn { + description + "Maximum bandwidth attributes for OTN paths."; + leaf odu-type { + type identityref { + base odu-type; + } + description "ODU type"; + } + leaf max-ts-number { + when 'derived-from-or-self(../odu-type,"ODUflex") or + derived-from-or-self(../odu-type, + "ODUflex-resizable")' { + description + "Applicable when odu-type is ODUflex or + ODUflex-resizable"; + } + type uint16 { + range "1..4095"; + } + description + "The maximum number of Tributary Slots (TS) that could be + used by an ODUflex LSP."; + } + } + } + + grouping otn-label-range-info { + + + + + description + "Label range information for OTN. + + This grouping SHOULD be used together with the + otn-label-start-end and otn-label-step groupings to provide + OTN technology-specific label information to the models which + use the label-restriction-info grouping defined in the module + ietf-te-types."; + container otn-label-range { + description + "Label range information for OTN."; + leaf range-type { + type otn-label-range-type; + description "The type of range (e.g., TPN or TS) + to which the label range applies"; + } + leaf tsg { + type identityref { + base tributary-slot-granularity; + } + description + "Tributary slot granularity (TSG) to which the label range + applies. + + This leaf MUST be present when the range-type is TS. + + This leaf MAY be omitted when mapping an ODUk over an OTUk + Link. In this case the range-type is tpn, with only one + entry (ODUk), and the tpn range has only one value (1)."; + reference + "ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + leaf-list odu-type-list { + type identityref { + base odu-type; + } + description + "List of ODU types to which the label range applies. + + An Empty odu-type-list means that the label range + applies to all the supported ODU types."; + } + leaf priority { + type uint8 { + range 0..7; + } + description + + + + + "Priority in Interface Switching Capability + Descriptor (ISCD)."; + reference + "RFC4203: OSPF Extensions in Support of Generalized + Multi-Protocol Label Switching (GMPLS)"; + } + } + } + + grouping otn-label-start-end { + description + "The OTN label-start or label-end used to specify an OTN label + range. + + This grouping is dependent on the range-type defined in the + otn-label-range-info grouping. + + This grouping SHOULD be used together with the + otn-label-range-info and otn-label-step groupings to provide + OTN technology-specific label information to the models which + use the label-restriction-info grouping defined in the module + ietf-te-types."; + container otn { + description + "Label start or label end for OTN."; + choice range-type { + description + "OTN label range type, either TPN range or TS range"; + case trib-port { + leaf tpn { + when "../../../../otn-label-range/range-type = + 'trib-port'" { + description + "Valid only when range-type represented by + trib-port"; + } + type otn-tpn; + description + "Tributary Port Number (TPN)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of + Evolving G.709 Optical Transport Networks."; + } + } + case trib-slot { + leaf ts { + when "../../../../otn-label-range/range-type = + 'trib-slot'" { + + + + + description + "Valid only when range-type represented by + trib-slot"; + } + type otn-ts; + description + "Tributary Slot (TS) number."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of + Evolving G.709 Optical Transport Networks"; + } + } + } + } + } + + grouping otn-label-hop { + description "OTN Label"; + reference + "RFC7139, section 6: GMPLS Signaling Extensions for Control of + Evolving G.709 Optical Transport Networks"; + container otn { + description + "Label hop for OTN."; + leaf tpn { + type otn-tpn; + description + "Tributary Port Number (TPN)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of + Evolving G.709 Optical Transport Networks."; + } + leaf tsg { + type identityref { + base tributary-slot-granularity; + } + description "Tributary Slot Granularity (TSG)."; + reference + "ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + leaf ts-list { + type string { + pattern "([1-9][0-9]{0,3}(-[1-9][0-9]{0,3})?" + + "(,[1-9][0-9]{0,3}(-[1-9][0-9]{0,3})?)*)"; + } + description + "A list of available Tributary Slots (TS) ranging + + + + + between 1 and 4095. If multiple values or + ranges are given, they all MUST be disjoint + and MUST be in ascending order. + For example 1-20,25,50-1000."; + reference + "RFC 7139: GMPLS Signaling Extensions for Control + of Evolving G.709 Optical Transport Networks"; + } + } + } + + grouping otn-label-step { + description + "Label step for OTN. + + This grouping is dependent on the range-type defined in the + otn-label-range-info grouping. + + This grouping SHOULD be used together with the + otn-label-range-info and otn-label-start-end groupings to + provide OTN technology-specific label information to the + models which use the label-restriction-info grouping defined + in the module ietf-te-types."; + container otn { + description + "Label step for OTN"; + choice range-type { + description + "OTN label range type, either TPN range or TS range"; + case trib-port { + leaf tpn { + when "../../../otn-label-range/range-type = + 'trib-port'" { + description + "Valid only when range-type represented by + trib-port"; + } + type otn-tpn; + description + "Label step which represents possible increments for + Tributary Port Number (TPN)."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of + Evolving G.709 Optical Transport Networks."; + } + } + case trib-slot { + leaf ts { + + + + + when "../../../otn-label-range/range-type = + 'trib-slot'" { + description + "Valid only when range-type represented by + trib-slot"; + } + type otn-ts; + description + "Label step which represents possible increments for + Tributary Slot (TS) number."; + reference + "RFC7139: GMPLS Signaling Extensions for Control of + Evolving G.709 Optical Transport Networks."; + } + } + } + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-netconf-acm@2018-02-14.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-netconf-acm@2018-02-14.yang new file mode 100644 index 000000000..bf4855faf --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-netconf-acm@2018-02-14.yang @@ -0,0 +1,464 @@ +module ietf-netconf-acm { + + namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"; + + prefix nacm; + + import ietf-yang-types { + prefix yang; + } + + organization + "IETF NETCONF (Network Configuration) Working Group"; + + contact + "WG Web: + WG List: + + Author: Andy Bierman + + + Author: Martin Bjorklund + "; + + description + "Network Configuration Access Control Model. + + Copyright (c) 2012 - 2018 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's + Legal Provisions Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8341; see + the RFC itself for full legal notices."; + + revision "2018-02-14" { + description + "Added support for YANG 1.1 actions and notifications tied to + data nodes. Clarified how NACM extensions can be used by + other data models."; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + + revision "2012-02-22" { + description + "Initial version."; + reference + "RFC 6536: Network Configuration Protocol (NETCONF) + Access Control Model"; + } + + /* + * Extension statements + */ + + extension default-deny-write { + description + "Used to indicate that the data model node + represents a sensitive security system parameter. + + If present, the NETCONF server will only allow the designated + 'recovery session' to have write access to the node. An + explicit access control rule is required for all other users. + + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + + The 'default-deny-write' extension MAY appear within a data + definition statement. It is ignored otherwise."; + } + + extension default-deny-all { + description + "Used to indicate that the data model node + controls a very sensitive security system parameter. + + If present, the NETCONF server will only allow the designated + 'recovery session' to have read, write, or execute access to + the node. An explicit access control rule is required for all + other users. + + If the NACM module is used, then it must be enabled (i.e., + /nacm/enable-nacm object equals 'true'), or this extension + is ignored. + + The 'default-deny-all' extension MAY appear within a data + definition statement, 'rpc' statement, or 'notification' + statement. It is ignored otherwise."; + } + + /* + * Derived types + */ + + typedef user-name-type { + type string { + length "1..max"; + } + description + "General-purpose username string."; + } + + typedef matchall-string-type { + type string { + pattern '\*'; + } + description + "The string containing a single asterisk '*' is used + to conceptually represent all possible values + for the particular leaf using this data type."; + } + + typedef access-operations-type { + type bits { + bit create { + description + "Any protocol operation that creates a + new data node."; + } + bit read { + description + "Any protocol operation or notification that + returns the value of a data node."; + } + bit update { + description + "Any protocol operation that alters an existing + data node."; + } + bit delete { + description + "Any protocol operation that removes a data node."; + } + bit exec { + description + "Execution access to the specified protocol operation."; + } + } + description + "Access operation."; + } + + typedef group-name-type { + type string { + length "1..max"; + pattern '[^\*].*'; + } + description + "Name of administrative group to which + users can be assigned."; + } + + typedef action-type { + type enumeration { + enum permit { + description + "Requested action is permitted."; + } + enum deny { + description + "Requested action is denied."; + } + } + description + "Action taken by the server when a particular + rule matches."; + } + + typedef node-instance-identifier { + type yang:xpath1.0; + description + "Path expression used to represent a special + data node, action, or notification instance-identifier + string. + + A node-instance-identifier value is an + unrestricted YANG instance-identifier expression. + All the same rules as an instance-identifier apply, + except that predicates for keys are optional. If a key + predicate is missing, then the node-instance-identifier + represents all possible server instances for that key. + + This XML Path Language (XPath) expression is evaluated in the + following context: + + o The set of namespace declarations are those in scope on + the leaf element where this type is used. + + o The set of variable bindings contains one variable, + 'USER', which contains the name of the user of the + current session. + + o The function library is the core function library, but + note that due to the syntax restrictions of an + instance-identifier, no functions are allowed. + + o The context node is the root node in the data tree. + + The accessible tree includes actions and notifications tied + to data nodes."; + } + + /* + * Data definition statements + */ + + container nacm { + nacm:default-deny-all; + + description + "Parameters for NETCONF access control model."; + + leaf enable-nacm { + type boolean; + default "true"; + description + "Enables or disables all NETCONF access control + enforcement. If 'true', then enforcement + is enabled. If 'false', then enforcement + is disabled."; + } + + leaf read-default { + type action-type; + default "permit"; + description + "Controls whether read access is granted if + no appropriate rule is found for a + particular read request."; + } + + leaf write-default { + type action-type; + default "deny"; + description + "Controls whether create, update, or delete access + is granted if no appropriate rule is found for a + particular write request."; + } + + leaf exec-default { + type action-type; + default "permit"; + description + "Controls whether exec access is granted if no appropriate + rule is found for a particular protocol operation request."; + } + + leaf enable-external-groups { + type boolean; + default "true"; + description + "Controls whether the server uses the groups reported by the + NETCONF transport layer when it assigns the user to a set of + NACM groups. If this leaf has the value 'false', any group + names reported by the transport layer are ignored by the + server."; + } + + leaf denied-operations { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request was denied."; + } + + leaf denied-data-writes { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that a + protocol operation request to alter + a configuration datastore was denied."; + } + + leaf denied-notifications { + type yang:zero-based-counter32; + config false; + mandatory true; + description + "Number of times since the server last restarted that + a notification was dropped for a subscription because + access to the event type was denied."; + } + + container groups { + description + "NETCONF access control groups."; + + list group { + key name; + + description + "One NACM group entry. This list will only contain + configured entries, not any entries learned from + any transport protocols."; + + leaf name { + type group-name-type; + description + "Group name associated with this entry."; + } + + leaf-list user-name { + type user-name-type; + description + "Each entry identifies the username of + a member of the group associated with + this entry."; + } + } + } + + list rule-list { + key name; + ordered-by user; + description + "An ordered collection of access control rules."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule-list."; + } + leaf-list group { + type union { + type matchall-string-type; + type group-name-type; + } + description + "List of administrative groups that will be + assigned the associated access rights + defined by the 'rule' list. + + The string '*' indicates that all groups apply to the + entry."; + } + + list rule { + key name; + ordered-by user; + description + "One access control rule. + + Rules are processed in user-defined order until a match is + found. A rule matches if 'module-name', 'rule-type', and + 'access-operations' match the request. If a rule + matches, the 'action' leaf determines whether or not + access is granted."; + + leaf name { + type string { + length "1..max"; + } + description + "Arbitrary name assigned to the rule."; + } + + leaf module-name { + type union { + type matchall-string-type; + type string; + } + default "*"; + description + "Name of the module associated with this rule. + + This leaf matches if it has the value '*' or if the + object being accessed is defined in the module with the + specified module name."; + } + choice rule-type { + description + "This choice matches if all leafs present in the rule + match the request. If no leafs are present, the + choice matches all requests."; + case protocol-operation { + leaf rpc-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if + its value equals the requested protocol operation + name."; + } + } + case notification { + leaf notification-name { + type union { + type matchall-string-type; + type string; + } + description + "This leaf matches if it has the value '*' or if its + value equals the requested notification name."; + } + } + + case data-node { + leaf path { + type node-instance-identifier; + mandatory true; + description + "Data node instance-identifier associated with the + data node, action, or notification controlled by + this rule. + + Configuration data or state data + instance-identifiers start with a top-level + data node. A complete instance-identifier is + required for this type of path value. + + The special value '/' refers to all possible + datastore contents."; + } + } + } + + leaf access-operations { + type union { + type matchall-string-type; + type access-operations-type; + } + default "*"; + description + "Access operations associated with this rule. + + This leaf matches if it has the value '*' or if the + bit corresponding to the requested operation is set."; + } + + leaf action { + type action-type; + mandatory true; + description + "The access control action associated with the + rule. If a rule has been determined to match a + particular request, then this object is used + to determine whether to permit or deny the + request."; + } + + leaf comment { + type string; + description + "A textual description of the access rule."; + } + } + } + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-network-topology@2018-02-26.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-network-topology@2018-02-26.yang new file mode 100644 index 000000000..0538ac01b --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-network-topology@2018-02-26.yang @@ -0,0 +1,294 @@ + module ietf-network-topology { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-network-topology"; + prefix nt; + + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-network { + prefix nw; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + + organization + "IETF I2RS (Interface to the Routing System) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Alexander Clemm + + + Editor: Jan Medved + + + Editor: Robert Varga + + + Editor: Nitin Bahadur + + + Editor: Hariharan Ananthakrishnan + + + Editor: Xufeng Liu + "; + + description + "This module defines a common base model for a network topology, + augmenting the base network data model with links to connect + nodes, as well as termination points to terminate links + on nodes. + + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8345; + see the RFC itself for full legal notices."; + + revision 2018-02-26 { + description + "Initial revision."; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + + typedef link-id { + type inet:uri; + description + "An identifier for a link in a topology. The precise + structure of the link-id will be up to the implementation. + The identifier SHOULD be chosen such that the same link in a + real network topology will always be identified through the + same identifier, even if the data model is instantiated in + separate datastores. An implementation MAY choose to capture + semantics in the identifier -- for example, to indicate the + type of link and/or the type of topology of which the link is + a part."; + } + + typedef tp-id { + type inet:uri; + description + "An identifier for termination points on a node. The precise + structure of the tp-id will be up to the implementation. + The identifier SHOULD be chosen such that the same termination + point in a real network topology will always be identified + through the same identifier, even if the data model is + instantiated in separate datastores. An implementation MAY + choose to capture semantics in the identifier -- for example, + to indicate the type of termination point and/or the type of + node that contains the termination point."; + } + + grouping link-ref { + description + "This grouping can be used to reference a link in a specific + network. Although it is not used in this module, it is + defined here for the convenience of augmenting modules."; + leaf link-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../"+ + "network-ref]/nt:link/nt:link-id"; + require-instance false; + } + description + "A type for an absolute reference to a link instance. + (This type should not be used for relative references. + In such a case, a relative path should be used instead.)"; + } + uses nw:network-ref; + } + + grouping tp-ref { + description + "This grouping can be used to reference a termination point + in a specific node. Although it is not used in this module, + it is defined here for the convenience of augmenting + modules."; + leaf tp-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../"+ + "network-ref]/nw:node[nw:node-id=current()/../"+ + "node-ref]/nt:termination-point/nt:tp-id"; + require-instance false; + } + description + "A type for an absolute reference to a termination point. + (This type should not be used for relative references. + In such a case, a relative path should be used instead.)"; + } + uses nw:node-ref; + } + + augment "/nw:networks/nw:network" { + description + "Add links to the network data model."; + list link { + key "link-id"; + description + "A network link connects a local (source) node and + a remote (destination) node via a set of the respective + node's termination points. It is possible to have several + links between the same source and destination nodes. + Likewise, a link could potentially be re-homed between + termination points. Therefore, in order to ensure that we + would always know to distinguish between links, every link + is identified by a dedicated link identifier. Note that a + link models a point-to-point link, not a multipoint link."; + leaf link-id { + type link-id; + description + "The identifier of a link in the topology. + A link is specific to a topology to which it belongs."; + } + container source { + description + "This container holds the logical source of a particular + link."; + leaf source-node { + type leafref { + path "../../../nw:node/nw:node-id"; + require-instance false; + } + description + "Source node identifier. Must be in the same topology."; + } + leaf source-tp { + type leafref { + path "../../../nw:node[nw:node-id=current()/../"+ + "source-node]/termination-point/tp-id"; + require-instance false; + } + description + "This termination point is located within the source node + and terminates the link."; + } + } + + container destination { + description + "This container holds the logical destination of a + particular link."; + leaf dest-node { + type leafref { + path "../../../nw:node/nw:node-id"; + require-instance false; + } + description + "Destination node identifier. Must be in the same + network."; + } + leaf dest-tp { + type leafref { + path "../../../nw:node[nw:node-id=current()/../"+ + "dest-node]/termination-point/tp-id"; + require-instance false; + } + description + "This termination point is located within the + destination node and terminates the link."; + } + } + list supporting-link { + key "network-ref link-ref"; + description + "Identifies the link or links on which this link depends."; + leaf network-ref { + type leafref { + path "../../../nw:supporting-network/nw:network-ref"; + require-instance false; + } + description + "This leaf identifies in which underlay topology + the supporting link is present."; + } + + leaf link-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/"+ + "../network-ref]/link/link-id"; + require-instance false; + } + description + "This leaf identifies a link that is a part + of this link's underlay. Reference loops in which + a link identifies itself as its underlay, either + directly or transitively, are not allowed."; + } + } + } + } + augment "/nw:networks/nw:network/nw:node" { + description + "Augments termination points that terminate links. + Termination points can ultimately be mapped to interfaces."; + list termination-point { + key "tp-id"; + description + "A termination point can terminate a link. + Depending on the type of topology, a termination point + could, for example, refer to a port or an interface."; + leaf tp-id { + type tp-id; + description + "Termination point identifier."; + } + list supporting-termination-point { + key "network-ref node-ref tp-ref"; + description + "This list identifies any termination points on which a + given termination point depends or onto which it maps. + Those termination points will themselves be contained + in a supporting node. This dependency information can be + inferred from the dependencies between links. Therefore, + this item is not separately configurable. Hence, no + corresponding constraint needs to be articulated. + The corresponding information is simply provided by the + implementing system."; + + leaf network-ref { + type leafref { + path "../../../nw:supporting-node/nw:network-ref"; + require-instance false; + } + description + "This leaf identifies in which topology the + supporting termination point is present."; + } + leaf node-ref { + type leafref { + path "../../../nw:supporting-node/nw:node-ref"; + require-instance false; + } + description + "This leaf identifies in which node the supporting + termination point is present."; + } + leaf tp-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/"+ + "../network-ref]/nw:node[nw:node-id=current()/../"+ + "node-ref]/termination-point/tp-id"; + require-instance false; + } + description + "Reference to the underlay node (the underlay node must + be in a different topology)."; + } + } + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-network@2018-02-26.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-network@2018-02-26.yang new file mode 100644 index 000000000..d9da81eee --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-network@2018-02-26.yang @@ -0,0 +1,193 @@ + module ietf-network { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-network"; + prefix nw; + + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + + organization + "IETF I2RS (Interface to the Routing System) Working Group"; + + contact + "WG Web: + WG List: + + Editor: Alexander Clemm + + + Editor: Jan Medved + + + Editor: Robert Varga + + + Editor: Nitin Bahadur + + + Editor: Hariharan Ananthakrishnan + + + Editor: Xufeng Liu + "; + + description + "This module defines a common base data model for a collection + of nodes in a network. Node definitions are further used + in network topologies and inventories. + + Copyright (c) 2018 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8345; + see the RFC itself for full legal notices."; + + revision 2018-02-26 { + description + "Initial revision."; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + + typedef node-id { + type inet:uri; + description + "Identifier for a node. The precise structure of the node-id + will be up to the implementation. For example, some + implementations MAY pick a URI that includes the network-id + as part of the path. The identifier SHOULD be chosen + such that the same node in a real network topology will + always be identified through the same identifier, even if + the data model is instantiated in separate datastores. An + implementation MAY choose to capture semantics in the + identifier -- for example, to indicate the type of node."; + } + + typedef network-id { + type inet:uri; + description + "Identifier for a network. The precise structure of the + network-id will be up to the implementation. The identifier + SHOULD be chosen such that the same network will always be + identified through the same identifier, even if the data model + is instantiated in separate datastores. An implementation MAY + choose to capture semantics in the identifier -- for example, + to indicate the type of network."; + } + + grouping network-ref { + description + "Contains the information necessary to reference a network -- + for example, an underlay network."; + leaf network-ref { + type leafref { + path "/nw:networks/nw:network/nw:network-id"; + require-instance false; + } + description + "Used to reference a network -- for example, an underlay + network."; + } + } + + grouping node-ref { + description + "Contains the information necessary to reference a node."; + leaf node-ref { + type leafref { + path "/nw:networks/nw:network[nw:network-id=current()/../"+ + "network-ref]/nw:node/nw:node-id"; + require-instance false; + } + description + "Used to reference a node. + Nodes are identified relative to the network that + contains them."; + } + uses network-ref; + } + + container networks { + description + "Serves as a top-level container for a list of networks."; + list network { + key "network-id"; + description + "Describes a network. + A network typically contains an inventory of nodes, + topological information (augmented through the + network-topology data model), and layering information."; + leaf network-id { + type network-id; + description + "Identifies a network."; + } + container network-types { + description + "Serves as an augmentation target. + The network type is indicated through corresponding + presence containers augmented into this container."; + } + list supporting-network { + key "network-ref"; + description + "An underlay network, used to represent layered network + topologies."; + leaf network-ref { + type leafref { + path "/nw:networks/nw:network/nw:network-id"; + require-instance false; + } + description + "References the underlay network."; + } + } + + list node { + key "node-id"; + description + "The inventory of nodes of this network."; + leaf node-id { + type node-id; + description + "Uniquely identifies a node within the containing + network."; + } + list supporting-node { + key "network-ref node-ref"; + description + "Represents another node that is in an underlay network + and that supports this node. Used to represent layering + structure."; + leaf network-ref { + type leafref { + path "../../../nw:supporting-network/nw:network-ref"; + require-instance false; + } + description + "References the underlay network of which the + underlay node is a part."; + } + leaf node-ref { + type leafref { + path "/nw:networks/nw:network/nw:node/nw:node-id"; + require-instance false; + } + description + "References the underlay node itself."; + } + } + } + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-otn-topology@2023-07-06.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-otn-topology@2023-07-06.yang new file mode 100644 index 000000000..587612e8e --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-otn-topology@2023-07-06.yang @@ -0,0 +1,2405 @@ + module ietf-otn-topology { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-otn-topology"; + prefix "otnt"; + + import ietf-network { + prefix "nw"; + reference "RFC 8345: A YANG Data Model for Network Topologies"; + } + + import ietf-network-topology { + prefix "nt"; + reference "RFC 8345: A YANG Data Model for Network Topologies"; + } + + import ietf-te-topology { + prefix "tet"; + reference + "RFC 8795: YANG Data Model for Traffic Engineering + (TE) Topologies"; + } + + import ietf-layer1-types { + prefix "l1-types"; + reference + "I-D.ietf-ccamp-layer1-types: A YANG Data Model + for Layer 1 Types"; + } + + organization + "IETF CCAMP Working Group"; + contact + "WG Web: + WG List: + + Editor: Haomian Zheng + + + Editor: Italo Busi + + + Editor: Xufeng Liu + + + Editor: Sergio Belotti + + + + + + Editor: Oscar Gonzalez de Dios + "; + + description + "This module defines a protocol independent Layer 1/ODU topology + data model. The model fully conforms + to the Network Management Datastore Architecture (NMDA). + + Copyright (c) 2023 IETF Trust and the persons identified + as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Revised BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices. + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here."; + + revision 2023-07-06 { + description + "Initial Revision"; + reference + "RFC XXXX: A YANG Data Model for Optical Transport Network + Topology"; + // RFC Ed.: replace XXXX with actual RFC number, update date + // information and remove this note + } + + /* + * Groupings + */ + + grouping label-range-info { + description + "OTN technology-specific label range related information with + a presence container indicating that the label range is an + OTN technology-specific label range. + + This grouping SHOULD be used together with the + + + + + otn-label-start-end and otn-label-step groupings to provide + OTN technology-specific label information to the models which + use the label-restriction-info grouping defined in the module + ietf-te-types."; + uses l1-types:otn-label-range-info { + refine otn-label-range { + presence + "Indicates the label range is an OTN label range. + + This container MUST NOT be present if there are other + presence containers or attributes indicating another type + of label range."; + } + } + } + + /* + * Data nodes + */ + + augment "/nw:networks/nw:network/nw:network-types/" + + "tet:te-topology" { + container otn-topology { + presence "indicates a topology type of Optical Transport + Network (OTN)-electrical layer."; + description "OTN topology type"; + } + description "augment network types to include OTN newtork"; + } + + augment "/nw:networks/nw:network/nw:node/tet:te" + + "/tet:te-node-attributes" { + when "../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description "Augment only for OTN network."; + } + description "Augment TE node attributes."; + container otn-node { + presence "The TE node is an OTN node."; + description + "Introduce new TE node type for OTN node."; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes" { + when "../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + + + + + description "Augment only for OTN network."; + } + description "Augment link configuration"; + + container otn-link { + description + "Attributes of the OTN Link."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs set up + on this OTN Link."; + } + leaf tsg { + type identityref { + base l1-types:tributary-slot-granularity; + } + description "Tributary slot granularity."; + reference + "ITU-T G.709 v6.0 (06/2020): Interfaces for the Optical + Transport Network (OTN)"; + } + leaf distance { + type uint32; + description "distance in the unit of kilometers"; + } + } + container client-svc { + presence + "When present, indicates that the Link supports Costant + Bit Rate (CBR) client signals."; + description + "Attributes of the Link supporting CBR client signals."; + leaf-list supported-client-signal { + type identityref { + base l1-types:client-signal; + } + min-elements 1; + description + "List of client signal types supported by the Link."; + } + } + } + + augment "/nw:networks/nw:network/nw:node/nt:termination-point/" + + "tet:te" { + + + + + when "../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description "Augment only for OTN network"; + } + description "OTN TP attributes config in ODU topology."; + + container otn-ltp { + description + "Attributes of the OTN Link Termination Point (LTP)."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs set up + on this OTN Link Termination Point (LTP)."; + } + } + container client-svc { + presence + "When present, indicates that the Link Termination Point + (LTP) supports Costant Bit Rate (CBR) client signals."; + description + "OTN LTP Service attributes."; + leaf-list supported-client-signal { + type identityref { + base l1-types:client-signal; + } + description + "List of client signal types supported by the LTP."; + } + } + } + + /* + * Augment TE bandwidth + */ + + augment "/nw:networks/nw:network/nw:node/nt:termination-point/" + + "tet:te/" + + "tet:interface-switching-capability/tet:max-lsp-bandwidth/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + + + + + description + "Augment maximum LSP TE bandwidth for the link termination + point (LTP)."; + case otn { + uses l1-types:otn-max-path-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link Termination + Point (LTP) is used to compute the number of Tributary + Slots (TS) required by the ODUflex LSPs set up on this + OTN LTP."; + } + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE bandwidth path constraints of the TE node + connectivity matrices."; + case otn { + uses l1-types:otn-link-bandwidth { + augment otn { + description + "Augment OTN link bandwidth information."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs + set up along the underlay paths of these OTN + connectivity matrices."; + } + } + } + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + + + + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE bandwidth path constraints of the + connectivity matrix entry."; + case otn { + uses l1-types:otn-link-bandwidth { + augment otn { + description + "Augment OTN link bandwidth information."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs + set up along the underlay path of this OTN + connectivity matrix entry."; + } + } + } + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE bandwidth path constraints of the TE node + connectivity matrices information source."; + case otn { + uses l1-types:otn-link-bandwidth { + augment otn { + description + "Augment OTN link bandwidth information."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + + + + + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs + set up along the underlay paths of these OTN + connectivity matrices."; + } + } + } + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:path-constraints/tet:te-bandwidth/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE bandwidth path constraints of the + connectivity matrix entry information source"; + case otn { + uses l1-types:otn-link-bandwidth { + augment otn { + description + "Augment OTN link bandwidth information."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs + set up along the underlay path of this OTN + connectivity matrix entry."; + } + } + } + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:client-layer-adaptation/tet:switching-capability/" + + "tet:te-bandwidth/tet:technology" { + + + + + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment client TE bandwidth of the tunnel termination point + (TTP)"; + case otn { + uses l1-types:otn-link-bandwidth { + augment otn { + description + "Augment OTN link bandwidth information."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs + terminated on this OTN Tunnel Termination Point + (TTP)."; + } + } + } + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/tet:path-constraints/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE bandwidth path constraints for the TTP + Local Link Connectivities."; + case otn { + uses l1-types:otn-link-bandwidth { + augment otn { + description + "Augment OTN link bandwidth information."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + + + + + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs + set up along the underlay paths of these OTN Local + Link Connectivities."; + } + } + } + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/tet:path-constraints/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE bandwidth path constraints for the TTP + Local Link Connectivity entry."; + case otn { + uses l1-types:otn-link-bandwidth { + augment otn { + description + "Augment OTN link bandwidth information."; + leaf odtu-flex-type { + type l1-types:odtu-flex-type; + description + "The type of Optical Data Tributary Unit (ODTU) + whose nominal bitrate is used to compute the number of + Tributary Slots (TS) required by the ODUflex LSPs + set up along the underlay path of this OTN Local + Link Connectivyt entry."; + } + } + } + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:interface-switching-capability/tet:max-lsp-bandwidth/" + + + + + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment maximum LSP TE bandwidth for the TE link."; + case otn { + uses l1-types:otn-max-path-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:max-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment maximum TE bandwidth for the TE link"; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:max-resv-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + + + + + } + description + "Augment maximum reservable TE bandwidth for the TE link"; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:unreserved-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment unreserved TE bandwidth for the TE Link"; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:interface-switching-capability/" + + "tet:max-lsp-bandwidth/" + + "tet:te-bandwidth/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment maximum LSP TE bandwidth for the TE link + information source"; + case otn { + uses l1-types:otn-max-path-bandwidth { + description + + + + + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:max-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment maximum TE bandwidth for the TE link + information source"; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:max-resv-link-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment maximum reservable TE bandwidth for the TE link + information-source"; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + + + + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:unreserved-bandwidth/" + + "tet:te-bandwidth" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment unreserved TE bandwidth of the TE link + information source"; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on this OTN Link."; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:interface-switching-capability/" + + "tet:max-lsp-bandwidth/" + + "tet:te-bandwidth/tet:technology" { + description + "Augment maximum LSP TE bandwidth of the TE link + template"; + case otn { + uses l1-types:otn-max-path-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on the OTN Link that uses this + Link Template."; + } + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:max-link-bandwidth/" + + "tet:te-bandwidth" { + description + "Augment maximum TE bandwidth the TE link template"; + uses l1-types:otn-link-bandwidth { + description + + + + + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on the OTN Link that uses this + Link Template."; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:max-resv-link-bandwidth/" + + "tet:te-bandwidth" { + description + "Augment maximum reservable TE bandwidth for the TE link + template."; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on the OTN Link that uses this + Link Template."; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:unreserved-bandwidth/" + + "tet:te-bandwidth" { + description + "Augment unreserved TE bandwidth the TE link template"; + uses l1-types:otn-link-bandwidth { + description + "The odtu-flex-type attribute of the OTN Link is used + to compute the number of Tributary Slots (TS) required + by the ODUflex LSPs set up on the OTN Link that uses this + Link Template."; + } + } + + /* + * Augment TE label range information + */ + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + + + + + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the TE node + connectivity matrices."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the source LTP + of the connectivity matrix entry."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the destination LTP + of the connectivity matrix entry."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + + + + + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the TE node + connectivity matrices information source."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the source LTP + of the connectivity matrix entry information source."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the destination LTP + of the connectivity matrix entry information source."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + + + + + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the TTP + Local Link Connectivities."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the TTP + Local Link Connectivity entry."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range information for the TE link."; + uses label-range-info; + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction" { + when "../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + + + + + } + description + "Augment TE label range information for the TE link + information source."; + uses label-range-info; + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction" { + description + "Augment TE label range information for the TE link template."; + uses label-range-info; + } + + /* + * Augment TE label + */ + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the TE node + connectivity matrices"; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/" + + "tet:label-restriction/tet:label-end/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + + + + + } + description + "Augment TE label range end for the TE node + connectivity matrices"; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:label-restrictions/" + + "tet:label-restriction/tet:label-step/" + + "tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the TE node + connectivity matrices"; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:underlay/tet:primary-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay primary path of the + TE node connectivity matrices"; + case otn { + uses l1-types:otn-label-hop; + } + } + + + + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:underlay/tet:backup-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay backup path of the + TE node connectivity matrices"; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TE node connectivity + matrices"; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + + + + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TE node connectivity + matrices"; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the TE node connectivity matrices"; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + + + + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the source LTP + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the source LTP + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:from/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/" + + "tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + + + + + "Augment TE label range step for the source LTP + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the destination LTP + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the destination LTP + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + + + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:to/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/" + + "tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the destination LTP + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:primary-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:backup-path/tet:path-element/" + + "tet:type/tet:label/tet:label-hop/" + + "tet:te-label/tet:technology" { + + + + + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:optimizations/" + + "tet:algorithm/tet:metric/tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/tet:optimizations/" + + "tet:algorithm/tet:metric/tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + + + + + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:te-node-attributes/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the connectivity matrix entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the TE node connectivity + matrices information source."; + case otn { + + + + + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the TE node connectivity + matrices information source."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/" + + "tet:connectivity-matrices/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the TE node connectivity + matrices information source."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + + + + + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TE node connectivity matrices of the information + source entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TE node connectivity matrices of the information + source entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + + + + + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TE node connectivity matrices + information source."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TE node connectivity matrices + information source."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the computed path route objects + + + + + of the TE node connectivity matrices information source."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the source LTP + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-start-end; + } + } + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the source LTP + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + + + + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:from/tet:label-restrictions/" + + "tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the source LTP + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the destination LTP + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + + + + + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the destination LTP + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:to/tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the destination LTP + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the connectivity matrix entry information source."; + case otn { + + + + + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the connectivity matrix entry + information source."; + case otn { + uses l1-types:otn-label-hop; + } + } + + + + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the connectivity matrix entry + information source."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:information-source-entry/tet:connectivity-matrices/" + + "tet:connectivity-matrix/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the connectivity matrix entry information source."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + + + + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/" + + "tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the TTP + Local Link Connectivities."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/" + + "tet:te-label/tet:technology"{ + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the TTP + Local Link Connectivities."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/" + + "tet:technology"{ + when "../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + + + + + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the TTP + Local Link Connectivities."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TTP Local Link Connectivities."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TTP Local Link Connectivities."; + case otn { + + + + + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TTP Local Link + Connectivities."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TTP Local Link + Connectivities."; + case otn { + + + + + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the TTP Local Link Connectivities."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the TTP + Local Link Connectivity entry."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + + + + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the TTP + Local Link Connectivity entry."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the TTP + Local Link Connectivity entry."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + + + + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TTP Local Link Connectivity entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TTP Local Link Connectivity entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-exclude-objects/" + + "tet:route-object-exclude-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + + + + + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects excluded + by the path computation of the TTP Local Link + Connectivity entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:optimizations/tet:algorithm/tet:metric/" + + "tet:optimization-metric/" + + "tet:explicit-route-include-objects/" + + "tet:route-object-include-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the explicit route objects included + by the path computation of the TTP Local Link + Connectivity entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nw:node/tet:te/" + + "tet:tunnel-termination-point/" + + "tet:local-link-connectivities/" + + "tet:local-link-connectivity/" + + "tet:path-properties/tet:path-route-objects/" + + "tet:path-route-object/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + + + + + OTN topology type."; + } + description + "Augment TE label hop for the computed path route objects + of the TTP Local Link Connectivity entry."; + case otn { + uses l1-types:otn-label-hop; + } + } + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay primary path + of the TE link."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + when "../../../../../../../../" + + "nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label hop for the underlay backup path + of the TE link."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + + + + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the TE link."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the TE link."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range step for the TE link."; + case otn { + uses l1-types:otn-label-step; + } + + + + + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range start for the TE link + information source."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + when "../../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + description + "Augment TE label range end for the TE link + information source."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/nw:network/nt:link/tet:te/" + + "tet:information-source-entry/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + when "../../../../../../nw:network-types/tet:te-topology/" + + "otnt:otn-topology" { + description + "Augmentation parameters apply only for networks with + OTN topology type."; + } + + + + + description + "Augment TE label range step for the TE link + information source."; + case otn { + uses l1-types:otn-label-step; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:underlay/tet:primary-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + description + "Augment TE label hop for the underlay primary path + of the TE link template."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:underlay/tet:backup-path/tet:path-element/tet:type/" + + "tet:label/tet:label-hop/tet:te-label/tet:technology" { + description + "Augment TE label hop for the underlay backup path + of the TE link template."; + case otn { + uses l1-types:otn-label-hop; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-start/tet:te-label/tet:technology" { + description + "Augment TE label range start for the TE link template."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-end/tet:te-label/tet:technology" { + description + + + + + "Augment TE label range end for the TE link template."; + case otn { + uses l1-types:otn-label-start-end; + } + } + + augment "/nw:networks/tet:te/tet:templates/" + + "tet:link-template/tet:te-link-attributes/" + + "tet:label-restrictions/tet:label-restriction/" + + "tet:label-step/tet:technology" { + description + "Augment TE label range step for the TE link template."; + case otn { + uses l1-types:otn-label-step; + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-packet-fields@2019-03-04.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-packet-fields@2019-03-04.yang new file mode 100644 index 000000000..2fb797bd8 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-packet-fields@2019-03-04.yang @@ -0,0 +1,576 @@ +module ietf-packet-fields { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-packet-fields"; + prefix packet-fields; + + import ietf-inet-types { + prefix inet; + reference + "RFC 6991 - Common YANG Data Types."; + } + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991 - Common YANG Data Types."; + } + + import ietf-ethertypes { + prefix eth; + reference + "RFC 8519 - YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + organization + "IETF NETMOD (Network Modeling) Working Group."; + + contact + "WG Web: + WG List: netmod@ietf.org + + Editor: Mahesh Jethanandani + mjethanandani@gmail.com + Editor: Lisa Huang + huangyi_99@yahoo.com + Editor: Sonal Agarwal + sagarwal12@gmail.com + Editor: Dana Blair + dana@blairhome.com"; + + description + "This YANG module defines groupings that are used by + the ietf-access-control-list YANG module. Their usage + is not limited to ietf-access-control-list and can be + used anywhere as applicable. + + Copyright (c) 2019 IETF Trust and the persons identified as + the document authors. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD + License set forth in Section 4.c of the IETF Trust's Legal + Provisions Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8519; see + the RFC itself for full legal notices."; + + revision 2019-03-04 { + description + "Initial version."; + reference + "RFC 8519: YANG Data Model for Network Access Control + Lists (ACLs)."; + } + + /* + * Typedefs + */ + typedef operator { + type enumeration { + enum lte { + description + "Less than or equal to."; + } + enum gte { + description + "Greater than or equal to."; + } + enum eq { + description + "Equal to."; + } + enum neq { + description + "Not equal to."; + } + } + description + "The source and destination port range definitions + can be further qualified using an operator. An + operator is needed only if the lower-port is specified + and the upper-port is not specified. The operator + therefore further qualifies the lower-port only."; + } + + /* + * Groupings + */ + grouping port-range-or-operator { + choice port-range-or-operator { + case range { + leaf lower-port { + type inet:port-number; + must '. <= ../upper-port' { + error-message + "The lower-port must be less than or equal to + the upper-port."; + } + mandatory true; + description + "Lower boundary for a port."; + } + leaf upper-port { + type inet:port-number; + mandatory true; + description + "Upper boundary for a port."; + } + } + case operator { + leaf operator { + type operator; + default "eq"; + description + "Operator to be applied on the port below."; + } + leaf port { + type inet:port-number; + mandatory true; + description + "Port number along with the operator on which to + match."; + } + } + description + "Choice of specifying a port range or a single + port along with an operator."; + } + description + "Grouping for port definitions in the form of a + choice statement."; + } + + grouping acl-ip-header-fields { + description + "IP header fields common to IPv4 and IPv6"; + reference + "RFC 791: Internet Protocol."; + + leaf dscp { + type inet:dscp; + description + "Differentiated Services Code Point."; + reference + "RFC 2474: Definition of the Differentiated Services + Field (DS Field) in the IPv4 and IPv6 + Headers."; + } + + leaf ecn { + type uint8 { + range "0..3"; + } + description + "Explicit Congestion Notification."; + reference + "RFC 3168: The Addition of Explicit Congestion + Notification (ECN) to IP."; + } + + leaf length { + type uint16; + description + "In the IPv4 header field, this field is known as the Total + Length. Total Length is the length of the datagram, measured + in octets, including internet header and data. + + In the IPv6 header field, this field is known as the Payload + Length, which is the length of the IPv6 payload, i.e., the rest + of the packet following the IPv6 header, in octets."; + reference + "RFC 791: Internet Protocol + RFC 8200: Internet Protocol, Version 6 (IPv6) Specification."; + } + leaf ttl { + type uint8; + description + "This field indicates the maximum time the datagram is allowed + to remain in the internet system. If this field contains the + value zero, then the datagram must be dropped. + + In IPv6, this field is known as the Hop Limit."; + reference + "RFC 791: Internet Protocol + RFC 8200: Internet Protocol, Version 6 (IPv6) Specification."; + } + leaf protocol { + type uint8; + description + "Internet Protocol number. Refers to the protocol of the + payload. In IPv6, this field is known as 'next-header', + and if extension headers are present, the protocol is + present in the 'upper-layer' header."; + reference + "RFC 791: Internet Protocol + RFC 8200: Internet Protocol, Version 6 (IPv6) Specification."; + } + } + + grouping acl-ipv4-header-fields { + description + "Fields in the IPv4 header."; + leaf ihl { + type uint8 { + range "5..60"; + } + description + "In an IPv4 header field, the Internet Header Length (IHL) is + the length of the internet header in 32-bit words and + thus points to the beginning of the data. Note that the + minimum value for a correct header is 5."; + } + leaf flags { + type bits { + bit reserved { + position 0; + description + "Reserved. Must be zero."; + } + bit fragment { + position 1; + description + "Setting the value to 0 indicates may fragment, while + setting the value to 1 indicates do not fragment."; + } + bit more { + position 2; + description + "Setting the value to 0 indicates this is the last fragment, + and setting the value to 1 indicates more fragments are + coming."; + } + } + description + "Bit definitions for the Flags field in the IPv4 header."; + } + leaf offset { + type uint16 { + range "20..65535"; + } + description + "The fragment offset is measured in units of 8 octets (64 bits). + The first fragment has offset zero. The length is 13 bits"; + } + leaf identification { + type uint16; + description + "An identifying value assigned by the sender to aid in + assembling the fragments of a datagram."; + } + + choice destination-network { + case destination-ipv4-network { + leaf destination-ipv4-network { + type inet:ipv4-prefix; + description + "Destination IPv4 address prefix."; + } + } + description + "Choice of specifying a destination IPv4 address or + referring to a group of IPv4 destination addresses."; + } + + choice source-network { + case source-ipv4-network { + leaf source-ipv4-network { + type inet:ipv4-prefix; + description + "Source IPv4 address prefix."; + } + } + description + "Choice of specifying a source IPv4 address or + referring to a group of IPv4 source addresses."; + } + } + + grouping acl-ipv6-header-fields { + description + "Fields in the IPv6 header."; + + choice destination-network { + case destination-ipv6-network { + leaf destination-ipv6-network { + type inet:ipv6-prefix; + description + "Destination IPv6 address prefix."; + } + } + description + "Choice of specifying a destination IPv6 address + or referring to a group of IPv6 destination + addresses."; + } + + choice source-network { + case source-ipv6-network { + leaf source-ipv6-network { + type inet:ipv6-prefix; + description + "Source IPv6 address prefix."; + } + } + description + "Choice of specifying a source IPv6 address or + referring to a group of IPv6 source addresses."; + } + + leaf flow-label { + type inet:ipv6-flow-label; + description + "IPv6 Flow label."; + } + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation."; + } + + grouping acl-eth-header-fields { + description + "Fields in the Ethernet header."; + leaf destination-mac-address { + type yang:mac-address; + description + "Destination IEEE 802 Media Access Control (MAC) + address."; + } + leaf destination-mac-address-mask { + type yang:mac-address; + description + "Destination IEEE 802 MAC address mask."; + } + leaf source-mac-address { + type yang:mac-address; + description + "Source IEEE 802 MAC address."; + } + leaf source-mac-address-mask { + type yang:mac-address; + description + "Source IEEE 802 MAC address mask."; + } + leaf ethertype { + type eth:ethertype; + description + "The Ethernet Type (or Length) value represented + in the canonical order defined by IEEE 802. + The canonical representation uses lowercase + characters."; + reference + "IEEE 802-2014, Clause 9.2."; + } + reference + "IEEE 802: IEEE Standard for Local and Metropolitan + Area Networks: Overview and Architecture."; + } + + grouping acl-tcp-header-fields { + description + "Collection of TCP header fields that can be used to + set up a match filter."; + leaf sequence-number { + type uint32; + description + "Sequence number that appears in the packet."; + } + leaf acknowledgement-number { + type uint32; + description + "The acknowledgement number that appears in the + packet."; + } + leaf data-offset { + type uint8 { + range "5..15"; + } + description + "Specifies the size of the TCP header in 32-bit + words. The minimum size header is 5 words and + the maximum is 15 words; thus, this gives a + minimum size of 20 bytes and a maximum of 60 + bytes, allowing for up to 40 bytes of options + in the header."; + } + leaf reserved { + type uint8; + description + "Reserved for future use."; + } + leaf flags { + type bits { + bit cwr { + position 1; + description + "The Congestion Window Reduced (CWR) flag is set + by the sending host to indicate that it received + a TCP segment with the ECN-Echo (ECE) flag set + and had responded in the congestion control + mechanism."; + reference + "RFC 3168: The Addition of Explicit Congestion + Notification (ECN) to IP."; + } + bit ece { + position 2; + description + "ECN-Echo has a dual role, depending on the value + of the SYN flag. It indicates the following: if + the SYN flag is set (1), the TCP peer is ECN + capable, and if the SYN flag is clear (0), a packet + with the Congestion Experienced flag set (ECN=11) + in the IP header was received during normal + transmission (added to the header by RFC 3168). + This serves as an indication of network congestion + (or impending congestion) to the TCP sender."; + reference + "RFC 3168: The Addition of Explicit Congestion + Notification (ECN) to IP."; + } + bit urg { + position 3; + description + "Indicates that the Urgent Pointer field is significant."; + } + bit ack { + position 4; + description + "Indicates that the Acknowledgement field is significant. + All packets after the initial SYN packet sent by the + client should have this flag set."; + } + bit psh { + position 5; + description + "Push function. Asks to push the buffered data to the + receiving application."; + } + bit rst { + position 6; + description + "Reset the connection."; + } + bit syn { + position 7; + description + "Synchronize sequence numbers. Only the first packet + sent from each end should have this flag set. Some + other flags and fields change meaning based on this + flag, and some are only valid for when it is set, + and others when it is clear."; + } + bit fin { + position 8; + description + "Last package from the sender."; + } + } + description + "Also known as Control Bits. Contains nine 1-bit flags."; + reference + "RFC 793: Transmission Control Protocol."; + } + leaf window-size { + type uint16; + units "bytes"; + description + "The size of the receive window, which specifies + the number of window size units beyond the segment + identified by the sequence number in the Acknowledgement + field that the sender of this segment is currently + willing to receive."; + } + leaf urgent-pointer { + type uint16; + description + "This field is an offset from the sequence number + indicating the last urgent data byte."; + } + leaf options { + type binary { + length "1..40"; + } + description + "The length of this field is determined by the + Data Offset field. Options have up to three + fields: Option-Kind (1 byte), Option-Length + (1 byte), and Option-Data (variable). The Option-Kind + field indicates the type of option and is the + only field that is not optional. Depending on + what kind of option we are dealing with, + the next two fields may be set: the Option-Length + field indicates the total length of the option, + and the Option-Data field contains the value of + the option, if applicable."; + } + } + + grouping acl-udp-header-fields { + description + "Collection of UDP header fields that can be used + to set up a match filter."; + leaf length { + type uint16; + description + "A field that specifies the length in bytes of + the UDP header and UDP data. The minimum + length is 8 bytes because that is the length of + the header. The field size sets a theoretical + limit of 65,535 bytes (8-byte header plus 65,527 + bytes of data) for a UDP datagram. However, the + actual limit for the data length, which is + imposed by the underlying IPv4 protocol, is + 65,507 bytes (65,535 minus 8-byte UDP header + minus 20-byte IP header). + + In IPv6 jumbograms, it is possible to have + UDP packets of a size greater than 65,535 bytes. + RFC 2675 specifies that the Length field is set + to zero if the length of the UDP header plus + UDP data is greater than 65,535."; + } + } + + grouping acl-icmp-header-fields { + description + "Collection of ICMP header fields that can be + used to set up a match filter."; + leaf type { + type uint8; + description + "Also known as control messages."; + reference + "RFC 792: Internet Control Message Protocol + RFC 4443: Internet Control Message Protocol (ICMPv6) + for Internet Protocol Version 6 (IPv6) + Specification."; + } + leaf code { + type uint8; + description + "ICMP subtype. Also known as control messages."; + reference + "RFC 792: Internet Control Message Protocol + RFC 4443: Internet Control Message Protocol (ICMPv6) + for Internet Protocol Version 6 (IPv6) + Specification."; + } + leaf rest-of-header { + type binary; + description + "Unbounded in length, the contents vary based on the + ICMP type and code. Also referred to as 'Message Body' + in ICMPv6."; + reference + "RFC 792: Internet Control Message Protocol + RFC 4443: Internet Control Message Protocol (ICMPv6) + for Internet Protocol Version 6 (IPv6) + Specification."; + } + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-routing-types@2017-12-04.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-routing-types@2017-12-04.yang new file mode 100644 index 000000000..695d9eaeb --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-routing-types@2017-12-04.yang @@ -0,0 +1,774 @@ + module ietf-routing-types { + namespace "urn:ietf:params:xml:ns:yang:ietf-routing-types"; + prefix rt-types; + + import ietf-yang-types { + prefix yang; + } + import ietf-inet-types { + prefix inet; + } + + organization + "IETF RTGWG - Routing Area Working Group"; + contact + "WG Web: + WG List: + + Editors: Xufeng Liu + + Yingzhen Qu + + Acee Lindem + + Christian Hopps + + Lou Berger + "; + + description + "This module contains a collection of YANG data types + considered generally useful for routing protocols. + + Copyright (c) 2017 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8294; see + the RFC itself for full legal notices."; + + revision 2017-12-04 { + description "Initial revision."; + reference + "RFC 8294: Common YANG Data Types for the Routing Area. + Section 3."; + } + + /*** Identities related to MPLS/GMPLS ***/ + + identity mpls-label-special-purpose-value { + description + "Base identity for deriving identities describing + special-purpose Multiprotocol Label Switching (MPLS) label + values."; + reference + "RFC 7274: Allocating and Retiring Special-Purpose MPLS + Labels."; + } + + identity ipv4-explicit-null-label { + base mpls-label-special-purpose-value; + description + "This identity represents the IPv4 Explicit NULL Label."; + reference + "RFC 3032: MPLS Label Stack Encoding. Section 2.1."; + } + + identity router-alert-label { + base mpls-label-special-purpose-value; + description + "This identity represents the Router Alert Label."; + reference + "RFC 3032: MPLS Label Stack Encoding. Section 2.1."; + } + + identity ipv6-explicit-null-label { + base mpls-label-special-purpose-value; + description + "This identity represents the IPv6 Explicit NULL Label."; + reference + "RFC 3032: MPLS Label Stack Encoding. Section 2.1."; + } + + identity implicit-null-label { + base mpls-label-special-purpose-value; + description + "This identity represents the Implicit NULL Label."; + reference + "RFC 3032: MPLS Label Stack Encoding. Section 2.1."; + } + + identity entropy-label-indicator { + base mpls-label-special-purpose-value; + description + "This identity represents the Entropy Label Indicator."; + reference + "RFC 6790: The Use of Entropy Labels in MPLS Forwarding. + Sections 3 and 10.1."; + } + + identity gal-label { + base mpls-label-special-purpose-value; + description + "This identity represents the Generic Associated Channel + (G-ACh) Label (GAL)."; + reference + "RFC 5586: MPLS Generic Associated Channel. + Sections 4 and 10."; + } + + identity oam-alert-label { + base mpls-label-special-purpose-value; + description + "This identity represents the OAM Alert Label."; + reference + "RFC 3429: Assignment of the 'OAM Alert Label' for + Multiprotocol Label Switching Architecture (MPLS) + Operation and Maintenance (OAM) Functions. + Sections 3 and 6."; + } + + identity extension-label { + base mpls-label-special-purpose-value; + description + "This identity represents the Extension Label."; + reference + "RFC 7274: Allocating and Retiring Special-Purpose MPLS + Labels. Sections 3.1 and 5."; + } + + /*** Collection of types related to routing ***/ + + typedef router-id { + type yang:dotted-quad; + description + "A 32-bit number in the dotted-quad format assigned to each + router. This number uniquely identifies the router within + an Autonomous System."; + } + + /*** Collection of types related to VPNs ***/ + + typedef route-target { + type string { + pattern + '(0:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|' + + '42949672[0-8][0-9]|' + + '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|' + + '42949[0-5][0-9]{4}|' + + '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|' + + '42[0-8][0-9]{7}|4[01][0-9]{8}|' + + '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))|' + + '(1:((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|' + + '25[0-5])\.){3}([0-9]|[1-9][0-9]|' + + '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|' + + '655[0-2][0-9]|' + + '65[0-4][0-9]{2}|6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' + + '(2:(429496729[0-5]|42949672[0-8][0-9]|' + + '4294967[01][0-9]{2}|' + + '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|' + + '4294[0-8][0-9]{5}|' + + '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|' + + '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):' + + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' + + '(6(:[a-fA-F0-9]{2}){6})|' + + '(([3-57-9a-fA-F]|[1-9a-fA-F][0-9a-fA-F]{1,3}):' + + '[0-9a-fA-F]{1,12})'; + } + + description + "A Route Target is an 8-octet BGP extended community + initially identifying a set of sites in a BGP VPN + (RFC 4364). However, it has since taken on a more general + role in BGP route filtering. A Route Target consists of two + or three fields: a 2-octet Type field, an administrator + field, and, optionally, an assigned number field. + + According to the data formats for types 0, 1, 2, and 6 as + defined in RFC 4360, RFC 5668, and RFC 7432, the encoding + pattern is defined as: + + 0:2-octet-asn:4-octet-number + 1:4-octet-ipv4addr:2-octet-number + 2:4-octet-asn:2-octet-number + 6:6-octet-mac-address + + Additionally, a generic pattern is defined for future + Route Target types: + + 2-octet-other-hex-number:6-octet-hex-number + + Some valid examples are 0:100:100, 1:1.1.1.1:100, + 2:1234567890:203, and 6:26:00:08:92:78:00."; + reference + "RFC 4360: BGP Extended Communities Attribute. + RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs). + RFC 5668: 4-Octet AS Specific BGP Extended Community. + RFC 7432: BGP MPLS-Based Ethernet VPN."; + } + + typedef ipv6-route-target { + type string { + pattern + '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])))' + + ':' + + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)'; + pattern '((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?))' + + ':' + + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)'; + } + description + "An IPv6 Route Target is a 20-octet BGP IPv6 Address + Specific Extended Community serving the same function + as a standard 8-octet Route Target, except that it only + allows an IPv6 address as the global administrator. + The format is . + + Two valid examples are 2001:db8::1:6544 and + 2001:db8::5eb1:791:6b37:17958."; + reference + "RFC 5701: IPv6 Address Specific BGP Extended Community + Attribute."; + } + + typedef route-target-type { + type enumeration { + enum import { + value 0; + description + "The Route Target applies to route import."; + } + enum export { + value 1; + description + "The Route Target applies to route export."; + } + + enum both { + value 2; + description + "The Route Target applies to both route import and + route export."; + } + } + description + "Indicates the role a Route Target takes in route filtering."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)."; + } + + typedef route-distinguisher { + type string { + pattern + '(0:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|' + + '42949672[0-8][0-9]|' + + '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|' + + '42949[0-5][0-9]{4}|' + + '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|' + + '42[0-8][0-9]{7}|4[01][0-9]{8}|' + + '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))|' + + '(1:((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|' + + '25[0-5])\.){3}([0-9]|[1-9][0-9]|' + + '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|' + + '655[0-2][0-9]|' + + '65[0-4][0-9]{2}|6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' + + '(2:(429496729[0-5]|42949672[0-8][0-9]|' + + '4294967[01][0-9]{2}|' + + '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|' + + '4294[0-8][0-9]{5}|' + + '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|' + + '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):' + + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' + + '(6(:[a-fA-F0-9]{2}){6})|' + + '(([3-57-9a-fA-F]|[1-9a-fA-F][0-9a-fA-F]{1,3}):' + + '[0-9a-fA-F]{1,12})'; + } + + description + "A Route Distinguisher is an 8-octet value used to + distinguish routes from different BGP VPNs (RFC 4364). + A Route Distinguisher will have the same format as a + Route Target as per RFC 4360 and will consist of + two or three fields: a 2-octet Type field, an administrator + field, and, optionally, an assigned number field. + + According to the data formats for types 0, 1, 2, and 6 as + defined in RFC 4360, RFC 5668, and RFC 7432, the encoding + pattern is defined as: + + 0:2-octet-asn:4-octet-number + 1:4-octet-ipv4addr:2-octet-number + 2:4-octet-asn:2-octet-number + 6:6-octet-mac-address + + Additionally, a generic pattern is defined for future + route discriminator types: + + 2-octet-other-hex-number:6-octet-hex-number + + Some valid examples are 0:100:100, 1:1.1.1.1:100, + 2:1234567890:203, and 6:26:00:08:92:78:00."; + reference + "RFC 4360: BGP Extended Communities Attribute. + RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs). + RFC 5668: 4-Octet AS Specific BGP Extended Community. + RFC 7432: BGP MPLS-Based Ethernet VPN."; + } + + typedef route-origin { + type string { + pattern + '(0:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|' + + '42949672[0-8][0-9]|' + + '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|' + + '42949[0-5][0-9]{4}|' + + '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|' + + '42[0-8][0-9]{7}|4[01][0-9]{8}|' + + '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))|' + + '(1:((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|' + + '25[0-5])\.){3}([0-9]|[1-9][0-9]|' + + '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|' + + '655[0-2][0-9]|' + + '65[0-4][0-9]{2}|6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' + + '(2:(429496729[0-5]|42949672[0-8][0-9]|' + + '4294967[01][0-9]{2}|' + + '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|' + + '4294[0-8][0-9]{5}|' + + '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|' + + '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):' + + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|' + + '(6(:[a-fA-F0-9]{2}){6})|' + + '(([3-57-9a-fA-F]|[1-9a-fA-F][0-9a-fA-F]{1,3}):' + + '[0-9a-fA-F]{1,12})'; + } + description + "A Route Origin is an 8-octet BGP extended community + identifying the set of sites where the BGP route + originated (RFC 4364). A Route Origin will have the same + format as a Route Target as per RFC 4360 and will consist + of two or three fields: a 2-octet Type field, an + administrator field, and, optionally, an assigned number + field. + + According to the data formats for types 0, 1, 2, and 6 as + defined in RFC 4360, RFC 5668, and RFC 7432, the encoding + pattern is defined as: + + 0:2-octet-asn:4-octet-number + 1:4-octet-ipv4addr:2-octet-number + 2:4-octet-asn:2-octet-number + 6:6-octet-mac-address + + Additionally, a generic pattern is defined for future + Route Origin types: + + 2-octet-other-hex-number:6-octet-hex-number + + Some valid examples are 0:100:100, 1:1.1.1.1:100, + 2:1234567890:203, and 6:26:00:08:92:78:00."; + reference + "RFC 4360: BGP Extended Communities Attribute. + RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs). + RFC 5668: 4-Octet AS Specific BGP Extended Community. + RFC 7432: BGP MPLS-Based Ethernet VPN."; + } + + typedef ipv6-route-origin { + type string { + pattern + '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])))' + + ':' + + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)'; + pattern '((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?))' + + ':' + + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|' + + '6[0-4][0-9]{3}|' + + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)'; + } + description + "An IPv6 Route Origin is a 20-octet BGP IPv6 Address + Specific Extended Community serving the same function + as a standard 8-octet route, except that it only allows + an IPv6 address as the global administrator. The format + is . + + Two valid examples are 2001:db8::1:6544 and + 2001:db8::5eb1:791:6b37:17958."; + reference + "RFC 5701: IPv6 Address Specific BGP Extended Community + Attribute."; + } + + /*** Collection of types common to multicast ***/ + + typedef ipv4-multicast-group-address { + type inet:ipv4-address { + pattern '(2((2[4-9])|(3[0-9]))\.).*'; + } + description + "This type represents an IPv4 multicast group address, + which is in the range of 224.0.0.0 to 239.255.255.255."; + reference + "RFC 1112: Host Extensions for IP Multicasting."; + } + + typedef ipv6-multicast-group-address { + type inet:ipv6-address { + pattern '(([fF]{2}[0-9a-fA-F]{2}):).*'; + } + description + "This type represents an IPv6 multicast group address, + which is in the range of ff00::/8."; + reference + "RFC 4291: IP Version 6 Addressing Architecture. Section 2.7. + RFC 7346: IPv6 Multicast Address Scopes."; + } + + typedef ip-multicast-group-address { + type union { + type ipv4-multicast-group-address; + type ipv6-multicast-group-address; + } + description + "This type represents a version-neutral IP multicast group + address. The format of the textual representation implies + the IP version."; + } + + typedef ipv4-multicast-source-address { + type union { + type enumeration { + enum * { + description + "Any source address."; + } + } + type inet:ipv4-address; + } + description + "Multicast source IPv4 address type."; + } + + typedef ipv6-multicast-source-address { + type union { + type enumeration { + enum * { + description + "Any source address."; + } + } + type inet:ipv6-address; + } + description + "Multicast source IPv6 address type."; + } + + /*** Collection of types common to protocols ***/ + + typedef bandwidth-ieee-float32 { + type string { + pattern + '0[xX](0((\.0?)?[pP](\+)?0?|(\.0?))|' + + '1(\.([0-9a-fA-F]{0,5}[02468aAcCeE]?)?)?[pP](\+)?(12[0-7]|' + + '1[01][0-9]|0?[0-9]?[0-9])?)'; + } + description + "Bandwidth in IEEE 754 floating-point 32-bit binary format: + (-1)**(S) * 2**(Exponent-127) * (1 + Fraction), + where Exponent uses 8 bits and Fraction uses 23 bits. + The units are octets per second. + The encoding format is the external hexadecimal-significant + character sequences specified in IEEE 754 and ISO/IEC C99. + The format is restricted to be normalized, non-negative, and + non-fraction: 0x1.hhhhhhp{+}d, 0X1.HHHHHHP{+}D, or 0x0p0, + where 'h' and 'H' are hexadecimal digits and 'd' and 'D' are + integers in the range of [0..127]. + + When six hexadecimal digits are used for 'hhhhhh' or + 'HHHHHH', the least significant digit must be an even + number. 'x' and 'X' indicate hexadecimal; 'p' and 'P' + indicate a power of two. Some examples are 0x0p0, 0x1p10, + and 0x1.abcde2p+20."; + reference + "IEEE Std 754-2008: IEEE Standard for Floating-Point + Arithmetic. + ISO/IEC C99: Information technology - Programming + Languages - C."; + } + + typedef link-access-type { + type enumeration { + enum broadcast { + description + "Specify broadcast multi-access network."; + } + enum non-broadcast-multiaccess { + description + "Specify Non-Broadcast Multi-Access (NBMA) network."; + } + enum point-to-multipoint { + description + "Specify point-to-multipoint network."; + } + enum point-to-point { + description + "Specify point-to-point network."; + } + } + description + "Link access type."; + } + + typedef timer-multiplier { + type uint8; + description + "The number of timer value intervals that should be + interpreted as a failure."; + } + + typedef timer-value-seconds16 { + type union { + type uint16 { + range "1..65535"; + } + type enumeration { + enum infinity { + description + "The timer is set to infinity."; + } + enum not-set { + description + "The timer is not set."; + } + } + } + units "seconds"; + description + "Timer value type, in seconds (16-bit range)."; + } + + typedef timer-value-seconds32 { + type union { + type uint32 { + range "1..4294967295"; + } + type enumeration { + enum infinity { + description + "The timer is set to infinity."; + } + enum not-set { + description + "The timer is not set."; + } + } + } + units "seconds"; + description + "Timer value type, in seconds (32-bit range)."; + } + + typedef timer-value-milliseconds { + type union { + type uint32 { + range "1..4294967295"; + } + type enumeration { + enum infinity { + description + "The timer is set to infinity."; + } + enum not-set { + description + "The timer is not set."; + } + } + } + units "milliseconds"; + description + "Timer value type, in milliseconds."; + } + + typedef percentage { + type uint8 { + range "0..100"; + } + description + "Integer indicating a percentage value."; + } + + typedef timeticks64 { + type uint64; + description + "This type is based on the timeticks type defined in + RFC 6991, but with 64-bit width. It represents the time, + modulo 2^64, in hundredths of a second between two epochs."; + reference + "RFC 6991: Common YANG Data Types."; + } + + typedef uint24 { + type uint32 { + range "0..16777215"; + } + description + "24-bit unsigned integer."; + } + + /*** Collection of types related to MPLS/GMPLS ***/ + + typedef generalized-label { + type binary; + description + "Generalized Label. Nodes sending and receiving the + Generalized Label are aware of the link-specific + label context and type."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description. Section 3.2."; + } + + typedef mpls-label-special-purpose { + type identityref { + base mpls-label-special-purpose-value; + } + description + "This type represents the special-purpose MPLS label values."; + reference + "RFC 3032: MPLS Label Stack Encoding. + RFC 7274: Allocating and Retiring Special-Purpose MPLS + Labels."; + } + + typedef mpls-label-general-use { + type uint32 { + range "16..1048575"; + } + description + "The 20-bit label value in an MPLS label stack as specified + in RFC 3032. This label value does not include the + encodings of Traffic Class and TTL (Time to Live). + The label range specified by this type is for general use, + with special-purpose MPLS label values excluded."; + reference + "RFC 3032: MPLS Label Stack Encoding."; + } + + typedef mpls-label { + type union { + type mpls-label-special-purpose; + type mpls-label-general-use; + } + description + "The 20-bit label value in an MPLS label stack as specified + in RFC 3032. This label value does not include the + encodings of Traffic Class and TTL."; + reference + "RFC 3032: MPLS Label Stack Encoding."; + } + + /*** Groupings **/ + + grouping mpls-label-stack { + description + "This grouping specifies an MPLS label stack. The label + stack is encoded as a list of label stack entries. The + list key is an identifier that indicates the relative + ordering of each entry, with the lowest-value identifier + corresponding to the top of the label stack."; + container mpls-label-stack { + description + "Container for a list of MPLS label stack entries."; + list entry { + key "id"; + description + "List of MPLS label stack entries."; + leaf id { + type uint8; + description + "Identifies the entry in a sequence of MPLS label + stack entries. An entry with a smaller identifier + value precedes an entry with a larger identifier + value in the label stack. The value of this ID has + no semantic meaning other than relative ordering + and referencing the entry."; + } + leaf label { + type rt-types:mpls-label; + description + "Label value."; + } + + leaf ttl { + type uint8; + description + "Time to Live (TTL)."; + reference + "RFC 3032: MPLS Label Stack Encoding."; + } + leaf traffic-class { + type uint8 { + range "0..7"; + } + description + "Traffic Class (TC)."; + reference + "RFC 5462: Multiprotocol Label Switching (MPLS) Label + Stack Entry: 'EXP' Field Renamed to 'Traffic Class' + Field."; + } + } + } + } + + grouping vpn-route-targets { + description + "A grouping that specifies Route Target import-export rules + used in BGP-enabled VPNs."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs). + RFC 4664: Framework for Layer 2 Virtual Private Networks + (L2VPNs)."; + list vpn-target { + key "route-target"; + description + "List of Route Targets."; + leaf route-target { + type rt-types:route-target; + description + "Route Target value."; + } + leaf route-target-type { + type rt-types:route-target-type; + mandatory true; + description + "Import/export type of the Route Target."; + } + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-sap-ntw@2023-06-20.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-sap-ntw@2023-06-20.yang new file mode 100644 index 000000000..a78e55c4c --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-sap-ntw@2023-06-20.yang @@ -0,0 +1,350 @@ +module ietf-sap-ntw { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-sap-ntw"; + prefix sap; + + import ietf-network-topology { + prefix nt; + reference + "RFC 8345: A YANG Data Model for Network + Topologies, Section 6.2"; + } + import ietf-network { + prefix nw; + reference + "RFC 8345: A YANG Data Model for Network + Topologies, Section 6.1"; + } + import ietf-vpn-common { + prefix vpn-common; + reference + "RFC 9181: A Common YANG Data Model for Layer 2 and Layer 3 + VPNs"; + } + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types, Section 3"; + } + + organization + "IETF OPSA (Operations and Management Area) Working Group"; + contact + "WG Web: + WG List: + + Editor: Mohamed Boucadair + + + Author: Oscar Gonzalez de Dios + + + Author: Samier Barguil + + + Author: Qin Wu + + + Author: Victor Lopez + "; + description + "This YANG module defines a model for representing, managing, + and controlling the Service Attachment Points (SAPs) in the + network topology. + + Copyright (c) 2023 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Revised BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 9408; see the + RFC itself for full legal notices."; + + revision 2023-06-20 { + description + "Initial version."; + reference + "RFC 9408: A YANG Network Data Model for Service Attachment + Points (SAPs)"; + } + + identity virtual-network { + base vpn-common:service-type; + description + "Virtual network. Refers to a logical network instance + that is built over a physical network."; + reference + "RFC 8453: Framework for Abstraction and Control of TE + Networks (ACTN)"; + } + + identity enhanced-vpn { + base vpn-common:service-type; + description + "Enhanced VPN (VPN+). VPN+ is an approach that is + based on existing VPN and Traffic Engineering (TE) + technologies but adds characteristics that specific + services require over and above conventional VPNs."; + reference + "draft-ietf-teas-enhanced-vpn: + A Framework for Enhanced Virtual Private Network + (VPN+)"; + } + + identity network-slice { + base vpn-common:service-type; + description + "IETF Network Slice. An IETF Network Slice + is a logical network topology connecting a number of + endpoints using a set of shared or dedicated network + resources that are used to satisfy specific service + objectives."; + reference + "draft-ietf-teas-ietf-network-slices: + A Framework for IETF Network Slices"; + } + + identity sdwan { + base vpn-common:service-type; + description + "PE-based Software-Defined Wide-Area Network (SD-WAN)."; + reference + "draft-ietf-bess-bgp-sdwan-usage: + BGP Usage for SD-WAN Overlay Networks"; + } + + identity basic-connectivity { + base vpn-common:service-type; + description + "Basic IP connectivity. This is, for example, a plain + form of connectivity offered to enterprises over a + dedicated or shared MPLS infrastructure."; + } + + identity interface-role { + description + "Base identity for the network role of an interface."; + } + + identity uni { + base interface-role; + description + "User-to-Network Interface (UNI)."; + } + + identity nni { + base interface-role; + description + "Network-to-Network Interface (NNI)."; + } + + identity interface-type { + description + "Base identity for the interface type."; + } + + identity phy { + base interface-type; + description + "Physical port."; + } + + identity loopback { + base interface-type; + description + "Loopback interface."; + } + + identity lag { + base interface-type; + description + "Link Aggregation Group (LAG) interface."; + } + + identity irb { + base interface-type; + description + "Integrated Routing and Bridging (IRB) interface. An IRB + interface typically connects an IP Virtual Routing and + Forwarding (IP-VRF) entity to a bridge domain."; + } + + identity local-bridge { + base interface-type; + description + "A local bridge reference to accommodate (for example) + implementations that require internal bridging. + When such a type is used, a reference to a local + bridge domain is used to identify the interface."; + } + + identity logical { + base interface-type; + description + "Refers to a logical sub-interface that is typically + used to bind a service. This type is used only + if none of the other more specific types (i.e., + 'loopback', 'lag', 'irb', or 'local-bridge') can be used."; + } + + grouping sap-entry { + description + "Service Attachment Point (SAP) entry information."; + leaf sap-id { + type string; + description + "Indicates an identifier that uniquely identifies + a SAP."; + } + leaf description { + type string; + description + "A textual description of the SAP."; + } + leaf parent-termination-point { + type nt:tp-id; + description + "Indicates the parent termination point to + which the SAP is attached. A termination + point can be a physical port, an interface, etc."; + } + leaf attachment-interface { + type string; + description + "Indicates the interface to which the SAP is bound."; + } + leaf interface-type { + type identityref { + base interface-type; + } + description + "The type of the interface to which the SAP is bound."; + } + leaf encapsulation-type { + type identityref { + base vpn-common:encapsulation-type; + } + description + "Encapsulation type of the interface to which the + SAP is bound."; + } + leaf role { + type identityref { + base interface-role; + } + description + "Indicates the role of a SAP."; + } + leaf allows-child-saps { + type boolean; + description + "Indicates whether the attachment interface of this + SAP is capable of hosting per-service sub-interfaces."; + } + leaf-list peer-sap-id { + type string; + description + "Indicates an identifier of the peer's termination + identifier (e.g., a Customer Edge (CE)). This + information can be used for correlation purposes, + such as identifying the SAP that is attached to + an endpoint that is provided in a service request."; + } + } + + grouping sap-list { + description + "SAP information."; + list sap { + key "sap-id"; + description + "The SAPs are an abstraction of the points to which + network services such as L3VPNs, L2VPNs, or network + slices can be attached."; + uses sap-entry; + container sap-status { + config false; + description + "Indicates the operational status of the SAP, + independent of any service provisioned over it."; + + uses vpn-common:oper-status-timestamp; + } + container service-status { + description + "Indicates the service status."; + container admin-status { + description + "Administrative service status."; + leaf status { + type identityref { + base vpn-common:administrative-status; + } + description + "Administrative status of the service provisioned + at the SAP."; + } + leaf last-change { + type yang:date-and-time; + description + "Indicates the actual date and time of the service + status change."; + } + } + container oper-status { + config false; + description + "Operational status of the service provisioned + at the SAP."; + uses vpn-common:oper-status-timestamp; + } + } + } + } + + augment "/nw:networks/nw:network/nw:network-types" { + description + "Introduces a new network type for a SAP network."; + container sap-network { + presence "Indicates the SAP network type."; + description + "The presence of the container node indicates the + SAP network type."; + leaf-list service-type { + type identityref { + base vpn-common:service-type; + } + description + "Indicates the set of supported service types."; + } + } + } + + augment "/nw:networks/nw:network/nw:node" { + when '../nw:network-types/sap:sap-network' { + description + "Augmentation parameters apply only for SAP + networks."; + } + description + "SAP parameters for the node level."; + list service { + key "service-type"; + description + "A list of supported service types for the node."; + leaf service-type { + type identityref { + base vpn-common:service-type; + } + description + "Indicates a service type."; + } + uses sap-list; + } + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-te-packet-types@2020-06-10.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-te-packet-types@2020-06-10.yang new file mode 100644 index 000000000..8e7d4aafa --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-te-packet-types@2020-06-10.yang @@ -0,0 +1,475 @@ +module ietf-te-packet-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-te-packet-types"; + prefix te-packet-types; + + /* Import TE generic types */ + + import ietf-te-types { + prefix te-types; + reference + "RFC 8776: Common YANG Data Types for Traffic Engineering"; + } + + organization + "IETF Traffic Engineering Architecture and Signaling (TEAS) + Working Group"; + contact + "WG Web: + WG List: + + Editor: Tarek Saad + + + Editor: Rakesh Gandhi + + + Editor: Vishnu Pavan Beeram + + + Editor: Xufeng Liu + + + Editor: Igor Bryskin + "; + description + "This YANG module contains a collection of generally useful YANG + data type definitions specific to MPLS TE. The model fully + conforms to the Network Management Datastore Architecture + (NMDA). + + Copyright (c) 2020 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Simplified BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8776; see the + RFC itself for full legal notices."; + + revision 2020-06-10 { + description + "Latest revision of TE MPLS types."; + reference + "RFC 8776: Common YANG Data Types for Traffic Engineering"; + } + + /** + * Typedefs + */ + + typedef te-bandwidth-requested-type { + type enumeration { + enum specified { + description + "Bandwidth is explicitly specified."; + } + enum auto { + description + "Bandwidth is automatically computed."; + } + } + description + "Enumerated type for specifying whether bandwidth is + explicitly specified or automatically computed."; + } + + typedef te-class-type { + type uint8; + description + "Diffserv-TE Class-Type. Defines a set of Traffic Trunks + crossing a link that is governed by a specific set of + bandwidth constraints. Class-Type is used for the purposes + of link bandwidth allocation, constraint-based routing, and + admission control."; + reference + "RFC 4124: Protocol Extensions for Support of Diffserv-aware + MPLS Traffic Engineering"; + } + + typedef bc-type { + type uint8 { + range "0..7"; + } + description + "Diffserv-TE bandwidth constraints as defined in RFC 4124."; + reference + "RFC 4124: Protocol Extensions for Support of Diffserv-aware + MPLS Traffic Engineering"; + } + + typedef bandwidth-kbps { + type uint64; + units "Kbps"; + description + "Bandwidth values, expressed in kilobits per second."; + } + + typedef bandwidth-mbps { + type uint64; + units "Mbps"; + description + "Bandwidth values, expressed in megabits per second."; + } + + typedef bandwidth-gbps { + type uint64; + units "Gbps"; + description + "Bandwidth values, expressed in gigabits per second."; + } + + identity backup-protection-type { + description + "Base identity for the backup protection type."; + } + + identity backup-protection-link { + base backup-protection-type; + description + "Backup provides link protection only."; + } + + identity backup-protection-node-link { + base backup-protection-type; + description + "Backup offers node (preferred) or link protection."; + } + + identity bc-model-type { + description + "Base identity for the Diffserv-TE Bandwidth Constraints + Model type."; + reference + "RFC 4124: Protocol Extensions for Support of Diffserv-aware + MPLS Traffic Engineering"; + } + + identity bc-model-rdm { + base bc-model-type; + description + "Russian Dolls Bandwidth Constraints Model type."; + reference + "RFC 4127: Russian Dolls Bandwidth Constraints Model for + Diffserv-aware MPLS Traffic Engineering"; + } + + identity bc-model-mam { + base bc-model-type; + description + "Maximum Allocation Bandwidth Constraints Model type."; + reference + "RFC 4125: Maximum Allocation Bandwidth Constraints Model for + Diffserv-aware MPLS Traffic Engineering"; + } + + identity bc-model-mar { + base bc-model-type; + description + "Maximum Allocation with Reservation Bandwidth Constraints + Model type."; + reference + "RFC 4126: Max Allocation with Reservation Bandwidth + Constraints Model for Diffserv-aware MPLS Traffic Engineering + & Performance Comparisons"; + } + + grouping performance-metrics-attributes-packet { + description + "Contains PM attributes."; + uses te-types:performance-metrics-attributes { + augment "performance-metrics-one-way" { + leaf one-way-min-delay { + type uint32 { + range "0..16777215"; + } + description + "One-way minimum delay or latency in microseconds."; + } + leaf one-way-min-delay-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "One-way minimum delay or latency normality."; + } + leaf one-way-max-delay { + type uint32 { + range "0..16777215"; + } + description + "One-way maximum delay or latency in microseconds."; + } + leaf one-way-max-delay-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "One-way maximum delay or latency normality."; + } + leaf one-way-delay-variation { + type uint32 { + range "0..16777215"; + } + description + "One-way delay variation in microseconds."; + reference + "RFC 5481: Packet Delay Variation Applicability + Statement, Section 4.2"; + } + leaf one-way-delay-variation-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "One-way delay variation normality."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric + Extensions + RFC 7823: Performance-Based Path Selection for + Explicitly Routed Label Switched Paths (LSPs) Using + TE Metric Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions"; + } + leaf one-way-packet-loss { + type decimal64 { + fraction-digits 6; + range "0..50.331642"; + } + description + "One-way packet loss as a percentage of the total traffic + sent over a configurable interval. The finest precision + is 0.000003%, where the maximum is 50.331642%."; + reference + "RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions, Section 4.4"; + } + leaf one-way-packet-loss-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Packet loss normality."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric + Extensions + RFC 7823: Performance-Based Path Selection for + Explicitly Routed Label Switched Paths (LSPs) Using + TE Metric Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions"; + } + description + "PM one-way packet-specific augmentation for a generic PM + grouping."; + } + augment "performance-metrics-two-way" { + leaf two-way-min-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Two-way minimum delay or latency in microseconds."; + } + leaf two-way-min-delay-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Two-way minimum delay or latency normality."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric + Extensions + RFC 7823: Performance-Based Path Selection for + Explicitly Routed Label Switched Paths (LSPs) Using + TE Metric Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions"; + } + leaf two-way-max-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Two-way maximum delay or latency in microseconds."; + } + leaf two-way-max-delay-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Two-way maximum delay or latency normality."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric + Extensions + RFC 7823: Performance-Based Path Selection for + Explicitly Routed Label Switched Paths (LSPs) Using + TE Metric Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions"; + } + leaf two-way-delay-variation { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Two-way delay variation in microseconds."; + reference + "RFC 5481: Packet Delay Variation Applicability + Statement, Section 4.2"; + } + leaf two-way-delay-variation-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Two-way delay variation normality."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric + Extensions + RFC 7823: Performance-Based Path Selection for + Explicitly Routed Label Switched Paths (LSPs) Using + TE Metric Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions"; + } + leaf two-way-packet-loss { + type decimal64 { + fraction-digits 6; + range "0..50.331642"; + } + default "0"; + description + "Two-way packet loss as a percentage of the total traffic + sent over a configurable interval. The finest precision + is 0.000003%."; + } + leaf two-way-packet-loss-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Two-way packet loss normality."; + } + description + "PM two-way packet-specific augmentation for a generic PM + grouping."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions + RFC 7823: Performance-Based Path Selection for + Explicitly Routed Label Switched Paths (LSPs) Using + TE Metric Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions"; + } + } + } + + grouping one-way-performance-metrics-packet { + description + "One-way packet PM throttle grouping."; + leaf one-way-min-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "One-way minimum delay or latency in microseconds."; + } + leaf one-way-max-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "One-way maximum delay or latency in microseconds."; + } + leaf one-way-delay-variation { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "One-way delay variation in microseconds."; + } + leaf one-way-packet-loss { + type decimal64 { + fraction-digits 6; + range "0..50.331642"; + } + default "0"; + description + "One-way packet loss as a percentage of the total traffic + sent over a configurable interval. The finest precision is + 0.000003%."; + } + } + + grouping two-way-performance-metrics-packet { + description + "Two-way packet PM throttle grouping."; + leaf two-way-min-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Two-way minimum delay or latency in microseconds."; + } + leaf two-way-max-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Two-way maximum delay or latency in microseconds."; + } + leaf two-way-delay-variation { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Two-way delay variation in microseconds."; + } + leaf two-way-packet-loss { + type decimal64 { + fraction-digits 6; + range "0..50.331642"; + } + default "0"; + description + "Two-way packet loss as a percentage of the total traffic + sent over a configurable interval. The finest precision is + 0.000003%."; + } + } + + grouping performance-metrics-throttle-container-packet { + description + "Packet PM threshold grouping."; + uses te-types:performance-metrics-throttle-container { + augment "throttle/threshold-out" { + uses one-way-performance-metrics-packet; + uses two-way-performance-metrics-packet; + description + "PM threshold-out packet augmentation for a + generic grouping."; + } + augment "throttle/threshold-in" { + uses one-way-performance-metrics-packet; + uses two-way-performance-metrics-packet; + description + "PM threshold-in packet augmentation for a + generic grouping."; + } + augment "throttle/threshold-accelerated-advertisement" { + uses one-way-performance-metrics-packet; + uses two-way-performance-metrics-packet; + description + "PM accelerated advertisement packet augmentation for a + generic grouping."; + } + } + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-te-topology@2020-08-06.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-te-topology@2020-08-06.yang new file mode 100644 index 000000000..6d76a77b2 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-te-topology@2020-08-06.yang @@ -0,0 +1,1952 @@ +module ietf-te-topology { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-te-topology"; + prefix tet; + + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-te-types { + prefix te-types; + reference + "RFC 8776: Common YANG Data Types for Traffic Engineering"; + } + import ietf-network { + prefix nw; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + import ietf-network-topology { + prefix nt; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + + organization + "IETF Traffic Engineering Architecture and Signaling (TEAS) + Working Group"; + contact + "WG Web: + WG List: + + Editor: Xufeng Liu + + + Editor: Igor Bryskin + + + Editor: Vishnu Pavan Beeram + + + Editor: Tarek Saad + + + Editor: Himanshu Shah + + + Editor: Oscar Gonzalez de Dios + "; + description + "This YANG module defines a TE topology model for representing, + retrieving, and manipulating technology-agnostic TE topologies. + + Copyright (c) 2020 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Simplified BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8795; see the + RFC itself for full legal notices."; + + revision 2020-08-06 { + description + "Initial revision."; + reference + "RFC 8795: YANG Data Model for Traffic Engineering (TE) + Topologies"; + } + + /* + * Features + */ + + feature nsrlg { + description + "This feature indicates that the system supports NSRLGs + (Non-Shared Risk Link Groups)."; + } + + feature te-topology-hierarchy { + description + "This feature indicates that the system allows an underlay + and/or overlay TE topology hierarchy."; + } + + feature template { + description + "This feature indicates that the system supports + template configuration."; + } + + /* + * Typedefs + */ + + typedef geographic-coordinate-degree { + type decimal64 { + fraction-digits 8; + } + description + "Decimal degree (DD) used to express latitude and longitude + geographic coordinates."; + } + // geographic-coordinate-degree + + typedef te-info-source { + type enumeration { + enum unknown { + description + "The source is unknown."; + } + enum locally-configured { + description + "Configured entity."; + } + enum ospfv2 { + description + "OSPFv2."; + } + enum ospfv3 { + description + "OSPFv3."; + } + enum isis { + description + "IS-IS."; + } + enum bgp-ls { + description + "BGP-LS."; + reference + "RFC 7752: North-Bound Distribution of Link-State and + Traffic Engineering (TE) Information Using BGP"; + } + enum system-processed { + description + "System-processed entity."; + } + enum other { + description + "Other source."; + } + } + description + "Describes the type of source that has provided the + related information, and the source's credibility."; + } + // te-info-source + + /* + * Groupings + */ + + grouping connectivity-matrix-entry-path-attributes { + description + "Attributes of a connectivity matrix entry."; + leaf is-allowed { + type boolean; + description + "'true' - switching is allowed; + 'false' - switching is disallowed."; + } + container underlay { + if-feature "te-topology-hierarchy"; + description + "Attributes of the TE link underlay."; + reference + "RFC 4206: Label Switched Paths (LSP) Hierarchy with + Generalized Multi-Protocol Label Switching (GMPLS) + Traffic Engineering (TE)"; + uses te-link-underlay-attributes; + } + uses te-types:generic-path-constraints; + uses te-types:generic-path-optimization; + uses te-types:generic-path-properties; + } + // connectivity-matrix-entry-path-attributes + + grouping geolocation-container { + description + "Contains a GPS location."; + container geolocation { + config false; + description + "Contains a GPS location."; + leaf altitude { + type int64; + units "millimeters"; + description + "Distance above sea level."; + } + leaf latitude { + type geographic-coordinate-degree { + range "-90..90"; + } + description + "Relative position north or south on the Earth's surface."; + } + leaf longitude { + type geographic-coordinate-degree { + range "-180..180"; + } + description + "Angular distance east or west on the Earth's surface."; + } + } + // geolocation + } + // geolocation-container + + grouping information-source-state-attributes { + description + "The attributes identifying the source that has provided the + related information, and the source's credibility."; + leaf credibility-preference { + type uint16; + description + "The preference value for calculating the Traffic + Engineering database credibility value used for + tie-break selection between different information-source + values. A higher value is preferable."; + } + leaf logical-network-element { + type string; + description + "When applicable, this is the name of a logical network + element from which the information is learned."; + } + leaf network-instance { + type string; + description + "When applicable, this is the name of a network instance + from which the information is learned."; + } + } + // information-source-state-attributes + + grouping information-source-per-link-attributes { + description + "Per-node container of the attributes identifying the source + that has provided the related information, and the source's + credibility."; + leaf information-source { + type te-info-source; + config false; + description + "Indicates the type of information source."; + } + leaf information-source-instance { + type string; + config false; + description + "The name indicating the instance of the information + source."; + } + container information-source-state { + config false; + description + "Contains state attributes related to the information + source."; + uses information-source-state-attributes; + container topology { + description + "When the information is processed by the system, + the attributes in this container indicate which topology + is used to generate the result information."; + uses nt:link-ref; + } + } + } + // information-source-per-link-attributes + + grouping information-source-per-node-attributes { + description + "Per-node container of the attributes identifying the source + that has provided the related information, and the source's + credibility."; + leaf information-source { + type te-info-source; + config false; + description + "Indicates the type of information source."; + } + leaf information-source-instance { + type string; + config false; + description + "The name indicating the instance of the information + source."; + } + container information-source-state { + config false; + description + "Contains state attributes related to the information + source."; + uses information-source-state-attributes; + container topology { + description + "When the information is processed by the system, + the attributes in this container indicate which topology + is used to generate the result information."; + uses nw:node-ref; + } + } + } + // information-source-per-node-attributes + + grouping interface-switching-capability-list { + description + "List of Interface Switching Capability Descriptors (ISCDs)."; + list interface-switching-capability { + key "switching-capability encoding"; + description + "List of ISCDs for this link."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description + RFC 4203: OSPF Extensions in Support of Generalized + Multi-Protocol Label Switching (GMPLS)"; + leaf switching-capability { + type identityref { + base te-types:switching-capabilities; + } + description + "Switching capability for this interface."; + } + leaf encoding { + type identityref { + base te-types:lsp-encoding-types; + } + description + "Encoding supported by this interface."; + } + uses te-link-iscd-attributes; + } + // interface-switching-capability + } + // interface-switching-capability-list + + grouping statistics-per-link { + description + "Statistics attributes per TE link."; + leaf discontinuity-time { + type yang:date-and-time; + description + "The time of the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + /* Administrative attributes */ + leaf disables { + type yang:counter32; + description + "Number of times that a link was disabled."; + } + leaf enables { + type yang:counter32; + description + "Number of times that a link was enabled."; + } + leaf maintenance-clears { + type yang:counter32; + description + "Number of times that a link was taken out of maintenance."; + } + leaf maintenance-sets { + type yang:counter32; + description + "Number of times that a link was put in maintenance."; + } + leaf modifies { + type yang:counter32; + description + "Number of times that a link was modified."; + } + /* Operational attributes */ + leaf downs { + type yang:counter32; + description + "Number of times that a link was set to an operational state + of 'down'."; + } + leaf ups { + type yang:counter32; + description + "Number of times that a link was set to an operational state + of 'up'."; + } + /* Recovery attributes */ + leaf fault-clears { + type yang:counter32; + description + "Number of times that a link experienced a fault-clear + event."; + } + leaf fault-detects { + type yang:counter32; + description + "Number of times that a link experienced fault detection."; + } + leaf protection-switches { + type yang:counter32; + description + "Number of times that a link experienced protection + switchover."; + } + leaf protection-reverts { + type yang:counter32; + description + "Number of times that a link experienced protection + reversion."; + } + leaf restoration-failures { + type yang:counter32; + description + "Number of times that a link experienced restoration + failure."; + } + leaf restoration-starts { + type yang:counter32; + description + "Number of times that a link experienced restoration + start."; + } + leaf restoration-successes { + type yang:counter32; + description + "Number of times that a link experienced restoration + success."; + } + leaf restoration-reversion-failures { + type yang:counter32; + description + "Number of times that a link experienced restoration + reversion failure."; + } + leaf restoration-reversion-starts { + type yang:counter32; + description + "Number of times that a link experienced restoration + reversion start."; + } + leaf restoration-reversion-successes { + type yang:counter32; + description + "Number of times that a link experienced restoration + reversion success."; + } + } + // statistics-per-link + + grouping statistics-per-node { + description + "Statistics attributes per TE node."; + leaf discontinuity-time { + type yang:date-and-time; + description + "The time of the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + container node { + description + "Contains statistics attributes at the TE node level."; + leaf disables { + type yang:counter32; + description + "Number of times that a node was disabled."; + } + leaf enables { + type yang:counter32; + description + "Number of times that a node was enabled."; + } + leaf maintenance-sets { + type yang:counter32; + description + "Number of times that a node was put in maintenance."; + } + leaf maintenance-clears { + type yang:counter32; + description + "Number of times that a node was taken out of + maintenance."; + } + leaf modifies { + type yang:counter32; + description + "Number of times that a node was modified."; + } + } + // node + container connectivity-matrix-entry { + description + "Contains statistics attributes at the level of a + connectivity matrix entry."; + leaf creates { + type yang:counter32; + description + "Number of times that a connectivity matrix entry was + created."; + reference + "RFC 6241: Network Configuration Protocol (NETCONF), + Section 7.2, 'create' operation"; + } + leaf deletes { + type yang:counter32; + description + "Number of times that a connectivity matrix entry was + deleted."; + reference + "RFC 6241: Network Configuration Protocol (NETCONF), + Section 7.2, 'delete' operation"; + } + leaf disables { + type yang:counter32; + description + "Number of times that a connectivity matrix entry was + disabled."; + } + leaf enables { + type yang:counter32; + description + "Number of times that a connectivity matrix entry was + enabled."; + } + leaf modifies { + type yang:counter32; + description + "Number of times that a connectivity matrix entry was + modified."; + } + } + // connectivity-matrix-entry + } + // statistics-per-node + + grouping statistics-per-ttp { + description + "Statistics attributes per TE TTP (Tunnel Termination Point)."; + leaf discontinuity-time { + type yang:date-and-time; + description + "The time of the most recent occasion at which any one or + more of this interface's counters suffered a + discontinuity. If no such discontinuities have occurred + since the last re-initialization of the local management + subsystem, then this node contains the time the local + management subsystem re-initialized itself."; + } + container tunnel-termination-point { + description + "Contains statistics attributes at the TE TTP level."; + /* Administrative attributes */ + leaf disables { + type yang:counter32; + description + "Number of times that a TTP was disabled."; + } + leaf enables { + type yang:counter32; + description + "Number of times that a TTP was enabled."; + } + leaf maintenance-clears { + type yang:counter32; + description + "Number of times that a TTP was taken out of maintenance."; + } + leaf maintenance-sets { + type yang:counter32; + description + "Number of times that a TTP was put in maintenance."; + } + leaf modifies { + type yang:counter32; + description + "Number of times that a TTP was modified."; + } + /* Operational attributes */ + leaf downs { + type yang:counter32; + description + "Number of times that a TTP was set to an operational state + of 'down'."; + } + leaf ups { + type yang:counter32; + description + "Number of times that a TTP was set to an operational state + of 'up'."; + } + leaf in-service-clears { + type yang:counter32; + description + "Number of times that a TTP was taken out of service + (TE tunnel was released)."; + } + leaf in-service-sets { + type yang:counter32; + description + "Number of times that a TTP was put in service by a TE + tunnel (TE tunnel was set up)."; + } + } + // tunnel-termination-point + container local-link-connectivity { + description + "Contains statistics attributes at the TE LLCL (Local Link + Connectivity List) level."; + leaf creates { + type yang:counter32; + description + "Number of times that an LLCL entry was created."; + reference + "RFC 6241: Network Configuration Protocol (NETCONF), + Section 7.2, 'create' operation"; + } + leaf deletes { + type yang:counter32; + description + "Number of times that an LLCL entry was deleted."; + reference + "RFC 6241: Network Configuration Protocol (NETCONF), + Section 7.2, 'delete' operation"; + } + leaf disables { + type yang:counter32; + description + "Number of times that an LLCL entry was disabled."; + } + leaf enables { + type yang:counter32; + description + "Number of times that an LLCL entry was enabled."; + } + leaf modifies { + type yang:counter32; + description + "Number of times that an LLCL entry was modified."; + } + } + // local-link-connectivity + } + // statistics-per-ttp + + grouping te-link-augment { + description + "Augmentation for a TE link."; + uses te-link-config; + uses te-link-state-derived; + container statistics { + config false; + description + "Statistics data."; + uses statistics-per-link; + } + } + // te-link-augment + + grouping te-link-config { + description + "TE link configuration grouping."; + choice bundle-stack-level { + description + "The TE link can be partitioned into bundled links or + component links."; + case bundle { + container bundled-links { + description + "A set of bundled links."; + reference + "RFC 4201: Link Bundling in MPLS Traffic + Engineering (TE)"; + list bundled-link { + key "sequence"; + description + "Specifies a bundled interface that is + further partitioned."; + leaf sequence { + type uint32; + description + "Identifies the sequence in the bundle."; + } + } + } + } + case component { + container component-links { + description + "A set of component links."; + list component-link { + key "sequence"; + description + "Specifies a component interface that is + sufficient to unambiguously identify the + appropriate resources."; + leaf sequence { + type uint32; + description + "Identifies the sequence in the bundle."; + } + leaf src-interface-ref { + type string; + description + "Reference to a component link interface on the + source node."; + } + leaf des-interface-ref { + type string; + description + "Reference to a component link interface on the + destination node."; + } + } + } + } + } + // bundle-stack-level + leaf-list te-link-template { + if-feature "template"; + type leafref { + path "../../../../te/templates/link-template/name"; + } + description + "The reference to a TE link template."; + } + uses te-link-config-attributes; + } + // te-link-config + + grouping te-link-config-attributes { + description + "Link configuration attributes in a TE topology."; + container te-link-attributes { + description + "Link attributes in a TE topology."; + leaf access-type { + type te-types:te-link-access-type; + description + "Link access type, which can be point-to-point or + multi-access."; + } + container external-domain { + description + "For an inter-domain link, specifies the attributes of + the remote end of the link, to facilitate the signaling at + the local end."; + uses nw:network-ref; + leaf remote-te-node-id { + type te-types:te-node-id; + description + "Remote TE node identifier, used together with + 'remote-te-link-tp-id' to identify the remote Link + Termination Point (LTP) in a different domain."; + } + leaf remote-te-link-tp-id { + type te-types:te-tp-id; + description + "Remote TE LTP identifier, used together with + 'remote-te-node-id' to identify the remote LTP in a + different domain."; + } + } + leaf is-abstract { + type empty; + description + "Present if the link is abstract."; + } + leaf name { + type string; + description + "Link name."; + } + container underlay { + if-feature "te-topology-hierarchy"; + description + "Attributes of the TE link underlay."; + reference + "RFC 4206: Label Switched Paths (LSP) Hierarchy with + Generalized Multi-Protocol Label Switching (GMPLS) + Traffic Engineering (TE)"; + uses te-link-underlay-attributes; + } + leaf admin-status { + type te-types:te-admin-status; + description + "The administrative state of the link."; + } + uses te-link-info-attributes; + } + // te-link-attributes + } + // te-link-config-attributes + + grouping te-link-info-attributes { + description + "Advertised TE information attributes."; + leaf link-index { + type uint64; + description + "The link identifier. If OSPF is used, this object + represents an ospfLsdbID. If IS-IS is used, this object + represents an isisLSPID. If a locally configured link is + used, this object represents a unique value, which is + locally defined in a router."; + } + leaf administrative-group { + type te-types:admin-groups; + description + "Administrative group or color of the link. + This attribute covers both administrative groups (defined + in RFCs 3630 and 5305) and Extended Administrative Groups + (defined in RFC 7308)."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 5305: IS-IS Extensions for Traffic Engineering + RFC 7308: Extended Administrative Groups in MPLS Traffic + Engineering (MPLS-TE)"; + } + uses interface-switching-capability-list; + uses te-types:label-set-info; + leaf link-protection-type { + type identityref { + base te-types:link-protection-type; + } + description + "Link Protection Type desired for this link."; + reference + "RFC 4202: Routing Extensions in Support of + Generalized Multi-Protocol Label Switching (GMPLS)"; + } + container max-link-bandwidth { + uses te-types:te-bandwidth; + description + "Maximum bandwidth that can be seen on this link in this + direction. Units are in bytes per second."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 5305: IS-IS Extensions for Traffic Engineering"; + } + container max-resv-link-bandwidth { + uses te-types:te-bandwidth; + description + "Maximum amount of bandwidth that can be reserved in this + direction in this link. Units are in bytes per second."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 5305: IS-IS Extensions for Traffic Engineering"; + } + list unreserved-bandwidth { + key "priority"; + max-elements 8; + description + "Unreserved bandwidth for priority levels 0-7. Units are in + bytes per second."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 5305: IS-IS Extensions for Traffic Engineering"; + leaf priority { + type uint8 { + range "0..7"; + } + description + "Priority."; + } + uses te-types:te-bandwidth; + } + leaf te-default-metric { + type uint32; + description + "Traffic Engineering metric."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 5305: IS-IS Extensions for Traffic Engineering"; + } + leaf te-delay-metric { + type uint32; + description + "Traffic Engineering delay metric."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions"; + } + leaf te-igp-metric { + type uint32; + description + "IGP metric used for Traffic Engineering."; + reference + "RFC 3785: Use of Interior Gateway Protocol (IGP) Metric as a + second MPLS Traffic Engineering (TE) Metric"; + } + container te-srlgs { + description + "Contains a list of SRLGs."; + leaf-list value { + type te-types:srlg; + description + "SRLG value."; + reference + "RFC 4202: Routing Extensions in Support of + Generalized Multi-Protocol Label Switching (GMPLS)"; + } + } + container te-nsrlgs { + if-feature "nsrlg"; + description + "Contains a list of NSRLGs (Non-Shared Risk Link Groups). + When an abstract TE link is configured, this list specifies + the request that underlay TE paths need to be mutually + disjoint with other TE links in the same groups."; + leaf-list id { + type uint32; + description + "NSRLG ID, uniquely configured within a topology."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) + Recovery"; + } + } + } + // te-link-info-attributes + + grouping te-link-iscd-attributes { + description + "TE link ISCD attributes."; + reference + "RFC 4203: OSPF Extensions in Support of Generalized + Multi-Protocol Label Switching (GMPLS), Section 1.4"; + list max-lsp-bandwidth { + key "priority"; + max-elements 8; + description + "Maximum Label Switched Path (LSP) bandwidth at + priorities 0-7."; + leaf priority { + type uint8 { + range "0..7"; + } + description + "Priority."; + } + uses te-types:te-bandwidth; + } + } + // te-link-iscd-attributes + + grouping te-link-state-derived { + description + "Link state attributes in a TE topology."; + leaf oper-status { + type te-types:te-oper-status; + config false; + description + "The current operational state of the link."; + } + leaf is-transitional { + type empty; + config false; + description + "Present if the link is transitional; used as an + alternative approach in lieu of 'inter-layer-lock-id' + for path computation in a TE topology covering multiple + layers or multiple regions."; + reference + "RFC 5212: Requirements for GMPLS-Based Multi-Region and + Multi-Layer Networks (MRN/MLN) + RFC 6001: Generalized MPLS (GMPLS) Protocol Extensions + for Multi-Layer and Multi-Region Networks (MLN/MRN)"; + } + uses information-source-per-link-attributes; + list information-source-entry { + key "information-source information-source-instance"; + config false; + description + "A list of information sources learned, including the source + that is used."; + uses information-source-per-link-attributes; + uses te-link-info-attributes; + } + container recovery { + config false; + description + "Status of the recovery process."; + leaf restoration-status { + type te-types:te-recovery-status; + description + "Restoration status."; + } + leaf protection-status { + type te-types:te-recovery-status; + description + "Protection status."; + } + } + container underlay { + if-feature "te-topology-hierarchy"; + config false; + description + "State attributes for the TE link underlay."; + leaf dynamic { + type boolean; + description + "'true' if the underlay is dynamically created."; + } + leaf committed { + type boolean; + description + "'true' if the underlay is committed."; + } + } + } + // te-link-state-derived + + grouping te-link-underlay-attributes { + description + "Attributes for the TE link underlay."; + reference + "RFC 4206: Label Switched Paths (LSP) Hierarchy with + Generalized Multi-Protocol Label Switching (GMPLS) + Traffic Engineering (TE)"; + leaf enabled { + type boolean; + description + "'true' if the underlay is enabled. + 'false' if the underlay is disabled."; + } + container primary-path { + description + "The service path on the underlay topology that + supports this link."; + uses nw:network-ref; + list path-element { + key "path-element-id"; + description + "A list of path elements describing the service path."; + leaf path-element-id { + type uint32; + description + "To identify the element in a path."; + } + uses te-path-element; + } + } + // primary-path + list backup-path { + key "index"; + description + "A list of backup service paths on the underlay topology that + protect the underlay primary path. If the primary path is + not protected, the list contains zero elements. If the + primary path is protected, the list contains one or more + elements."; + leaf index { + type uint32; + description + "A sequence number to identify a backup path."; + } + uses nw:network-ref; + list path-element { + key "path-element-id"; + description + "A list of path elements describing the backup service + path."; + leaf path-element-id { + type uint32; + description + "To identify the element in a path."; + } + uses te-path-element; + } + } + // backup-path + leaf protection-type { + type identityref { + base te-types:lsp-protection-type; + } + description + "Underlay protection type desired for this link."; + } + container tunnel-termination-points { + description + "Underlay TTPs desired for this link."; + leaf source { + type binary; + description + "Source TTP identifier."; + } + leaf destination { + type binary; + description + "Destination TTP identifier."; + } + } + container tunnels { + description + "Underlay TE tunnels supporting this TE link."; + leaf sharing { + type boolean; + default "true"; + description + "'true' if the underlay tunnel can be shared with other + TE links; + 'false' if the underlay tunnel is dedicated to this + TE link. + This leaf is the default option for all TE tunnels + and may be overridden by the per-TE-tunnel value."; + } + list tunnel { + key "tunnel-name"; + description + "Zero, one, or more underlay TE tunnels that support this + TE link."; + leaf tunnel-name { + type string; + description + "A tunnel name uniquely identifies an underlay TE tunnel, + used together with the 'source-node' value for this + link."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + leaf sharing { + type boolean; + description + "'true' if the underlay tunnel can be shared with other + TE links; + 'false' if the underlay tunnel is dedicated to this + TE link."; + } + } + // tunnel + } + // tunnels + } + // te-link-underlay-attributes + + grouping te-node-augment { + description + "Augmentation for a TE node."; + uses te-node-config; + uses te-node-state-derived; + container statistics { + config false; + description + "Statistics data."; + uses statistics-per-node; + } + list tunnel-termination-point { + key "tunnel-tp-id"; + description + "A termination point can terminate a tunnel."; + leaf tunnel-tp-id { + type binary; + description + "TTP identifier."; + } + uses te-node-tunnel-termination-point-config; + leaf oper-status { + type te-types:te-oper-status; + config false; + description + "The current operational state of the TTP."; + } + uses geolocation-container; + container statistics { + config false; + description + "Statistics data."; + uses statistics-per-ttp; + } + // Relationship to other TTPs + list supporting-tunnel-termination-point { + key "node-ref tunnel-tp-ref"; + description + "Identifies the TTPs on which this TTP depends."; + leaf node-ref { + type inet:uri; + description + "This leaf identifies the node in which the supporting + TTP is present. + This node is either the supporting node or a node in + an underlay topology."; + } + leaf tunnel-tp-ref { + type binary; + description + "Reference to a TTP that is in either the supporting node + or a node in an underlay topology."; + } + } + // supporting-tunnel-termination-point + } + // tunnel-termination-point + } + // te-node-augment + + grouping te-node-config { + description + "TE node configuration grouping."; + leaf-list te-node-template { + if-feature "template"; + type leafref { + path "../../../../te/templates/node-template/name"; + } + description + "The reference to a TE node template."; + } + uses te-node-config-attributes; + } + // te-node-config + + grouping te-node-config-attributes { + description + "Configuration node attributes in a TE topology."; + container te-node-attributes { + description + "Contains node attributes in a TE topology."; + leaf admin-status { + type te-types:te-admin-status; + description + "The administrative state of the link."; + } + uses te-node-connectivity-matrices; + uses te-node-info-attributes; + } + } + // te-node-config-attributes + + grouping te-node-config-attributes-template { + description + "Configuration node attributes for a template in a TE + topology."; + container te-node-attributes { + description + "Contains node attributes in a TE topology."; + leaf admin-status { + type te-types:te-admin-status; + description + "The administrative state of the link."; + } + uses te-node-info-attributes; + } + } + // te-node-config-attributes-template + + grouping te-node-connectivity-matrices { + description + "Connectivity matrix on a TE node."; + container connectivity-matrices { + description + "Contains a connectivity matrix on a TE node."; + leaf number-of-entries { + type uint16; + description + "The number of connectivity matrix entries. + If this number is specified in the configuration request, + the number is the requested number of entries, which may + not all be listed in the list; + if this number is reported in the state data, + the number is the current number of operational entries."; + } + uses te-types:label-set-info; + uses connectivity-matrix-entry-path-attributes; + list connectivity-matrix { + key "id"; + description + "Represents a node's switching limitations, i.e., + limitations in the interconnecting network TE links + across the node."; + reference + "RFC 7579: General Network Element Constraint Encoding + for GMPLS-Controlled Networks"; + leaf id { + type uint32; + description + "Identifies the connectivity matrix entry."; + } + } + // connectivity-matrix + } + // connectivity-matrices + } + // te-node-connectivity-matrices + + grouping te-node-connectivity-matrix-attributes { + description + "Termination point references of a connectivity matrix entry."; + container from { + description + "Reference to a source LTP."; + leaf tp-ref { + type leafref { + path "../../../../../../nt:termination-point/nt:tp-id"; + } + description + "Relative reference to a termination point."; + } + uses te-types:label-set-info; + } + container to { + description + "Reference to a destination LTP."; + leaf tp-ref { + type leafref { + path "../../../../../../nt:termination-point/nt:tp-id"; + } + description + "Relative reference to a termination point."; + } + uses te-types:label-set-info; + } + uses connectivity-matrix-entry-path-attributes; + } + // te-node-connectivity-matrix-attributes + + grouping te-node-info-attributes { + description + "Advertised TE information attributes."; + leaf domain-id { + type uint32; + description + "Identifies the domain to which this node belongs. + This attribute is used to support inter-domain links."; + reference + "RFC 5152: A Per-Domain Path Computation Method for + Establishing Inter-Domain Traffic Engineering (TE) + Label Switched Paths (LSPs) + RFC 5316: ISIS Extensions in Support of Inter-Autonomous + System (AS) MPLS and GMPLS Traffic Engineering + RFC 5392: OSPF Extensions in Support of Inter-Autonomous + System (AS) MPLS and GMPLS Traffic Engineering"; + } + leaf is-abstract { + type empty; + description + "Present if the node is abstract; not present if the node + is actual."; + } + leaf name { + type string; + description + "Node name."; + } + leaf-list signaling-address { + type inet:ip-address; + description + "The node's signaling address."; + } + container underlay-topology { + if-feature "te-topology-hierarchy"; + description + "When an abstract node encapsulates a topology, the + attributes in this container point to said topology."; + uses nw:network-ref; + } + } + // te-node-info-attributes + + grouping te-node-state-derived { + description + "Node state attributes in a TE topology."; + leaf oper-status { + type te-types:te-oper-status; + config false; + description + "The current operational state of the node."; + } + uses geolocation-container; + leaf is-multi-access-dr { + type empty; + config false; + description + "The presence of this attribute indicates that this TE node + is a pseudonode elected as a designated router."; + reference + "RFC 1195: Use of OSI IS-IS for Routing in TCP/IP and Dual + Environments + RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2"; + } + uses information-source-per-node-attributes; + list information-source-entry { + key "information-source information-source-instance"; + config false; + description + "A list of information sources learned, including the source + that is used."; + uses information-source-per-node-attributes; + uses te-node-connectivity-matrices; + uses te-node-info-attributes; + } + } + // te-node-state-derived + + grouping te-node-tunnel-termination-point-config { + description + "Termination capability of a TTP on a TE node."; + uses te-node-tunnel-termination-point-config-attributes; + container local-link-connectivities { + description + "Contains an LLCL for a TTP on a TE node."; + leaf number-of-entries { + type uint16; + description + "The number of LLCL entries. + If this number is specified in the configuration request, + the number is the requested number of entries, which may + not all be listed in the list; + if this number is reported in the state data, + the number is the current number of operational entries."; + } + uses te-types:label-set-info; + uses connectivity-matrix-entry-path-attributes; + } + } + // te-node-tunnel-termination-point-config + + grouping te-node-tunnel-termination-point-config-attributes { + description + "Configuration attributes of a TTP on a TE node."; + leaf admin-status { + type te-types:te-admin-status; + description + "The administrative state of the TTP."; + } + leaf name { + type string; + description + "A descriptive name for the TTP."; + } + leaf switching-capability { + type identityref { + base te-types:switching-capabilities; + } + description + "Switching capability for this interface."; + } + leaf encoding { + type identityref { + base te-types:lsp-encoding-types; + } + description + "Encoding supported by this interface."; + } + leaf-list inter-layer-lock-id { + type uint32; + description + "Inter-layer lock ID, used for path computation in a TE + topology covering multiple layers or multiple regions."; + reference + "RFC 5212: Requirements for GMPLS-Based Multi-Region and + Multi-Layer Networks (MRN/MLN) + RFC 6001: Generalized MPLS (GMPLS) Protocol Extensions + for Multi-Layer and Multi-Region Networks (MLN/MRN)"; + } + leaf protection-type { + type identityref { + base te-types:lsp-protection-type; + } + description + "The protection type that this TTP is capable of."; + } + container client-layer-adaptation { + description + "Contains capability information to support a client-layer + adaptation in a multi-layer topology."; + list switching-capability { + key "switching-capability encoding"; + description + "List of supported switching capabilities."; + reference + "RFC 4202: Routing Extensions in Support of + Generalized Multi-Protocol Label Switching (GMPLS) + RFC 6001: Generalized MPLS (GMPLS) Protocol Extensions + for Multi-Layer and Multi-Region Networks (MLN/MRN)"; + leaf switching-capability { + type identityref { + base te-types:switching-capabilities; + } + description + "Switching capability for the client-layer adaptation."; + } + leaf encoding { + type identityref { + base te-types:lsp-encoding-types; + } + description + "Encoding supported by the client-layer adaptation."; + } + uses te-types:te-bandwidth; + } + } + } + // te-node-tunnel-termination-point-config-attributes + + grouping te-node-tunnel-termination-point-llc-list { + description + "LLCL of a TTP on a TE node."; + list local-link-connectivity { + key "link-tp-ref"; + description + "The termination capabilities between the TTP and the LTP. + This capability information can be used to compute + the tunnel path. + The Interface Adjustment Capability Descriptors (IACDs) + (defined in RFC 6001) on each LTP can be derived from + this list."; + reference + "RFC 6001: Generalized MPLS (GMPLS) Protocol Extensions + for Multi-Layer and Multi-Region Networks (MLN/MRN)"; + leaf link-tp-ref { + type leafref { + path "../../../../../nt:termination-point/nt:tp-id"; + } + description + "LTP."; + } + uses te-types:label-set-info; + uses connectivity-matrix-entry-path-attributes; + } + } + // te-node-tunnel-termination-point-llc-list + + grouping te-path-element { + description + "A group of attributes defining an element in a TE path, + such as a TE node, TE link, TE atomic resource, or label."; + uses te-types:explicit-route-hop; + } + // te-path-element + + grouping te-termination-point-augment { + description + "Augmentation for a TE termination point."; + leaf te-tp-id { + type te-types:te-tp-id; + description + "An identifier that uniquely identifies a TE termination + point."; + } + container te { + must '../te-tp-id'; + presence "TE support"; + description + "Indicates TE support."; + uses te-termination-point-config; + leaf oper-status { + type te-types:te-oper-status; + config false; + description + "The current operational state of the LTP."; + } + uses geolocation-container; + } + } + // te-termination-point-augment + + grouping te-termination-point-config { + description + "TE termination point configuration grouping."; + leaf admin-status { + type te-types:te-admin-status; + description + "The administrative state of the LTP."; + } + leaf name { + type string; + description + "A descriptive name for the LTP."; + } + uses interface-switching-capability-list; + leaf inter-domain-plug-id { + type binary; + description + "A network-wide unique number that identifies on the + network a connection that supports a given inter-domain + TE link. This is a more flexible alternative to specifying + 'remote-te-node-id' and 'remote-te-link-tp-id' on a TE link + when the provider either does not know 'remote-te-node-id' + and 'remote-te-link-tp-id' or needs to give the client the + flexibility to mix and match multiple topologies."; + } + leaf-list inter-layer-lock-id { + type uint32; + description + "Inter-layer lock ID, used for path computation in a TE + topology covering multiple layers or multiple regions."; + reference + "RFC 5212: Requirements for GMPLS-Based Multi-Region and + Multi-Layer Networks (MRN/MLN) + RFC 6001: Generalized MPLS (GMPLS) Protocol Extensions + for Multi-Layer and Multi-Region Networks (MLN/MRN)"; + } + } + // te-termination-point-config + + grouping te-topologies-augment { + description + "Augmentation for TE topologies."; + container te { + presence "TE support"; + description + "Indicates TE support."; + container templates { + description + "Configuration parameters for templates used for a TE + topology."; + list node-template { + if-feature "template"; + key "name"; + leaf name { + type te-types:te-template-name; + description + "The name to identify a TE node template."; + } + description + "The list of TE node templates used to define sharable + and reusable TE node attributes."; + uses template-attributes; + uses te-node-config-attributes-template; + } + // node-template + list link-template { + if-feature "template"; + key "name"; + leaf name { + type te-types:te-template-name; + description + "The name to identify a TE link template."; + } + description + "The list of TE link templates used to define sharable + and reusable TE link attributes."; + uses template-attributes; + uses te-link-config-attributes; + } + // link-template + } + // templates + } + // te + } + // te-topologies-augment + + grouping te-topology-augment { + description + "Augmentation for a TE topology."; + uses te-types:te-topology-identifier; + container te { + must '../te-topology-identifier/provider-id' + + ' and ../te-topology-identifier/client-id' + + ' and ../te-topology-identifier/topology-id'; + presence "TE support"; + description + "Indicates TE support."; + uses te-topology-config; + uses geolocation-container; + } + } + // te-topology-augment + + grouping te-topology-config { + description + "TE topology configuration grouping."; + leaf name { + type string; + description + "Name of the TE topology. This attribute is optional and can + be specified by the operator to describe the TE topology, + which can be useful when 'network-id' (RFC 8345) is not + descriptive and not modifiable because of being generated + by the system."; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + leaf preference { + type uint8 { + range "1..255"; + } + description + "Specifies a preference for this topology. A lower number + indicates a higher preference."; + } + leaf optimization-criterion { + type identityref { + base te-types:objective-function-type; + } + description + "Optimization criterion applied to this topology."; + reference + "RFC 3272: Overview and Principles of Internet Traffic + Engineering"; + } + list nsrlg { + if-feature "nsrlg"; + key "id"; + description + "List of NSRLGs (Non-Shared Risk Link Groups)."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) + Recovery"; + leaf id { + type uint32; + description + "Identifies the NSRLG entry."; + } + leaf disjointness { + type te-types:te-path-disjointness; + description + "The type of resource disjointness."; + } + } + // nsrlg + } + // te-topology-config + + grouping template-attributes { + description + "Common attributes for all templates."; + leaf priority { + type uint16; + description + "The preference value for resolving conflicts between + different templates. When two or more templates specify + values for one configuration attribute, the value from the + template with the highest priority is used. + A lower number indicates a higher priority. The highest + priority is 0."; + } + leaf reference-change-policy { + type enumeration { + enum no-action { + description + "When an attribute changes in this template, the + configuration node referring to this template does + not take any action."; + } + enum not-allowed { + description + "When any configuration object has a reference to this + template, changing this template is not allowed."; + } + enum cascade { + description + "When an attribute changes in this template, the + configuration object referring to this template applies + the new attribute value to the corresponding + configuration."; + } + } + description + "This attribute specifies the action taken for a + configuration node that has a reference to this template."; + } + } + // template-attributes + + /* + * Data nodes + */ + + augment "/nw:networks/nw:network/nw:network-types" { + description + "Introduces a new network type for a TE topology."; + container te-topology { + presence "Indicates a TE topology"; + description + "Its presence identifies the TE topology type."; + } + } + + augment "/nw:networks" { + description + "Augmentation parameters for TE topologies."; + uses te-topologies-augment; + } + + augment "/nw:networks/nw:network" { + when 'nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Configuration parameters for a TE topology."; + uses te-topology-augment; + } + + augment "/nw:networks/nw:network/nw:node" { + when '../nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Configuration parameters for TE at the node level."; + leaf te-node-id { + type te-types:te-node-id; + description + "The identifier of a node in the TE topology. + A node is specific to a topology to which it belongs."; + } + container te { + must '../te-node-id' { + description + "'te-node-id' is mandatory."; + } + must 'count(../nw:supporting-node)<=1' { + description + "For a node in a TE topology, there cannot be more + than one supporting node. If multiple nodes are + abstracted, the 'underlay-topology' field is used."; + } + presence "TE support"; + description + "Indicates TE support."; + uses te-node-augment; + } + } + + augment "/nw:networks/nw:network/nt:link" { + when '../nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Configuration parameters for TE at the link level."; + container te { + must 'count(../nt:supporting-link)<=1' { + description + "For a link in a TE topology, there cannot be more + than one supporting link. If one or more link paths are + abstracted, the underlay is used."; + } + presence "TE support"; + description + "Indicates TE support."; + uses te-link-augment; + } + } + + augment "/nw:networks/nw:network/nw:node/" + + "nt:termination-point" { + when '../../nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Configuration parameters for TE at the termination point + level."; + uses te-termination-point-augment; + } + + augment "/nw:networks/nw:network/nt:link/te/bundle-stack-level/" + + "bundle/bundled-links/bundled-link" { + when '../../../../nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Augmentation for a TE bundled link."; + leaf src-tp-ref { + type leafref { + path "../../../../../nw:node[nw:node-id = " + + "current()/../../../../nt:source/" + + "nt:source-node]/" + + "nt:termination-point/nt:tp-id"; + require-instance true; + } + description + "Reference to another TE termination point on the + same source node."; + } + leaf des-tp-ref { + type leafref { + path "../../../../../nw:node[nw:node-id = " + + "current()/../../../../nt:destination/" + + "nt:dest-node]/" + + "nt:termination-point/nt:tp-id"; + require-instance true; + } + description + "Reference to another TE termination point on the + same destination node."; + } + } + + augment "/nw:networks/nw:network/nw:node/te/" + + "information-source-entry/connectivity-matrices/" + + "connectivity-matrix" { + when '../../../../../nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Augmentation for the TE node connectivity matrix."; + uses te-node-connectivity-matrix-attributes; + } + + augment "/nw:networks/nw:network/nw:node/te/te-node-attributes/" + + "connectivity-matrices/connectivity-matrix" { + when '../../../../../nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Augmentation for the TE node connectivity matrix."; + uses te-node-connectivity-matrix-attributes; + } + + augment "/nw:networks/nw:network/nw:node/te/" + + "tunnel-termination-point/local-link-connectivities" { + when '../../../../nw:network-types/tet:te-topology' { + description + "Augmentation parameters apply only for networks with a + TE topology type."; + } + description + "Augmentation for TE node TTP LLCs (Local Link + Connectivities)."; + uses te-node-tunnel-termination-point-llc-list; + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-te-types@2020-06-10.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-te-types@2020-06-10.yang new file mode 100644 index 000000000..6fc0544de --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-te-types@2020-06-10.yang @@ -0,0 +1,3379 @@ +module ietf-te-types { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-te-types"; + prefix te-types; + + import ietf-inet-types { + prefix inet; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types"; + } + import ietf-routing-types { + prefix rt-types; + reference + "RFC 8294: Common YANG Data Types for the Routing Area"; + } + + organization + "IETF Traffic Engineering Architecture and Signaling (TEAS) + Working Group"; + contact + "WG Web: + WG List: + + Editor: Tarek Saad + + + Editor: Rakesh Gandhi + + + Editor: Vishnu Pavan Beeram + + + Editor: Xufeng Liu + + + Editor: Igor Bryskin + "; + description + "This YANG module contains a collection of generally useful + YANG data type definitions specific to TE. The model fully + conforms to the Network Management Datastore Architecture + (NMDA). + + The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL + NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED', + 'MAY', and 'OPTIONAL' in this document are to be interpreted as + described in BCP 14 (RFC 2119) (RFC 8174) when, and only when, + they appear in all capitals, as shown here. + + Copyright (c) 2020 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Simplified BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 8776; see the + RFC itself for full legal notices."; + + revision 2020-06-10 { + description + "Latest revision of TE types."; + reference + "RFC 8776: Common YANG Data Types for Traffic Engineering"; + } + + /** + * Typedefs + */ + + typedef admin-group { + type yang:hex-string { + /* 01:02:03:04 */ + length "1..11"; + } + description + "Administrative group / resource class / color representation + in 'hex-string' type. + The most significant byte in the hex-string is the farthest + to the left in the byte sequence. Leading zero bytes in the + configured value may be omitted for brevity."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 5305: IS-IS Extensions for Traffic Engineering + RFC 7308: Extended Administrative Groups in MPLS Traffic + Engineering (MPLS-TE)"; + } + + typedef admin-groups { + type union { + type admin-group; + type extended-admin-group; + } + description + "Derived types for TE administrative groups."; + } + + typedef extended-admin-group { + type yang:hex-string; + description + "Extended administrative group / resource class / color + representation in 'hex-string' type. + The most significant byte in the hex-string is the farthest + to the left in the byte sequence. Leading zero bytes in the + configured value may be omitted for brevity."; + reference + "RFC 7308: Extended Administrative Groups in MPLS Traffic + Engineering (MPLS-TE)"; + } + + typedef path-attribute-flags { + type union { + type identityref { + base session-attributes-flags; + } + type identityref { + base lsp-attributes-flags; + } + } + description + "Path attributes flags type."; + } + + typedef performance-metrics-normality { + type enumeration { + enum unknown { + value 0; + description + "Unknown."; + } + enum normal { + value 1; + description + "Normal. Indicates that the anomalous bit is not set."; + } + enum abnormal { + value 2; + description + "Abnormal. Indicates that the anomalous bit is set."; + } + } + description + "Indicates whether a performance metric is normal (anomalous + bit not set), abnormal (anomalous bit set), or unknown."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions + RFC 7823: Performance-Based Path Selection for Explicitly + Routed Label Switched Paths (LSPs) Using TE Metric + Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions"; + } + + typedef srlg { + type uint32; + description + "SRLG type."; + reference + "RFC 4203: OSPF Extensions in Support of Generalized + Multi-Protocol Label Switching (GMPLS) + RFC 5307: IS-IS Extensions in Support of Generalized + Multi-Protocol Label Switching (GMPLS)"; + } + + typedef te-common-status { + type enumeration { + enum up { + description + "Enabled."; + } + enum down { + description + "Disabled."; + } + enum testing { + description + "In some test mode."; + } + enum preparing-maintenance { + description + "The resource is disabled in the control plane to prepare + for a graceful shutdown for maintenance purposes."; + reference + "RFC 5817: Graceful Shutdown in MPLS and Generalized MPLS + Traffic Engineering Networks"; + } + enum maintenance { + description + "The resource is disabled in the data plane for maintenance + purposes."; + } + enum unknown { + description + "Status is unknown."; + } + } + description + "Defines a type representing the common states of a TE + resource."; + } + + typedef te-bandwidth { + type string { + pattern '0[xX](0((\.0?)?[pP](\+)?0?|(\.0?))|' + + '1(\.([\da-fA-F]{0,5}[02468aAcCeE]?)?)?' + + '[pP](\+)?(12[0-7]|' + + '1[01]\d|0?\d?\d)?)|0[xX][\da-fA-F]{1,8}|\d+' + + '(,(0[xX](0((\.0?)?[pP](\+)?0?|(\.0?))|' + + '1(\.([\da-fA-F]{0,5}[02468aAcCeE]?)?)?' + + '[pP](\+)?(12[0-7]|' + + '1[01]\d|0?\d?\d)?)|0[xX][\da-fA-F]{1,8}|\d+))*'; + } + description + "This is the generic bandwidth type. It is a string containing + a list of numbers separated by commas, where each of these + numbers can be non-negative decimal, hex integer, or + hex float: + + (dec | hex | float)[*(','(dec | hex | float))] + + For the packet-switching type, the string encoding follows + the type 'bandwidth-ieee-float32' as defined in RFC 8294 + (e.g., 0x1p10), where the units are in bytes per second. + + For the Optical Transport Network (OTN) switching type, + a list of integers can be used, such as '0,2,3,1', indicating + two ODU0s and one ODU3. ('ODU' stands for 'Optical Data + Unit'.) For Dense Wavelength Division Multiplexing (DWDM), + a list of pairs of slot numbers and widths can be used, + such as '0,2,3,3', indicating a frequency slot 0 with + slot width 2 and a frequency slot 3 with slot width 3. + Canonically, the string is represented as all lowercase and in + hex, where the prefix '0x' precedes the hex number."; + reference + "RFC 8294: Common YANG Data Types for the Routing Area + ITU-T Recommendation G.709: Interfaces for the + optical transport network"; + } + + typedef te-ds-class { + type uint8 { + range "0..7"; + } + description + "The Differentiated Services Class-Type of traffic."; + reference + "RFC 4124: Protocol Extensions for Support of Diffserv-aware + MPLS Traffic Engineering, Section 4.3.1"; + } + + typedef te-global-id { + type uint32; + description + "An identifier to uniquely identify an operator, which can be + either a provider or a client. + The definition of this type is taken from RFCs 6370 and 5003. + This attribute type is used solely to provide a globally + unique context for TE topologies."; + reference + "RFC 5003: Attachment Individual Identifier (AII) Types for + Aggregation + RFC 6370: MPLS Transport Profile (MPLS-TP) Identifiers"; + } + + typedef te-hop-type { + type enumeration { + enum loose { + description + "A loose hop in an explicit path."; + } + enum strict { + description + "A strict hop in an explicit path."; + } + } + description + "Enumerated type for specifying loose or strict paths."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 4.3.3"; + } + + typedef te-link-access-type { + type enumeration { + enum point-to-point { + description + "The link is point-to-point."; + } + enum multi-access { + description + "The link is multi-access, including broadcast and NBMA."; + } + } + description + "Defines a type representing the access type of a TE link."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2"; + } + + typedef te-label-direction { + type enumeration { + enum forward { + description + "Label allocated for the forward LSP direction."; + } + enum reverse { + description + "Label allocated for the reverse LSP direction."; + } + } + description + "Enumerated type for specifying the forward or reverse + label."; + } + + typedef te-link-direction { + type enumeration { + enum incoming { + description + "The explicit route represents an incoming link on + a node."; + } + enum outgoing { + description + "The explicit route represents an outgoing link on + a node."; + } + } + description + "Enumerated type for specifying the direction of a link on + a node."; + } + + typedef te-metric { + type uint32; + description + "TE metric."; + reference + "RFC 3785: Use of Interior Gateway Protocol (IGP) Metric as a + second MPLS Traffic Engineering (TE) Metric"; + } + + typedef te-node-id { + type yang:dotted-quad; + description + "A type representing the identifier for a node in a TE + topology. + The identifier is represented as 4 octets in dotted-quad + notation. + This attribute MAY be mapped to the Router Address TLV + described in Section 2.4.1 of RFC 3630, the TE Router ID + described in Section 3 of RFC 6827, the Traffic Engineering + Router ID TLV described in Section 4.3 of RFC 5305, or the + TE Router ID TLV described in Section 3.2.1 of RFC 6119. + The reachability of such a TE node MAY be achieved by a + mechanism such as that described in Section 6.2 of RFC 6827."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2, Section 2.4.1 + RFC 5305: IS-IS Extensions for Traffic Engineering, + Section 4.3 + RFC 6119: IPv6 Traffic Engineering in IS-IS, Section 3.2.1 + RFC 6827: Automatically Switched Optical Network (ASON) + Routing for OSPFv2 Protocols, Section 3"; + } + + typedef te-oper-status { + type te-common-status; + description + "Defines a type representing the operational status of + a TE resource."; + } + + typedef te-admin-status { + type te-common-status; + description + "Defines a type representing the administrative status of + a TE resource."; + } + + typedef te-path-disjointness { + type bits { + bit node { + position 0; + description + "Node disjoint."; + } + bit link { + position 1; + description + "Link disjoint."; + } + bit srlg { + position 2; + description + "SRLG (Shared Risk Link Group) disjoint."; + } + } + description + "Type of the resource disjointness for a TE tunnel path."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + typedef te-recovery-status { + type enumeration { + enum normal { + description + "Both the recovery span and the working span are fully + allocated and active, data traffic is being + transported over (or selected from) the working + span, and no trigger events are reported."; + } + enum recovery-started { + description + "The recovery action has been started but not completed."; + } + enum recovery-succeeded { + description + "The recovery action has succeeded. The working span has + reported a failure/degrade condition, and the user traffic + is being transported (or selected) on the recovery span."; + } + enum recovery-failed { + description + "The recovery action has failed."; + } + enum reversion-started { + description + "The reversion has started."; + } + enum reversion-succeeded { + description + "The reversion action has succeeded."; + } + enum reversion-failed { + description + "The reversion has failed."; + } + enum recovery-unavailable { + description + "The recovery is unavailable, as a result of either an + operator's lockout command or a failure condition + detected on the recovery span."; + } + enum recovery-admin { + description + "The operator has issued a command to switch the user + traffic to the recovery span."; + } + enum wait-to-restore { + description + "The recovery domain is recovering from a failure/degrade + condition on the working span that is being controlled by + the Wait-to-Restore (WTR) timer."; + } + } + description + "Defines the status of a recovery action."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS) + RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection"; + } + + typedef te-template-name { + type string { + pattern '/?([a-zA-Z0-9\-_.]+)(/[a-zA-Z0-9\-_.]+)*'; + } + description + "A type for the name of a TE node template or TE link + template."; + } + + typedef te-topology-event-type { + type enumeration { + enum add { + value 0; + description + "A TE node or TE link has been added."; + } + enum remove { + value 1; + description + "A TE node or TE link has been removed."; + } + enum update { + value 2; + description + "A TE node or TE link has been updated."; + } + } + description + "TE event type for notifications."; + } + + typedef te-topology-id { + type union { + type string { + length "0"; + // empty string + } + type string { + pattern '([a-zA-Z0-9\-_.]+:)*' + + '/?([a-zA-Z0-9\-_.]+)(/[a-zA-Z0-9\-_.]+)*'; + } + } + description + "An identifier for a topology. + It is optional to have one or more prefixes at the beginning, + separated by colons. The prefixes can be 'network-types' as + defined in the 'ietf-network' module in RFC 8345, to help the + user better understand the topology before further inquiry + is made."; + reference + "RFC 8345: A YANG Data Model for Network Topologies"; + } + + typedef te-tp-id { + type union { + type uint32; + // Unnumbered + type inet:ip-address; + // IPv4 or IPv6 address + } + description + "An identifier for a TE link endpoint on a node. + This attribute is mapped to a local or remote link identifier + as defined in RFCs 3630 and 5305."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 5305: IS-IS Extensions for Traffic Engineering"; + } + + /* TE features */ + + feature p2mp-te { + description + "Indicates support for Point-to-Multipoint TE (P2MP-TE)."; + reference + "RFC 4875: Extensions to Resource Reservation Protocol - + Traffic Engineering (RSVP-TE) for Point-to-Multipoint TE + Label Switched Paths (LSPs)"; + } + + feature frr-te { + description + "Indicates support for TE Fast Reroute (FRR)."; + reference + "RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP Tunnels"; + } + + feature extended-admin-groups { + description + "Indicates support for TE link extended administrative + groups."; + reference + "RFC 7308: Extended Administrative Groups in MPLS Traffic + Engineering (MPLS-TE)"; + } + + feature named-path-affinities { + description + "Indicates support for named path affinities."; + } + + feature named-extended-admin-groups { + description + "Indicates support for named extended administrative groups."; + } + + feature named-srlg-groups { + description + "Indicates support for named SRLG groups."; + } + + feature named-path-constraints { + description + "Indicates support for named path constraints."; + } + + feature path-optimization-metric { + description + "Indicates support for path optimization metrics."; + } + + feature path-optimization-objective-function { + description + "Indicates support for path optimization objective functions."; + } + + /* + * Identities + */ + + identity session-attributes-flags { + description + "Base identity for the RSVP-TE session attributes flags."; + } + + identity local-protection-desired { + base session-attributes-flags; + description + "Local protection is desired."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 4.7.1"; + } + + identity se-style-desired { + base session-attributes-flags; + description + "Shared explicit style, to allow the LSP to be established + and share resources with the old LSP."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + + identity local-recording-desired { + base session-attributes-flags; + description + "Label recording is desired."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 4.7.1"; + } + + identity bandwidth-protection-desired { + base session-attributes-flags; + description + "Requests FRR bandwidth protection on LSRs, if present."; + reference + "RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP Tunnels"; + } + + identity node-protection-desired { + base session-attributes-flags; + description + "Requests FRR node protection on LSRs, if present."; + reference + "RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP Tunnels"; + } + + identity path-reevaluation-request { + base session-attributes-flags; + description + "This flag indicates that a path re-evaluation (of the + current path in use) is requested. Note that this does + not trigger any LSP reroutes but instead just signals a + request to evaluate whether a preferable path exists."; + reference + "RFC 4736: Reoptimization of Multiprotocol Label Switching + (MPLS) Traffic Engineering (TE) Loosely Routed Label Switched + Path (LSP)"; + } + + identity soft-preemption-desired { + base session-attributes-flags; + description + "Soft preemption of LSP resources is desired."; + reference + "RFC 5712: MPLS Traffic Engineering Soft Preemption"; + } + + identity lsp-attributes-flags { + description + "Base identity for LSP attributes flags."; + } + + identity end-to-end-rerouting-desired { + base lsp-attributes-flags; + description + "Indicates end-to-end rerouting behavior for an LSP + undergoing establishment. This MAY also be used to + specify the behavior of end-to-end LSP recovery for + established LSPs."; + reference + "RFC 4920: Crankback Signaling Extensions for MPLS and GMPLS + RSVP-TE + RFC 5420: Encoding of Attributes for MPLS LSP Establishment + Using Resource Reservation Protocol Traffic Engineering + (RSVP-TE) + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity boundary-rerouting-desired { + base lsp-attributes-flags; + description + "Indicates boundary rerouting behavior for an LSP undergoing + establishment. This MAY also be used to specify + segment-based LSP recovery through nested crankback for + established LSPs. The boundary Area Border Router (ABR) / + Autonomous System Border Router (ASBR) can decide to forward + the PathErr message upstream to either an upstream boundary + ABR/ASBR or the ingress LSR. Alternatively, it can try to + select another egress boundary LSR."; + reference + "RFC 4920: Crankback Signaling Extensions for MPLS and GMPLS + RSVP-TE + RFC 5420: Encoding of Attributes for MPLS LSP Establishment + Using Resource Reservation Protocol Traffic Engineering + (RSVP-TE) + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity segment-based-rerouting-desired { + base lsp-attributes-flags; + description + "Indicates segment-based rerouting behavior for an LSP + undergoing establishment. This MAY also be used to specify + segment-based LSP recovery for established LSPs."; + reference + "RFC 4920: Crankback Signaling Extensions for MPLS and GMPLS + RSVP-TE + RFC 5420: Encoding of Attributes for MPLS LSP Establishment + Using Resource Reservation Protocol Traffic Engineering + (RSVP-TE) + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity lsp-integrity-required { + base lsp-attributes-flags; + description + "Indicates that LSP integrity is required."; + reference + "RFC 4875: Extensions to Resource Reservation Protocol - + Traffic Engineering (RSVP-TE) for Point-to-Multipoint TE + Label Switched Paths (LSPs) + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity contiguous-lsp-desired { + base lsp-attributes-flags; + description + "Indicates that a contiguous LSP is desired."; + reference + "RFC 5151: Inter-Domain MPLS and GMPLS Traffic Engineering -- + Resource Reservation Protocol-Traffic Engineering (RSVP-TE) + Extensions + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity lsp-stitching-desired { + base lsp-attributes-flags; + description + "Indicates that LSP stitching is desired."; + reference + "RFC 5150: Label Switched Path Stitching with Generalized + Multiprotocol Label Switching Traffic Engineering (GMPLS TE) + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity pre-planned-lsp-flag { + base lsp-attributes-flags; + description + "Indicates that the LSP MUST be provisioned in the + control plane only."; + reference + "RFC 6001: Generalized MPLS (GMPLS) Protocol Extensions for + Multi-Layer and Multi-Region Networks (MLN/MRN) + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity non-php-behavior-flag { + base lsp-attributes-flags; + description + "Indicates that non-PHP (non-Penultimate Hop Popping) behavior + for the LSP is desired."; + reference + "RFC 6511: Non-Penultimate Hop Popping Behavior and Out-of-Band + Mapping for RSVP-TE Label Switched Paths + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity oob-mapping-flag { + base lsp-attributes-flags; + description + "Indicates that signaling of the egress binding information is + out of band (e.g., via the Border Gateway Protocol (BGP))."; + reference + "RFC 6511: Non-Penultimate Hop Popping Behavior and Out-of-Band + Mapping for RSVP-TE Label Switched Paths + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity entropy-label-capability { + base lsp-attributes-flags; + description + "Indicates entropy label capability."; + reference + "RFC 6790: The Use of Entropy Labels in MPLS Forwarding + RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO)"; + } + + identity oam-mep-entity-desired { + base lsp-attributes-flags; + description + "OAM Maintenance Entity Group End Point (MEP) entities + desired."; + reference + "RFC 7260: GMPLS RSVP-TE Extensions for Operations, + Administration, and Maintenance (OAM) Configuration"; + } + + identity oam-mip-entity-desired { + base lsp-attributes-flags; + description + "OAM Maintenance Entity Group Intermediate Points (MIP) + entities desired."; + reference + "RFC 7260: GMPLS RSVP-TE Extensions for Operations, + Administration, and Maintenance (OAM) Configuration"; + } + + identity srlg-collection-desired { + base lsp-attributes-flags; + description + "SRLG collection desired."; + reference + "RFC 7570: Label Switched Path (LSP) Attribute in the Explicit + Route Object (ERO) + RFC 8001: RSVP-TE Extensions for Collecting Shared Risk + Link Group (SRLG) Information"; + } + + identity loopback-desired { + base lsp-attributes-flags; + description + "This flag indicates that a particular node on the LSP is + required to enter loopback mode. This can also be + used to specify the loopback state of the node."; + reference + "RFC 7571: GMPLS RSVP-TE Extensions for Lock Instruct and + Loopback"; + } + + identity p2mp-te-tree-eval-request { + base lsp-attributes-flags; + description + "P2MP-TE tree re-evaluation request."; + reference + "RFC 8149: RSVP Extensions for Reoptimization of Loosely Routed + Point-to-Multipoint Traffic Engineering Label Switched Paths + (LSPs)"; + } + + identity rtm-set-desired { + base lsp-attributes-flags; + description + "Residence Time Measurement (RTM) attribute flag requested."; + reference + "RFC 8169: Residence Time Measurement in MPLS Networks"; + } + + identity link-protection-type { + description + "Base identity for the link protection type."; + } + + identity link-protection-unprotected { + base link-protection-type; + description + "Unprotected link type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity link-protection-extra-traffic { + base link-protection-type; + description + "Extra-Traffic protected link type."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity link-protection-shared { + base link-protection-type; + description + "Shared protected link type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity link-protection-1-for-1 { + base link-protection-type; + description + "One-for-one (1:1) protected link type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity link-protection-1-plus-1 { + base link-protection-type; + description + "One-plus-one (1+1) protected link type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity link-protection-enhanced { + base link-protection-type; + description + "A compound link protection type derived from the underlay + TE tunnel protection configuration supporting the TE link."; + } + + identity association-type { + description + "Base identity for the tunnel association."; + } + + identity association-type-recovery { + base association-type; + description + "Association type for recovery, used to associate LSPs of the + same tunnel for recovery."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery + RFC 6780: RSVP ASSOCIATION Object Extensions"; + } + + identity association-type-resource-sharing { + base association-type; + description + "Association type for resource sharing, used to enable + resource sharing during make-before-break."; + reference + "RFC 4873: GMPLS Segment Recovery + RFC 6780: RSVP ASSOCIATION Object Extensions"; + } + + identity association-type-double-sided-bidir { + base association-type; + description + "Association type for double-sided bidirectional LSPs, + used to associate two LSPs of two tunnels that are + independently configured on either endpoint."; + reference + "RFC 7551: RSVP-TE Extensions for Associated Bidirectional + Label Switched Paths (LSPs)"; + } + + identity association-type-single-sided-bidir { + base association-type; + description + "Association type for single-sided bidirectional LSPs, + used to associate two LSPs of two tunnels, where one + tunnel is configured on one side/endpoint and the other + tunnel is dynamically created on the other endpoint."; + reference + "RFC 6780: RSVP ASSOCIATION Object Extensions + RFC 7551: RSVP-TE Extensions for Associated Bidirectional + Label Switched Paths (LSPs)"; + } + + identity objective-function-type { + description + "Base objective function type."; + } + + identity of-minimize-cost-path { + base objective-function-type; + description + "Objective function for minimizing path cost."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity of-minimize-load-path { + base objective-function-type; + description + "Objective function for minimizing the load on one or more + paths."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity of-maximize-residual-bandwidth { + base objective-function-type; + description + "Objective function for maximizing residual bandwidth."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity of-minimize-agg-bandwidth-consumption { + base objective-function-type; + description + "Objective function for minimizing aggregate bandwidth + consumption."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity of-minimize-load-most-loaded-link { + base objective-function-type; + description + "Objective function for minimizing the load on the link that + is carrying the highest load."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity of-minimize-cost-path-set { + base objective-function-type; + description + "Objective function for minimizing the cost on a path set."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity path-computation-method { + description + "Base identity for supported path computation mechanisms."; + } + + identity path-locally-computed { + base path-computation-method; + description + "Indicates a constrained-path LSP in which the + path is computed by the local LER."; + reference + "RFC 3272: Overview and Principles of Internet Traffic + Engineering, Section 5.4"; + } + + identity path-externally-queried { + base path-computation-method; + description + "Constrained-path LSP in which the path is obtained by + querying an external source, such as a PCE server. + In the case that an LSP is defined to be externally queried, + it may also have associated explicit definitions (provided + to the external source to aid computation). The path that is + returned by the external source may require further local + computation on the device."; + reference + "RFC 3272: Overview and Principles of Internet Traffic + Engineering + RFC 4657: Path Computation Element (PCE) Communication + Protocol Generic Requirements"; + } + + identity path-explicitly-defined { + base path-computation-method; + description + "Constrained-path LSP in which the path is + explicitly specified as a collection of strict and/or loose + hops."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels + RFC 3272: Overview and Principles of Internet Traffic + Engineering"; + } + + identity lsp-metric-type { + description + "Base identity for the LSP metric specification types."; + } + + identity lsp-metric-relative { + base lsp-metric-type; + description + "The metric specified for the LSPs to which this identity + refers is specified as a value relative to the IGP metric + cost to the LSP's tail end."; + reference + "RFC 4657: Path Computation Element (PCE) Communication + Protocol Generic Requirements"; + } + + identity lsp-metric-absolute { + base lsp-metric-type; + description + "The metric specified for the LSPs to which this identity + refers is specified as an absolute value."; + reference + "RFC 4657: Path Computation Element (PCE) Communication + Protocol Generic Requirements"; + } + + identity lsp-metric-inherited { + base lsp-metric-type; + description + "The metric for the LSPs to which this identity refers is + not specified explicitly; rather, it is directly inherited + from the IGP cost."; + reference + "RFC 4657: Path Computation Element (PCE) Communication + Protocol Generic Requirements"; + } + + identity te-tunnel-type { + description + "Base identity from which specific tunnel types are derived."; + } + + identity te-tunnel-p2p { + base te-tunnel-type; + description + "TE Point-to-Point (P2P) tunnel type."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + + identity te-tunnel-p2mp { + base te-tunnel-type; + description + "TE P2MP tunnel type."; + reference + "RFC 4875: Extensions to Resource Reservation Protocol - + Traffic Engineering (RSVP-TE) for Point-to-Multipoint TE + Label Switched Paths (LSPs)"; + } + + identity tunnel-action-type { + description + "Base identity from which specific tunnel action types + are derived."; + } + + identity tunnel-action-resetup { + base tunnel-action-type; + description + "TE tunnel action that tears down the tunnel's current LSP + (if any) and attempts to re-establish a new LSP."; + } + + identity tunnel-action-reoptimize { + base tunnel-action-type; + description + "TE tunnel action that reoptimizes the placement of the + tunnel LSP(s)."; + } + + identity tunnel-action-switchpath { + base tunnel-action-type; + description + "TE tunnel action that switches the tunnel's LSP to use the + specified path."; + } + + identity te-action-result { + description + "Base identity from which specific TE action results + are derived."; + } + + identity te-action-success { + base te-action-result; + description + "TE action was successful."; + } + + identity te-action-fail { + base te-action-result; + description + "TE action failed."; + } + + identity tunnel-action-inprogress { + base te-action-result; + description + "TE action is in progress."; + } + + identity tunnel-admin-state-type { + description + "Base identity for TE tunnel administrative states."; + } + + identity tunnel-admin-state-up { + base tunnel-admin-state-type; + description + "Tunnel's administrative state is up."; + } + + identity tunnel-admin-state-down { + base tunnel-admin-state-type; + description + "Tunnel's administrative state is down."; + } + + identity tunnel-state-type { + description + "Base identity for TE tunnel states."; + } + + identity tunnel-state-up { + base tunnel-state-type; + description + "Tunnel's state is up."; + } + + identity tunnel-state-down { + base tunnel-state-type; + description + "Tunnel's state is down."; + } + + identity lsp-state-type { + description + "Base identity for TE LSP states."; + } + + identity lsp-path-computing { + base lsp-state-type; + description + "State path computation is in progress."; + } + + identity lsp-path-computation-ok { + base lsp-state-type; + description + "State path computation was successful."; + } + + identity lsp-path-computation-failed { + base lsp-state-type; + description + "State path computation failed."; + } + + identity lsp-state-setting-up { + base lsp-state-type; + description + "State is being set up."; + } + + identity lsp-state-setup-ok { + base lsp-state-type; + description + "State setup was successful."; + } + + identity lsp-state-setup-failed { + base lsp-state-type; + description + "State setup failed."; + } + + identity lsp-state-up { + base lsp-state-type; + description + "State is up."; + } + + identity lsp-state-tearing-down { + base lsp-state-type; + description + "State is being torn down."; + } + + identity lsp-state-down { + base lsp-state-type; + description + "State is down."; + } + + identity path-invalidation-action-type { + description + "Base identity for TE path invalidation action types."; + } + + identity path-invalidation-action-drop { + base path-invalidation-action-type; + description + "Upon invalidation of the TE tunnel path, the tunnel remains + valid, but any packet mapped over the tunnel is dropped."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 2.5"; + } + + identity path-invalidation-action-teardown { + base path-invalidation-action-type; + description + "TE path invalidation action teardown."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 2.5"; + } + + identity lsp-restoration-type { + description + "Base identity from which LSP restoration types are derived."; + } + + identity lsp-restoration-restore-any { + base lsp-restoration-type; + description + "Any LSP affected by a failure is restored."; + } + + identity lsp-restoration-restore-all { + base lsp-restoration-type; + description + "Affected LSPs are restored after all LSPs of the tunnel are + broken."; + } + + identity restoration-scheme-type { + description + "Base identity for LSP restoration schemes."; + } + + identity restoration-scheme-preconfigured { + base restoration-scheme-type; + description + "Restoration LSP is preconfigured prior to the failure."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity restoration-scheme-precomputed { + base restoration-scheme-type; + description + "Restoration LSP is precomputed prior to the failure."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity restoration-scheme-presignaled { + base restoration-scheme-type; + description + "Restoration LSP is presignaled prior to the failure."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity lsp-protection-type { + description + "Base identity from which LSP protection types are derived."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-unprotected { + base lsp-protection-type; + description + "'Unprotected' LSP protection type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-reroute-extra { + base lsp-protection-type; + description + "'(Full) Rerouting' LSP protection type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-reroute { + base lsp-protection-type; + description + "'Rerouting without Extra-Traffic' LSP protection type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-1-for-n { + base lsp-protection-type; + description + "'1:N Protection with Extra-Traffic' LSP protection type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-1-for-1 { + base lsp-protection-type; + description + "LSP protection '1:1 Protection Type'."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-unidir-1-plus-1 { + base lsp-protection-type; + description + "'1+1 Unidirectional Protection' LSP protection type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-bidir-1-plus-1 { + base lsp-protection-type; + description + "'1+1 Bidirectional Protection' LSP protection type."; + reference + "RFC 4872: RSVP-TE Extensions in Support of End-to-End + Generalized Multi-Protocol Label Switching (GMPLS) Recovery"; + } + + identity lsp-protection-extra-traffic { + base lsp-protection-type; + description + "Extra-Traffic LSP protection type."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity lsp-protection-state { + description + "Base identity of protection states for reporting purposes."; + } + + identity normal { + base lsp-protection-state; + description + "Normal state."; + } + + identity signal-fail-of-protection { + base lsp-protection-state; + description + "The protection transport entity has a signal fail condition + that is of higher priority than the forced switchover + command."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity lockout-of-protection { + base lsp-protection-state; + description + "A Loss of Protection (LoP) command is active."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity forced-switch { + base lsp-protection-state; + description + "A forced switchover command is active."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity signal-fail { + base lsp-protection-state; + description + "There is a signal fail condition on either the working path + or the protection path."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity signal-degrade { + base lsp-protection-state; + description + "There is a signal degrade condition on either the working + path or the protection path."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity manual-switch { + base lsp-protection-state; + description + "A manual switchover command is active."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity wait-to-restore { + base lsp-protection-state; + description + "A WTR timer is running."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity do-not-revert { + base lsp-protection-state; + description + "A Do Not Revert (DNR) condition is active because of + non-revertive behavior."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity failure-of-protocol { + base lsp-protection-state; + description + "LSP protection is not working because of a protocol failure + condition."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity protection-external-commands { + description + "Base identity from which protection-related external commands + used for troubleshooting purposes are derived."; + } + + identity action-freeze { + base protection-external-commands; + description + "A temporary configuration action initiated by an operator + command that prevents any switchover action from being taken + and, as such, freezes the current state."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity clear-freeze { + base protection-external-commands; + description + "An action that clears the active freeze state."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity action-lockout-of-normal { + base protection-external-commands; + description + "A temporary configuration action initiated by an operator + command to ensure that the normal traffic is not allowed + to use the protection transport entity."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity clear-lockout-of-normal { + base protection-external-commands; + description + "An action that clears the active lockout of the + normal state."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity action-lockout-of-protection { + base protection-external-commands; + description + "A temporary configuration action initiated by an operator + command to ensure that the protection transport entity is + temporarily not available to transport a traffic signal + (either normal or Extra-Traffic)."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity action-forced-switch { + base protection-external-commands; + description + "A switchover action initiated by an operator command to switch + the Extra-Traffic signal, the normal traffic signal, or the + null signal to the protection transport entity, unless a + switchover command of equal or higher priority is in effect."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity action-manual-switch { + base protection-external-commands; + description + "A switchover action initiated by an operator command to switch + the Extra-Traffic signal, the normal traffic signal, or + the null signal to the protection transport entity, unless + a fault condition exists on other transport entities or a + switchover command of equal or higher priority is in effect."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity action-exercise { + base protection-external-commands; + description + "An action that starts testing whether or not APS communication + is operating correctly. It is of lower priority than any + other state or command."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity clear { + base protection-external-commands; + description + "An action that clears the active near-end lockout of a + protection, forced switchover, manual switchover, WTR state, + or exercise command."; + reference + "RFC 4427: Recovery (Protection and Restoration) Terminology + for Generalized Multi-Protocol Label Switching (GMPLS)"; + } + + identity switching-capabilities { + description + "Base identity for interface switching capabilities."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity switching-psc1 { + base switching-capabilities; + description + "Packet-Switch Capable-1 (PSC-1)."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity switching-evpl { + base switching-capabilities; + description + "Ethernet Virtual Private Line (EVPL)."; + reference + "RFC 6004: Generalized MPLS (GMPLS) Support for Metro Ethernet + Forum and G.8011 Ethernet Service Switching"; + } + + identity switching-l2sc { + base switching-capabilities; + description + "Layer-2 Switch Capable (L2SC)."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity switching-tdm { + base switching-capabilities; + description + "Time-Division-Multiplex Capable (TDM)."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity switching-otn { + base switching-capabilities; + description + "OTN-TDM capable."; + reference + "RFC 7138: Traffic Engineering Extensions to OSPF for GMPLS + Control of Evolving G.709 Optical Transport Networks"; + } + + identity switching-dcsc { + base switching-capabilities; + description + "Data Channel Switching Capable (DCSC)."; + reference + "RFC 6002: Generalized MPLS (GMPLS) Data Channel + Switching Capable (DCSC) and Channel Set Label Extensions"; + } + + identity switching-lsc { + base switching-capabilities; + description + "Lambda-Switch Capable (LSC)."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity switching-fsc { + base switching-capabilities; + description + "Fiber-Switch Capable (FSC)."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-types { + description + "Base identity for encoding types."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-packet { + base lsp-encoding-types; + description + "Packet LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-ethernet { + base lsp-encoding-types; + description + "Ethernet LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-pdh { + base lsp-encoding-types; + description + "ANSI/ETSI PDH LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-sdh { + base lsp-encoding-types; + description + "SDH ITU-T G.707 / SONET ANSI T1.105 LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-digital-wrapper { + base lsp-encoding-types; + description + "Digital Wrapper LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-lambda { + base lsp-encoding-types; + description + "Lambda (photonic) LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-fiber { + base lsp-encoding-types; + description + "Fiber LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-fiber-channel { + base lsp-encoding-types; + description + "FiberChannel LSP encoding."; + reference + "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Functional Description"; + } + + identity lsp-encoding-oduk { + base lsp-encoding-types; + description + "G.709 ODUk (Digital Path) LSP encoding."; + reference + "RFC 4328: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Extensions for G.709 Optical Transport Networks + Control"; + } + + identity lsp-encoding-optical-channel { + base lsp-encoding-types; + description + "G.709 Optical Channel LSP encoding."; + reference + "RFC 4328: Generalized Multi-Protocol Label Switching (GMPLS) + Signaling Extensions for G.709 Optical Transport Networks + Control"; + } + + identity lsp-encoding-line { + base lsp-encoding-types; + description + "Line (e.g., 8B/10B) LSP encoding."; + reference + "RFC 6004: Generalized MPLS (GMPLS) Support for Metro + Ethernet Forum and G.8011 Ethernet Service Switching"; + } + + identity path-signaling-type { + description + "Base identity from which specific LSP path setup types + are derived."; + } + + identity path-setup-static { + base path-signaling-type; + description + "Static LSP provisioning path setup."; + } + + identity path-setup-rsvp { + base path-signaling-type; + description + "RSVP-TE signaling path setup."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + + identity path-setup-sr { + base path-signaling-type; + description + "Segment-routing path setup."; + } + + identity path-scope-type { + description + "Base identity from which specific path scope types are + derived."; + } + + identity path-scope-segment { + base path-scope-type; + description + "Path scope segment."; + reference + "RFC 4873: GMPLS Segment Recovery"; + } + + identity path-scope-end-to-end { + base path-scope-type; + description + "Path scope end to end."; + reference + "RFC 4873: GMPLS Segment Recovery"; + } + + identity route-usage-type { + description + "Base identity for route usage."; + } + + identity route-include-object { + base route-usage-type; + description + "'Include route' object."; + } + + identity route-exclude-object { + base route-usage-type; + description + "'Exclude route' object."; + reference + "RFC 4874: Exclude Routes - Extension to Resource ReserVation + Protocol-Traffic Engineering (RSVP-TE)"; + } + + identity route-exclude-srlg { + base route-usage-type; + description + "Excludes SRLGs."; + reference + "RFC 4874: Exclude Routes - Extension to Resource ReserVation + Protocol-Traffic Engineering (RSVP-TE)"; + } + + identity path-metric-type { + description + "Base identity for the path metric type."; + } + + identity path-metric-te { + base path-metric-type; + description + "TE path metric."; + reference + "RFC 3785: Use of Interior Gateway Protocol (IGP) Metric as a + second MPLS Traffic Engineering (TE) Metric"; + } + + identity path-metric-igp { + base path-metric-type; + description + "IGP path metric."; + reference + "RFC 3785: Use of Interior Gateway Protocol (IGP) Metric as a + second MPLS Traffic Engineering (TE) Metric"; + } + + identity path-metric-hop { + base path-metric-type; + description + "Hop path metric."; + } + + identity path-metric-delay-average { + base path-metric-type; + description + "Average unidirectional link delay."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions"; + } + + identity path-metric-delay-minimum { + base path-metric-type; + description + "Minimum unidirectional link delay."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions"; + } + + identity path-metric-residual-bandwidth { + base path-metric-type; + description + "Unidirectional Residual Bandwidth, which is defined to be + Maximum Bandwidth (RFC 3630) minus the bandwidth currently + allocated to LSPs."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2 + RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions"; + } + + identity path-metric-optimize-includes { + base path-metric-type; + description + "A metric that optimizes the number of included resources + specified in a set."; + } + + identity path-metric-optimize-excludes { + base path-metric-type; + description + "A metric that optimizes to a maximum the number of excluded + resources specified in a set."; + } + + identity path-tiebreaker-type { + description + "Base identity for the path tiebreaker type."; + } + + identity path-tiebreaker-minfill { + base path-tiebreaker-type; + description + "Min-Fill LSP path placement."; + } + + identity path-tiebreaker-maxfill { + base path-tiebreaker-type; + description + "Max-Fill LSP path placement."; + } + + identity path-tiebreaker-random { + base path-tiebreaker-type; + description + "Random LSP path placement."; + } + + identity resource-affinities-type { + description + "Base identity for resource class affinities."; + reference + "RFC 2702: Requirements for Traffic Engineering Over MPLS"; + } + + identity resource-aff-include-all { + base resource-affinities-type; + description + "The set of attribute filters associated with a + tunnel, all of which must be present for a link + to be acceptable."; + reference + "RFC 2702: Requirements for Traffic Engineering Over MPLS + RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + + identity resource-aff-include-any { + base resource-affinities-type; + description + "The set of attribute filters associated with a + tunnel, any of which must be present for a link + to be acceptable."; + reference + "RFC 2702: Requirements for Traffic Engineering Over MPLS + RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + + identity resource-aff-exclude-any { + base resource-affinities-type; + description + "The set of attribute filters associated with a + tunnel, any of which renders a link unacceptable."; + reference + "RFC 2702: Requirements for Traffic Engineering Over MPLS + RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + + identity te-optimization-criterion { + description + "Base identity for the TE optimization criteria."; + reference + "RFC 3272: Overview and Principles of Internet Traffic + Engineering"; + } + + identity not-optimized { + base te-optimization-criterion; + description + "Optimization is not applied."; + } + + identity cost { + base te-optimization-criterion; + description + "Optimized on cost."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity delay { + base te-optimization-criterion; + description + "Optimized on delay."; + reference + "RFC 5541: Encoding of Objective Functions in the Path + Computation Element Communication Protocol (PCEP)"; + } + + identity path-computation-srlg-type { + description + "Base identity for SRLG path computation."; + } + + identity srlg-ignore { + base path-computation-srlg-type; + description + "Ignores SRLGs in the path computation."; + } + + identity srlg-strict { + base path-computation-srlg-type; + description + "Includes a strict SRLG check in the path computation."; + } + + identity srlg-preferred { + base path-computation-srlg-type; + description + "Includes a preferred SRLG check in the path computation."; + } + + identity srlg-weighted { + base path-computation-srlg-type; + description + "Includes a weighted SRLG check in the path computation."; + } + + /** + * TE bandwidth groupings + **/ + + grouping te-bandwidth { + description + "This grouping defines the generic TE bandwidth. + For some known data-plane technologies, specific modeling + structures are specified. The string-encoded 'te-bandwidth' + type is used for unspecified technologies. + The modeling structure can be augmented later for other + technologies."; + container te-bandwidth { + description + "Container that specifies TE bandwidth. The choices + can be augmented for specific data-plane technologies."; + choice technology { + default "generic"; + description + "Data-plane technology type."; + case generic { + leaf generic { + type te-bandwidth; + description + "Bandwidth specified in a generic format."; + } + } + } + } + } + + /** + * TE label groupings + **/ + + grouping te-label { + description + "This grouping defines the generic TE label. + The modeling structure can be augmented for each technology. + For unspecified technologies, 'rt-types:generalized-label' + is used."; + container te-label { + description + "Container that specifies the TE label. The choices can + be augmented for specific data-plane technologies."; + choice technology { + default "generic"; + description + "Data-plane technology type."; + case generic { + leaf generic { + type rt-types:generalized-label; + description + "TE label specified in a generic format."; + } + } + } + leaf direction { + type te-label-direction; + default "forward"; + description + "Label direction."; + } + } + } + + grouping te-topology-identifier { + description + "Augmentation for a TE topology."; + container te-topology-identifier { + description + "TE topology identifier container."; + leaf provider-id { + type te-global-id; + default "0"; + description + "An identifier to uniquely identify a provider. + If omitted, it assumes that the topology provider ID + value = 0 (the default)."; + } + leaf client-id { + type te-global-id; + default "0"; + description + "An identifier to uniquely identify a client. + If omitted, it assumes that the topology client ID + value = 0 (the default)."; + } + leaf topology-id { + type te-topology-id; + default ""; + description + "When the datastore contains several topologies, + 'topology-id' distinguishes between them. If omitted, + the default (empty) string for this leaf is assumed."; + } + } + } + + /** + * TE performance metrics groupings + **/ + + grouping performance-metrics-one-way-delay-loss { + description + "Performance Metrics (PM) information in real time that can + be applicable to links or connections. PM defined in this + grouping are applicable to generic TE PM as well as packet TE + PM."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions + RFC 7823: Performance-Based Path Selection for Explicitly + Routed Label Switched Paths (LSPs) Using TE Metric + Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions"; + leaf one-way-delay { + type uint32 { + range "0..16777215"; + } + description + "One-way delay or latency in microseconds."; + } + leaf one-way-delay-normality { + type te-types:performance-metrics-normality; + description + "One-way delay normality."; + } + } + + grouping performance-metrics-two-way-delay-loss { + description + "PM information in real time that can be applicable to links or + connections. PM defined in this grouping are applicable to + generic TE PM as well as packet TE PM."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions + RFC 7823: Performance-Based Path Selection for Explicitly + Routed Label Switched Paths (LSPs) Using TE Metric + Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions"; + leaf two-way-delay { + type uint32 { + range "0..16777215"; + } + description + "Two-way delay or latency in microseconds."; + } + leaf two-way-delay-normality { + type te-types:performance-metrics-normality; + description + "Two-way delay normality."; + } + } + + grouping performance-metrics-one-way-bandwidth { + description + "PM information in real time that can be applicable to links. + PM defined in this grouping are applicable to generic TE PM + as well as packet TE PM."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions + RFC 7823: Performance-Based Path Selection for Explicitly + Routed Label Switched Paths (LSPs) Using TE Metric + Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions"; + leaf one-way-residual-bandwidth { + type rt-types:bandwidth-ieee-float32; + units "bytes per second"; + default "0x0p0"; + description + "Residual bandwidth that subtracts tunnel reservations from + Maximum Bandwidth (or link capacity) (RFC 3630) and + provides an aggregated remainder across QoS classes."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2"; + } + leaf one-way-residual-bandwidth-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Residual bandwidth normality."; + } + leaf one-way-available-bandwidth { + type rt-types:bandwidth-ieee-float32; + units "bytes per second"; + default "0x0p0"; + description + "Available bandwidth that is defined to be residual + bandwidth minus the measured bandwidth used for the + actual forwarding of non-RSVP-TE LSP packets. For a + bundled link, available bandwidth is defined to be the + sum of the component link available bandwidths."; + } + leaf one-way-available-bandwidth-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Available bandwidth normality."; + } + leaf one-way-utilized-bandwidth { + type rt-types:bandwidth-ieee-float32; + units "bytes per second"; + default "0x0p0"; + description + "Bandwidth utilization that represents the actual + utilization of the link (i.e., as measured in the router). + For a bundled link, bandwidth utilization is defined to + be the sum of the component link bandwidth utilizations."; + } + leaf one-way-utilized-bandwidth-normality { + type te-types:performance-metrics-normality; + default "normal"; + description + "Bandwidth utilization normality."; + } + } + + grouping one-way-performance-metrics { + description + "One-way PM throttle grouping."; + leaf one-way-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "One-way delay or latency in microseconds."; + } + leaf one-way-residual-bandwidth { + type rt-types:bandwidth-ieee-float32; + units "bytes per second"; + default "0x0p0"; + description + "Residual bandwidth that subtracts tunnel reservations from + Maximum Bandwidth (or link capacity) (RFC 3630) and + provides an aggregated remainder across QoS classes."; + reference + "RFC 3630: Traffic Engineering (TE) Extensions to OSPF + Version 2"; + } + leaf one-way-available-bandwidth { + type rt-types:bandwidth-ieee-float32; + units "bytes per second"; + default "0x0p0"; + description + "Available bandwidth that is defined to be residual + bandwidth minus the measured bandwidth used for the + actual forwarding of non-RSVP-TE LSP packets. For a + bundled link, available bandwidth is defined to be the + sum of the component link available bandwidths."; + } + leaf one-way-utilized-bandwidth { + type rt-types:bandwidth-ieee-float32; + units "bytes per second"; + default "0x0p0"; + description + "Bandwidth utilization that represents the actual + utilization of the link (i.e., as measured in the router). + For a bundled link, bandwidth utilization is defined to + be the sum of the component link bandwidth utilizations."; + } + } + + grouping two-way-performance-metrics { + description + "Two-way PM throttle grouping."; + leaf two-way-delay { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Two-way delay or latency in microseconds."; + } + } + + grouping performance-metrics-thresholds { + description + "Grouping for configurable thresholds for measured + attributes."; + uses one-way-performance-metrics; + uses two-way-performance-metrics; + } + + grouping performance-metrics-attributes { + description + "Contains PM attributes."; + container performance-metrics-one-way { + description + "One-way link performance information in real time."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions + RFC 7823: Performance-Based Path Selection for Explicitly + Routed Label Switched Paths (LSPs) Using TE Metric + Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions"; + uses performance-metrics-one-way-delay-loss; + uses performance-metrics-one-way-bandwidth; + } + container performance-metrics-two-way { + description + "Two-way link performance information in real time."; + reference + "RFC 6374: Packet Loss and Delay Measurement for MPLS + Networks"; + uses performance-metrics-two-way-delay-loss; + } + } + + grouping performance-metrics-throttle-container { + description + "Controls PM throttling."; + container throttle { + must 'suppression-interval >= measure-interval' { + error-message "'suppression-interval' cannot be less than " + + "'measure-interval'."; + description + "Constraint on 'suppression-interval' and + 'measure-interval'."; + } + description + "Link performance information in real time."; + reference + "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions + RFC 7823: Performance-Based Path Selection for Explicitly + Routed Label Switched Paths (LSPs) Using TE Metric + Extensions + RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions"; + leaf one-way-delay-offset { + type uint32 { + range "0..16777215"; + } + default "0"; + description + "Offset value to be added to the measured delay value."; + } + leaf measure-interval { + type uint32; + default "30"; + description + "Interval, in seconds, to measure the extended metric + values."; + } + leaf advertisement-interval { + type uint32; + default "0"; + description + "Interval, in seconds, to advertise the extended metric + values."; + } + leaf suppression-interval { + type uint32 { + range "1..max"; + } + default "120"; + description + "Interval, in seconds, to suppress advertisement of the + extended metric values."; + reference + "RFC 8570: IS-IS Traffic Engineering (TE) Metric + Extensions, Section 6"; + } + container threshold-out { + uses performance-metrics-thresholds; + description + "If the measured parameter falls outside an upper bound + for all but the minimum-delay metric (or a lower bound + for the minimum-delay metric only) and the advertised + value is not already outside that bound, an 'anomalous' + announcement (anomalous bit set) will be triggered."; + } + container threshold-in { + uses performance-metrics-thresholds; + description + "If the measured parameter falls inside an upper bound + for all but the minimum-delay metric (or a lower bound + for the minimum-delay metric only) and the advertised + value is not already inside that bound, a 'normal' + announcement (anomalous bit cleared) will be triggered."; + } + container threshold-accelerated-advertisement { + description + "When the difference between the last advertised value and + the current measured value exceeds this threshold, an + 'anomalous' announcement (anomalous bit set) will be + triggered."; + uses performance-metrics-thresholds; + } + } + } + + /** + * TE tunnel generic groupings + **/ + + grouping explicit-route-hop { + description + "The explicit route entry grouping."; + choice type { + description + "The explicit route entry type."; + case numbered-node-hop { + container numbered-node-hop { + leaf node-id { + type te-node-id; + mandatory true; + description + "The identifier of a node in the TE topology."; + } + leaf hop-type { + type te-hop-type; + default "strict"; + description + "Strict or loose hop."; + } + description + "Numbered node route hop."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 4.3, EXPLICIT_ROUTE in RSVP-TE + RFC 3477: Signalling Unnumbered Links in Resource + ReSerVation Protocol - Traffic Engineering (RSVP-TE)"; + } + } + case numbered-link-hop { + container numbered-link-hop { + leaf link-tp-id { + type te-tp-id; + mandatory true; + description + "TE Link Termination Point (LTP) identifier."; + } + leaf hop-type { + type te-hop-type; + default "strict"; + description + "Strict or loose hop."; + } + leaf direction { + type te-link-direction; + default "outgoing"; + description + "Link route object direction."; + } + description + "Numbered link explicit route hop."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 4.3, EXPLICIT_ROUTE in RSVP-TE + RFC 3477: Signalling Unnumbered Links in Resource + ReSerVation Protocol - Traffic Engineering (RSVP-TE)"; + } + } + case unnumbered-link-hop { + container unnumbered-link-hop { + leaf link-tp-id { + type te-tp-id; + mandatory true; + description + "TE LTP identifier. The combination of the TE link ID + and the TE node ID is used to identify an unnumbered + TE link."; + } + leaf node-id { + type te-node-id; + mandatory true; + description + "The identifier of a node in the TE topology."; + } + leaf hop-type { + type te-hop-type; + default "strict"; + description + "Strict or loose hop."; + } + leaf direction { + type te-link-direction; + default "outgoing"; + description + "Link route object direction."; + } + description + "Unnumbered link explicit route hop."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels, + Section 4.3, EXPLICIT_ROUTE in RSVP-TE + RFC 3477: Signalling Unnumbered Links in Resource + ReSerVation Protocol - Traffic Engineering (RSVP-TE)"; + } + } + case as-number { + container as-number-hop { + leaf as-number { + type inet:as-number; + mandatory true; + description + "The Autonomous System (AS) number."; + } + leaf hop-type { + type te-hop-type; + default "strict"; + description + "Strict or loose hop."; + } + description + "AS explicit route hop."; + } + } + case label { + container label-hop { + description + "Label hop type."; + uses te-label; + } + description + "The label explicit route hop type."; + } + } + } + + grouping record-route-state { + description + "The Record Route grouping."; + leaf index { + type uint32; + description + "Record Route hop index. The index is used to + identify an entry in the list. The order of entries + is defined by the user without relying on key values."; + } + choice type { + description + "The Record Route entry type."; + case numbered-node-hop { + container numbered-node-hop { + description + "Numbered node route hop container."; + leaf node-id { + type te-node-id; + mandatory true; + description + "The identifier of a node in the TE topology."; + } + leaf-list flags { + type path-attribute-flags; + description + "Path attributes flags."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels + RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP + Tunnels + RFC 4561: Definition of a Record Route Object (RRO) + Node-Id Sub-Object"; + } + } + description + "Numbered node route hop."; + } + case numbered-link-hop { + container numbered-link-hop { + description + "Numbered link route hop container."; + leaf link-tp-id { + type te-tp-id; + mandatory true; + description + "Numbered TE LTP identifier."; + } + leaf-list flags { + type path-attribute-flags; + description + "Path attributes flags."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels + RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP + Tunnels + RFC 4561: Definition of a Record Route Object (RRO) + Node-Id Sub-Object"; + } + } + description + "Numbered link route hop."; + } + case unnumbered-link-hop { + container unnumbered-link-hop { + leaf link-tp-id { + type te-tp-id; + mandatory true; + description + "TE LTP identifier. The combination of the TE link ID + and the TE node ID is used to identify an unnumbered + TE link."; + } + leaf node-id { + type te-node-id; + description + "The identifier of a node in the TE topology."; + } + leaf-list flags { + type path-attribute-flags; + description + "Path attributes flags."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels + RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP + Tunnels + RFC 4561: Definition of a Record Route Object (RRO) + Node-Id Sub-Object"; + } + description + "Unnumbered link Record Route hop."; + reference + "RFC 3477: Signalling Unnumbered Links in Resource + ReSerVation Protocol - Traffic Engineering (RSVP-TE)"; + } + description + "Unnumbered link route hop."; + } + case label { + container label-hop { + description + "Label route hop type."; + uses te-label; + leaf-list flags { + type path-attribute-flags; + description + "Path attributes flags."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels + RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP + Tunnels + RFC 4561: Definition of a Record Route Object (RRO) + Node-Id Sub-Object"; + } + } + description + "The label Record Route entry types."; + } + } + } + + grouping label-restriction-info { + description + "Label set item information."; + leaf restriction { + type enumeration { + enum inclusive { + description + "The label or label range is inclusive."; + } + enum exclusive { + description + "The label or label range is exclusive."; + } + } + default "inclusive"; + description + "Indicates whether the list item is inclusive or exclusive."; + } + leaf index { + type uint32; + description + "The index of the label restriction list entry."; + } + container label-start { + must "(not(../label-end/te-label/direction) and" + + " not(te-label/direction))" + + " or " + + "(../label-end/te-label/direction = te-label/direction)" + + " or " + + "(not(te-label/direction) and" + + " (../label-end/te-label/direction = 'forward'))" + + " or " + + "(not(../label-end/te-label/direction) and" + + " (te-label/direction = 'forward'))" { + error-message "'label-start' and 'label-end' must have the " + + "same direction."; + } + description + "This is the starting label if a label range is specified. + This is the label value if a single label is specified, + in which case the 'label-end' attribute is not set."; + uses te-label; + } + container label-end { + must "(not(../label-start/te-label/direction) and" + + " not(te-label/direction))" + + " or " + + "(../label-start/te-label/direction = te-label/direction)" + + " or " + + "(not(te-label/direction) and" + + " (../label-start/te-label/direction = 'forward'))" + + " or " + + "(not(../label-start/te-label/direction) and" + + " (te-label/direction = 'forward'))" { + error-message "'label-start' and 'label-end' must have the " + + "same direction."; + } + description + "This is the ending label if a label range is specified. + This attribute is not set if a single label is specified."; + uses te-label; + } + container label-step { + description + "The step increment between labels in the label range. + The label start/end values will have to be consistent + with the sign of label step. For example, + 'label-start' < 'label-end' enforces 'label-step' > 0 + 'label-start' > 'label-end' enforces 'label-step' < 0."; + choice technology { + default "generic"; + description + "Data-plane technology type."; + case generic { + leaf generic { + type int32; + default "1"; + description + "Label range step."; + } + } + } + } + leaf range-bitmap { + type yang:hex-string; + description + "When there are gaps between 'label-start' and 'label-end', + this attribute is used to specify the positions + of the used labels. This is represented in big endian as + 'hex-string'. + The most significant byte in the hex-string is the farthest + to the left in the byte sequence. Leading zero bytes in the + configured value may be omitted for brevity. + Each bit position in the 'range-bitmap' 'hex-string' maps + to a label in the range derived from 'label-start'. + + For example, assuming that 'label-start' = 16000 and + 'range-bitmap' = 0x01000001, then: + + - bit position (0) is set, and the corresponding mapped + label from the range is 16000 + (0 * 'label-step') or + 16000 for default 'label-step' = 1. + - bit position (24) is set, and the corresponding mapped + label from the range is 16000 + (24 * 'label-step') or + 16024 for default 'label-step' = 1."; + } + } + + grouping label-set-info { + description + "Grouping for the list of label restrictions specifying what + labels may or may not be used."; + container label-restrictions { + description + "The label restrictions container."; + list label-restriction { + key "index"; + description + "The absence of the label restrictions container implies + that all labels are acceptable; otherwise, only restricted + labels are available."; + reference + "RFC 7579: General Network Element Constraint Encoding + for GMPLS-Controlled Networks"; + uses label-restriction-info; + } + } + } + + grouping optimization-metric-entry { + description + "Optimization metrics configuration grouping."; + leaf metric-type { + type identityref { + base path-metric-type; + } + description + "Identifies the 'metric-type' that the path computation + process uses for optimization."; + } + leaf weight { + type uint8; + default "1"; + description + "TE path metric normalization weight."; + } + container explicit-route-exclude-objects { + when "../metric-type = " + + "'te-types:path-metric-optimize-excludes'"; + description + "Container for the 'exclude route' object list."; + uses path-route-exclude-objects; + } + container explicit-route-include-objects { + when "../metric-type = " + + "'te-types:path-metric-optimize-includes'"; + description + "Container for the 'include route' object list."; + uses path-route-include-objects; + } + } + + grouping common-constraints { + description + "Common constraints grouping that can be set on + a constraint set or directly on the tunnel."; + uses te-bandwidth { + description + "A requested bandwidth to use for path computation."; + } + leaf link-protection { + type identityref { + base link-protection-type; + } + default "te-types:link-protection-unprotected"; + description + "Link protection type required for the links included + in the computed path."; + reference + "RFC 4202: Routing Extensions in Support of + Generalized Multi-Protocol Label Switching (GMPLS)"; + } + leaf setup-priority { + type uint8 { + range "0..7"; + } + default "7"; + description + "TE LSP requested setup priority."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + leaf hold-priority { + type uint8 { + range "0..7"; + } + default "7"; + description + "TE LSP requested hold priority."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + leaf signaling-type { + type identityref { + base path-signaling-type; + } + default "te-types:path-setup-rsvp"; + description + "TE tunnel path signaling type."; + } + } + + grouping tunnel-constraints { + description + "Tunnel constraints grouping that can be set on + a constraint set or directly on the tunnel."; + uses te-topology-identifier; + uses common-constraints; + } + + grouping path-constraints-route-objects { + description + "List of route entries to be included or excluded when + performing the path computation."; + container explicit-route-objects-always { + description + "Container for the 'exclude route' object list."; + list route-object-exclude-always { + key "index"; + ordered-by user; + description + "List of route objects to always exclude from the path + computation."; + leaf index { + type uint32; + description + "Explicit Route Object index. The index is used to + identify an entry in the list. The order of entries + is defined by the user without relying on key values."; + } + uses explicit-route-hop; + } + list route-object-include-exclude { + key "index"; + ordered-by user; + description + "List of route objects to include or exclude in the path + computation."; + leaf explicit-route-usage { + type identityref { + base route-usage-type; + } + default "te-types:route-include-object"; + description + "Indicates whether to include or exclude the + route object. The default is to include it."; + } + leaf index { + type uint32; + description + "Route object include-exclude index. The index is used + to identify an entry in the list. The order of entries + is defined by the user without relying on key values."; + } + uses explicit-route-hop { + augment "type" { + case srlg { + container srlg { + description + "SRLG container."; + leaf srlg { + type uint32; + description + "SRLG value."; + } + } + description + "An SRLG value to be included or excluded."; + } + description + "Augmentation for a generic explicit route for SRLG + exclusion."; + } + } + } + } + } + + grouping path-route-include-objects { + description + "List of route objects to be included when performing + the path computation."; + list route-object-include-object { + key "index"; + ordered-by user; + description + "List of Explicit Route Objects to be included in the + path computation."; + leaf index { + type uint32; + description + "Route object entry index. The index is used to + identify an entry in the list. The order of entries + is defined by the user without relying on key values."; + } + uses explicit-route-hop; + } + } + + grouping path-route-exclude-objects { + description + "List of route objects to be excluded when performing + the path computation."; + list route-object-exclude-object { + key "index"; + ordered-by user; + description + "List of Explicit Route Objects to be excluded in the + path computation."; + leaf index { + type uint32; + description + "Route object entry index. The index is used to + identify an entry in the list. The order of entries + is defined by the user without relying on key values."; + } + uses explicit-route-hop { + augment "type" { + case srlg { + container srlg { + description + "SRLG container."; + leaf srlg { + type uint32; + description + "SRLG value."; + } + } + description + "An SRLG value to be included or excluded."; + } + description + "Augmentation for a generic explicit route for SRLG + exclusion."; + } + } + } + } + + grouping generic-path-metric-bounds { + description + "TE path metric bounds grouping."; + container path-metric-bounds { + description + "TE path metric bounds container."; + list path-metric-bound { + key "metric-type"; + description + "List of TE path metric bounds."; + leaf metric-type { + type identityref { + base path-metric-type; + } + description + "Identifies an entry in the list of 'metric-type' items + bound for the TE path."; + } + leaf upper-bound { + type uint64; + default "0"; + description + "Upper bound on the end-to-end TE path metric. A zero + indicates an unbounded upper limit for the specific + 'metric-type'."; + } + } + } + } + + grouping generic-path-optimization { + description + "TE generic path optimization grouping."; + container optimizations { + description + "The objective function container that includes + attributes to impose when computing a TE path."; + choice algorithm { + description + "Optimizations algorithm."; + case metric { + if-feature "path-optimization-metric"; + /* Optimize by metric */ + list optimization-metric { + key "metric-type"; + description + "TE path metric type."; + uses optimization-metric-entry; + } + /* Tiebreakers */ + container tiebreakers { + description + "Container for the list of tiebreakers."; + list tiebreaker { + key "tiebreaker-type"; + description + "The list of tiebreaker criteria to apply on an + equally favored set of paths, in order to pick + the best."; + leaf tiebreaker-type { + type identityref { + base path-metric-type; + } + description + "Identifies an entry in the list of tiebreakers."; + } + } + } + } + case objective-function { + if-feature "path-optimization-objective-function"; + /* Objective functions */ + container objective-function { + description + "The objective function container that includes + attributes to impose when computing a TE path."; + leaf objective-function-type { + type identityref { + base objective-function-type; + } + default "te-types:of-minimize-cost-path"; + description + "Objective function entry."; + } + } + } + } + } + } + + grouping generic-path-affinities { + description + "Path affinities grouping."; + container path-affinities-values { + description + "Path affinities represented as values."; + list path-affinities-value { + key "usage"; + description + "List of named affinity constraints."; + leaf usage { + type identityref { + base resource-affinities-type; + } + description + "Identifies an entry in the list of value affinity + constraints."; + } + leaf value { + type admin-groups; + default ""; + description + "The affinity value. The default is empty."; + } + } + } + container path-affinity-names { + description + "Path affinities represented as names."; + list path-affinity-name { + key "usage"; + description + "List of named affinity constraints."; + leaf usage { + type identityref { + base resource-affinities-type; + } + description + "Identifies an entry in the list of named affinity + constraints."; + } + list affinity-name { + key "name"; + leaf name { + type string; + description + "Identifies a named affinity entry."; + } + description + "List of named affinities."; + } + } + } + } + + grouping generic-path-srlgs { + description + "Path SRLG grouping."; + container path-srlgs-lists { + description + "Path SRLG properties container."; + list path-srlgs-list { + key "usage"; + description + "List of SRLG values to be included or excluded."; + leaf usage { + type identityref { + base route-usage-type; + } + description + "Identifies an entry in a list of SRLGs to either + include or exclude."; + } + leaf-list values { + type srlg; + description + "List of SRLG values."; + } + } + } + container path-srlgs-names { + description + "Container for the list of named SRLGs."; + list path-srlgs-name { + key "usage"; + description + "List of named SRLGs to be included or excluded."; + leaf usage { + type identityref { + base route-usage-type; + } + description + "Identifies an entry in a list of named SRLGs to either + include or exclude."; + } + leaf-list names { + type string; + description + "List of named SRLGs."; + } + } + } + } + + grouping generic-path-disjointness { + description + "Path disjointness grouping."; + leaf disjointness { + type te-path-disjointness; + description + "The type of resource disjointness. + When configured for a primary path, the disjointness level + applies to all secondary LSPs. When configured for a + secondary path, the disjointness level overrides the level + configured for the primary path."; + } + } + + grouping common-path-constraints-attributes { + description + "Common path constraints configuration grouping."; + uses common-constraints; + uses generic-path-metric-bounds; + uses generic-path-affinities; + uses generic-path-srlgs; + } + + grouping generic-path-constraints { + description + "Global named path constraints configuration grouping."; + container path-constraints { + description + "TE named path constraints container."; + uses common-path-constraints-attributes; + uses generic-path-disjointness; + } + } + + grouping generic-path-properties { + description + "TE generic path properties grouping."; + container path-properties { + config false; + description + "The TE path properties."; + list path-metric { + key "metric-type"; + description + "TE path metric type."; + leaf metric-type { + type identityref { + base path-metric-type; + } + description + "TE path metric type."; + } + leaf accumulative-value { + type uint64; + description + "TE path metric accumulative value."; + } + } + uses generic-path-affinities; + uses generic-path-srlgs; + container path-route-objects { + description + "Container for the list of route objects either returned by + the computation engine or actually used by an LSP."; + list path-route-object { + key "index"; + ordered-by user; + description + "List of route objects either returned by the computation + engine or actually used by an LSP."; + leaf index { + type uint32; + description + "Route object entry index. The index is used to + identify an entry in the list. The order of entries + is defined by the user without relying on key + values."; + } + uses explicit-route-hop; + } + } + } + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-service@2023-10-23.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-service@2023-10-23.yang new file mode 100644 index 000000000..f0157bcc8 --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-service@2023-10-23.yang @@ -0,0 +1,325 @@ + module ietf-trans-client-service { + /* TODO: FIXME */ + yang-version 1.1; + + namespace "urn:ietf:params:xml:ns:yang:ietf-trans-client-service"; + prefix "clntsvc"; + + import ietf-network { + prefix "nw"; + reference "RFC8345 - A YANG Data Model for Network Topologies"; + } + + import ietf-network-topology { + prefix "nt"; + reference "RFC8345 - A YANG Data Model for Network Topologies"; + } + + import ietf-te-types { + prefix "te-types"; + reference "RFC 8776 - Traffic Engineering Common YANG Types"; + } + + import ietf-layer1-types { + prefix "layer1-types"; + reference "RFC ZZZZ - A YANG Data Model for Layer 1 Types"; + } + + import ietf-yang-types { + prefix "yang"; + reference "RFC 6991 - Common YANG Data Types"; + } + + import ietf-trans-client-svc-types { + prefix "clntsvc-types"; + reference "RFC XXXX - A YANG Data Model for + Transport Network Client Signals"; + } + + organization + "Internet Engineering Task Force (IETF) CCAMP WG"; + contact + " + ID-draft editor: + Haomian Zheng (zhenghaomian@huawei.com); + Aihua Guo (aihuaguo.ietf@gmail.com); + Italo Busi (italo.busi@huawei.com); + Anton Snitser (antons@sedonasys.com); + Francesco Lazzeri (francesco.lazzeri@ericsson.com); + Yunbin Xu (xuyunbin@caict.ac.cn); + Yang Zhao (zhaoyangyjy@chinamobile.com); + Xufeng Liu (Xufeng_Liu@jabil.com); + Giuseppe Fioccola (giuseppe.fioccola@huawei.com); + Chaode Yu (yuchaode@huawei.com); + "; + + description + "This module defines a YANG data model for describing + transport network client services. The model fully conforms + to the Network Management Datastore Architecture (NMDA). + + Copyright (c) 2021 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices."; + revision 2023-10-23 { + description + "version -04 as a WG document"; + reference + "draft-ietf-ccamp-client-signal-yang"; + } + + /* + * Groupings + */ + grouping client-svc-access-parameters { + description + "Transport network client signals access parameters"; + + leaf access-node-id { + type te-types:te-node-id; + description + "The identifier of the access node in the TE topology."; + } + + leaf access-node-uri { + type nw:node-id; + description + "The identifier of the access node in the network."; + } + + leaf access-ltp-id { + type te-types:te-tp-id; + description + "The TE link termination point identifier in TE topology, used + together with access-node-id to identify the access LTP."; + } + + leaf access-ltp-uri { + type nt:tp-id; + description + "The link termination point identifier in network topology, + used together with access-node-uri to identify the access LTP"; + } + + leaf client-signal { + type identityref { + base layer1-types:client-signal; + } + description + "Identify the client signal type associated with this port"; + } + + } + + grouping pm-state-grouping { + leaf latency { + description "latency value of the E2E client signal service"; + type uint32; + units microsecond; + } + } + + grouping error-info-grouping { + leaf error-code { + description "error code"; + type uint16; + } + + leaf error-description { + description "detail message of error"; + type string; + } + + leaf error-timestamp { + description "the date and time error is happened"; + type yang:date-and-time; + } + } + + grouping alarm-shreshold-grouping { + leaf latency-threshold { + description "a threshold for the E2E client signal service's + latency. Once the latency value exceed this threshold, an alarm + should be triggered."; + type uint32; + units microsecond; + } + } + + grouping client-svc-tunnel-parameters { + description + "Transport network client signals tunnel parameters"; + + leaf tunnel-name { + type string; + description + "TE tunnel instance name."; + } + } + + grouping client-svc-instance-config { + description + "Configuration parameters for client services."; + leaf client-svc-name { + type string; + description + "Identifier of the p2p transport network client signals."; + } + + leaf client-svc-title { + type string; + description + "Name of the p2p transport network client signals."; + } + + leaf user-label { + type string; + description + "Alias of the p2p transport network client signals."; + } + + leaf client-svc-descr { + type string; + description + "Description of the transport network client signals."; + } + + leaf client-svc-customer { + type string; + description + "Customer of the transport network client signals."; + } + + container resilience { + description "Place holder for resilience functionalities"; + } + + uses te-types:te-topology-identifier; + + leaf admin-status { + type identityref { + base te-types:tunnel-admin-state-type; + } + default te-types:tunnel-admin-state-up; + description "Client signals administrative state."; + } + + container src-access-ports { + description + "Source access port of a client signal."; + uses client-svc-access-parameters; + } + container dst-access-ports { + description + "Destination access port of a client signal."; + uses client-svc-access-parameters; + } + + container pm-state { + config false; + description "PM data of E2E client signal"; + uses pm-state-grouping; + } + + container error-info { + config false; + description "error messages of configuration"; + uses error-info-grouping; + } + + container alarm-shreshold { + description "threshold configuration for the E2E client signal"; + uses alarm-shreshold-grouping; + } + + leaf direction { + type identityref { + base clntsvc-types:direction; + } + description "Uni-dir or Bi-dir for the client signal."; + } + + list svc-tunnels { + key tunnel-name; + description + "List of the TE Tunnels supporting the client signal."; + uses client-svc-tunnel-parameters; + } + } + + grouping client-svc-instance-state { + description + "State parameters for client services."; + leaf operational-state { + type identityref { + base te-types:tunnel-state-type; + } + config false; + description "Client signal operational state."; + } + leaf provisioning-state { + type identityref { + base te-types:lsp-state-type; + } + config false; + description "Client signal provisioning state."; + } + leaf creation-time { + type yang:date-and-time; + config false; + description "The time of the client signal be created."; + } + leaf last-updated-time { + type yang:date-and-time; + config false; + description "The time of the client signal's latest update."; + } + leaf created-by { + type string; + config false; + description + "The client signal is created by whom, + can be a system or staff ID."; + } + leaf last-updated-by { + type string; + config false; + description + "The client signal is last updated by whom, + can be a system or staff ID."; + } + leaf owned-by { + type string; + config false; + description + "The client signal is owned by whom, + can be a system ID."; + } + } + + /* + * Data nodes + */ + + container client-svc { + description + "Transport client services."; + + list client-svc-instances { + key client-svc-name; + description + "The list of p2p transport client service instances"; + + uses client-svc-instance-config; + uses client-svc-instance-state; + } + } + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-svc-types@2023-10-23.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-svc-types@2023-10-23.yang new file mode 100644 index 000000000..60db5633a --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-trans-client-svc-types@2023-10-23.yang @@ -0,0 +1,63 @@ + module ietf-trans-client-svc-types { + namespace "urn:ietf:params:xml:ns:yang:ietf-trans-client-svc-types"; + prefix "clntsvc-types"; + + organization + "Internet Engineering Task Force (IETF) CCAMP WG"; + contact + " + ID-draft editor: + Haomian Zheng (zhenghaomian@huawei.com); + Aihua Guo (aihuaguo.ietf@gmail.com); + Italo Busi (italo.busi@huawei.com); + Anton Snitser (antons@sedonasys.com); + Francesco Lazzeri (francesco.lazzeri@ericsson.com); + Yunbin Xu (xuyunbin@caict.ac.cn); + Yang Zhao (zhaoyangyjy@chinamobile.com); + Xufeng Liu (Xufeng_Liu@jabil.com); + Giuseppe Fioccola (giuseppe.fioccola@huawei.com); + Chaode Yu (yuchaode@huawei.com); + "; + + description + "This module defines a YANG data model for describing + transport network client types. The model fully conforms + to the Network Management Datastore Architecture (NMDA). + + Copyright (c) 2019 IETF Trust and the persons + identified as authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + This version of this YANG module is part of RFC XXXX; see + the RFC itself for full legal notices."; + + revision 2023-10-23 { + description + "version -01 as a WG document"; + reference + "draft-ietf-ccamp-client-signal-yang"; + } + + identity direction { + description + "Direction information of Client Signal."; + } + + identity bidirectional { + base direction; + description + "Client Signal is bi-directional."; + } + + identity unidirectional { + base direction; + description + "Client Signal is uni-directional."; + } + + } diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-vpn-common@2022-02-11.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-vpn-common@2022-02-11.yang new file mode 100644 index 000000000..7205a1fdf --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-vpn-common@2022-02-11.yang @@ -0,0 +1,2251 @@ +module ietf-vpn-common { + yang-version 1.1; + namespace "urn:ietf:params:xml:ns:yang:ietf-vpn-common"; + prefix vpn-common; + + import ietf-netconf-acm { + prefix nacm; + reference + "RFC 8341: Network Configuration Access Control Model"; + } + import ietf-routing-types { + prefix rt-types; + reference + "RFC 8294: Common YANG Data Types for the Routing Area"; + } + import ietf-yang-types { + prefix yang; + reference + "RFC 6991: Common YANG Data Types, Section 3"; + } + import ietf-packet-fields { + prefix packet-fields; + reference + "RFC 8519: YANG Data Model for Network Access + Control Lists (ACLs)"; + } + + organization + "IETF OPSAWG (Operations and Management Area Working Group)"; + contact + "WG Web: + WG List: + + Editor: Mohamed Boucadair + + Author: Samier Barguil + + Editor: Oscar Gonzalez de Dios + + Author: Qin Wu + "; + description + "This YANG module defines a common module that is meant + to be reused by various VPN-related modules (e.g., the + Layer 3 VPN Service Model (L3SM), the Layer 2 VPN Service + Model (L2SM), the Layer 3 VPN Network Model (L3NM), and + the Layer 2 VPN Network Model (L2NM)). + + Copyright (c) 2022 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject to + the license terms contained in, the Revised BSD License set + forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (https://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 9181; see the + RFC itself for full legal notices."; + + revision 2022-02-11 { + description + "Initial revision."; + reference + "RFC 9181: A Common YANG Data Model for Layer 2 and Layer 3 + VPNs"; + } + + /******** Collection of VPN-related features ********/ + /* + * Features related to encapsulation schemes + */ + + feature dot1q { + description + "Indicates support for dot1Q encapsulation."; + reference + "IEEE Std 802.1Q: IEEE Standard for Local and Metropolitan + Area Networks--Bridges and Bridged + Networks"; + } + + feature qinq { + description + "Indicates support for QinQ encapsulation."; + reference + "IEEE Std 802.1ad: IEEE Standard for Local and Metropolitan + Area Networks---Virtual Bridged Local + Area Networks---Amendment 4: Provider + Bridges"; + } + + feature vxlan { + description + "Indicates support for Virtual eXtensible Local Area + Network (VXLAN) encapsulation."; + reference + "RFC 7348: Virtual eXtensible Local Area Network (VXLAN): + A Framework for Overlaying Virtualized Layer 2 + Networks over Layer 3 Networks"; + } + + feature qinany { + description + "Indicates support for QinAny encapsulation. + The outer VLAN tag is set to a specific value, but + the inner VLAN tag is set to any."; + } + + feature lag-interface { + description + "Indicates support for Link Aggregation Groups (LAGs) + between VPN network accesses."; + reference + "IEEE Std 802.1AX: IEEE Standard for Local and Metropolitan + Area Networks--Link Aggregation"; + } + + /* + * Features related to multicast + */ + + feature multicast { + description + "Indicates support for multicast capabilities in a VPN."; + reference + "RFC 6513: Multicast in MPLS/BGP IP VPNs"; + } + + feature igmp { + description + "Indicates support for the Internet Group Management + Protocol (IGMP)."; + reference + "RFC 1112: Host Extensions for IP Multicasting + RFC 2236: Internet Group Management Protocol, Version 2 + RFC 3376: Internet Group Management Protocol, Version 3"; + } + + feature mld { + description + "Indicates support for Multicast Listener Discovery (MLD)."; + reference + "RFC 2710: Multicast Listener Discovery (MLD) for IPv6 + RFC 3810: Multicast Listener Discovery Version 2 (MLDv2) + for IPv6"; + } + + feature pim { + description + "Indicates support for Protocol Independent Multicast + (PIM)."; + reference + "RFC 7761: Protocol Independent Multicast - Sparse Mode + (PIM-SM): Protocol Specification (Revised)"; + } + + /* + * Features related to address family types + */ + + feature ipv4 { + description + "Indicates IPv4 support in a VPN. That is, IPv4 traffic + can be carried in the VPN, IPv4 addresses/prefixes can + be assigned to a VPN network access, IPv4 routes can be + installed for the Customer Edge to Provider Edge (CE-PE) + link, etc."; + reference + "RFC 791: Internet Protocol"; + } + + feature ipv6 { + description + "Indicates IPv6 support in a VPN. That is, IPv6 traffic + can be carried in the VPN, IPv6 addresses/prefixes can + be assigned to a VPN network access, IPv6 routes can be + installed for the CE-PE link, etc."; + reference + "RFC 8200: Internet Protocol, Version 6 (IPv6) + Specification"; + } + + /* + * Features related to routing protocols + */ + + feature rtg-ospf { + description + "Indicates support for OSPF as the Provider Edge to + Customer Edge (PE-CE) routing protocol."; + reference + "RFC 4577: OSPF as the Provider/Customer Edge Protocol + for BGP/MPLS IP Virtual Private Networks (VPNs) + RFC 6565: OSPFv3 as a Provider Edge to Customer Edge + (PE-CE) Routing Protocol"; + } + + feature rtg-ospf-sham-link { + description + "Indicates support for OSPF sham links."; + reference + "RFC 4577: OSPF as the Provider/Customer Edge Protocol + for BGP/MPLS IP Virtual Private Networks (VPNs), + Section 4.2.7 + RFC 6565: OSPFv3 as a Provider Edge to Customer Edge + (PE-CE) Routing Protocol, Section 5"; + } + + feature rtg-bgp { + description + "Indicates support for BGP as the PE-CE routing protocol."; + reference + "RFC 4271: A Border Gateway Protocol 4 (BGP-4)"; + } + + feature rtg-rip { + description + "Indicates support for RIP as the PE-CE routing protocol."; + reference + "RFC 2453: RIP Version 2 + RFC 2080: RIPng for IPv6"; + } + + feature rtg-isis { + description + "Indicates support for IS-IS as the PE-CE routing + protocol."; + reference + "ISO10589: Information technology - Telecommunications and + information exchange between systems - + Intermediate System to Intermediate System + intra-domain routeing information exchange + protocol for use in conjunction with the protocol + for providing the connectionless-mode network + service (ISO 8473)"; + } + + feature rtg-vrrp { + description + "Indicates support for the Virtual Router Redundancy + Protocol (VRRP) in the CE-PE link."; + reference + "RFC 5798: Virtual Router Redundancy Protocol (VRRP) + Version 3 for IPv4 and IPv6"; + } + + feature bfd { + description + "Indicates support for Bidirectional Forwarding Detection + (BFD) between the CE and the PE."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD)"; + } + + /* + * Features related to VPN service constraints + */ + + feature bearer-reference { + description + "A bearer refers to properties of the CE-PE attachment that + are below Layer 3. + This feature indicates support for the bearer reference + access constraint, i.e., the reuse of a network connection + that was already ordered to the service provider apart from + the IP VPN site."; + } + + feature placement-diversity { + description + "Indicates support for placement diversity constraints in + the customer premises. An example of these constraints + may be to avoid connecting a site network access to the + same PE as a target site network access."; + } + + /* + * Features related to bandwidth and Quality of Service (QoS) + */ + + feature qos { + description + "Indicates support for Classes of Service (CoSes) in + the VPN."; + } + + feature inbound-bw { + description + "Indicates support for the inbound bandwidth in a VPN, + i.e., support for specifying the download bandwidth from + the service provider network to the VPN site. Note that + the L3SM uses 'input' to identify the same feature. + That terminology should be deprecated in favor of + the terminology defined in this module."; + } + + feature outbound-bw { + description + "Indicates support for the outbound bandwidth in a VPN, + i.e., support for specifying the upload bandwidth from + the VPN site to the service provider network. Note that + the L3SM uses 'output' to identify the same feature. + That terminology should be deprecated in favor of the + terminology defined in this module."; + } + + /* + * Features related to security and resilience + */ + + feature encryption { + description + "Indicates support for encryption in the VPN."; + } + + feature fast-reroute { + description + "Indicates support for Fast Reroute (FRR) capabilities for + a VPN site."; + } + + /* + * Features related to advanced VPN options + */ + + feature external-connectivity { + description + "Indicates support for the VPN to provide external + connectivity (e.g., Internet, private or public cloud)."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks + (VPNs), Section 11"; + } + + feature extranet-vpn { + description + "Indicates support for extranet VPNs, i.e., the capability + of a VPN to access a list of other VPNs."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks + (VPNs), Section 1.1"; + } + + feature carriers-carrier { + description + "Indicates support for Carriers' Carriers in VPNs."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks + (VPNs), Section 9"; + } + + /* + * Identities related to address families + */ + + identity address-family { + description + "Defines a type for the address family."; + } + + identity ipv4 { + base address-family; + description + "Identity for an IPv4 address family."; + } + + identity ipv6 { + base address-family; + description + "Identity for an IPv6 address family."; + } + + identity dual-stack { + base address-family; + description + "Identity for IPv4 and IPv6 address families."; + } + + /* + * Identities related to VPN topology + */ + + identity vpn-topology { + description + "Base identity of the VPN topology."; + } + + identity any-to-any { + base vpn-topology; + description + "Identity for any-to-any VPN topology. All VPN sites + can communicate with each other without any restrictions."; + } + + identity hub-spoke { + base vpn-topology; + description + "Identity for Hub-and-Spoke VPN topology. All Spokes can + communicate with Hubs only and not with each other. Hubs + can communicate with each other."; + } + + identity hub-spoke-disjoint { + base vpn-topology; + description + "Identity for Hub-and-Spoke VPN topology where Hubs cannot + communicate with each other."; + } + + identity custom { + base vpn-topology; + description + "Identity for custom VPN topologies where the role of the + nodes is not strictly Hub or Spoke. The VPN topology is + controlled by the import/export policies. The custom + topology reflects more complex VPN nodes, such as a + VPN node that acts as a Hub for certain nodes and a Spoke + for others."; + } + + /* + * Identities related to network access types + */ + + identity site-network-access-type { + description + "Base identity for site network access types."; + } + + identity point-to-point { + base site-network-access-type; + description + "Point-to-point access type."; + } + + identity multipoint { + base site-network-access-type; + description + "Multipoint access type."; + } + + identity irb { + base site-network-access-type; + description + "Integrated Routing and Bridging (IRB). + Identity for pseudowire connections."; + } + + identity loopback { + base site-network-access-type; + description + "Loopback access type."; + } + + /* + * Identities related to operational and administrative status + */ + + identity operational-status { + description + "Base identity for operational status."; + } + + identity op-up { + base operational-status; + description + "Operational status is Up/Enabled."; + } + + identity op-down { + base operational-status; + description + "Operational status is Down/Disabled."; + } + + identity op-unknown { + base operational-status; + description + "Operational status is Unknown."; + } + + identity administrative-status { + description + "Base identity for administrative status."; + } + + identity admin-up { + base administrative-status; + description + "Administrative status is Up/Enabled."; + } + + identity admin-down { + base administrative-status; + description + "Administrative status is Down/Disabled."; + } + + identity admin-testing { + base administrative-status; + description + "Administrative status is Up for testing purposes."; + } + + identity admin-pre-deployment { + base administrative-status; + description + "Administrative status reflects a pre-deployment phase, + i.e., prior to the actual deployment of a service."; + } + + /* + * Identities related to site or node roles + */ + + identity role { + description + "Base identity of a site or node role."; + } + + identity any-to-any-role { + base role; + description + "Any-to-any role."; + } + + identity spoke-role { + base role; + description + "A node or a site is acting as a Spoke."; + } + + identity hub-role { + base role; + description + "A node or a site is acting as a Hub."; + } + + identity custom-role { + base role; + description + "VPN node with a custom or complex role in the VPN. For + some sources/destinations, it can behave as a Hub, but for + others, it can act as a Spoke, depending on the configured + policy."; + } + + /* + * Identities related to VPN service constraints + */ + + identity placement-diversity { + description + "Base identity for access placement constraints."; + } + + identity bearer-diverse { + base placement-diversity; + description + "Bearer diversity. + + The bearers should not use common elements."; + } + + identity pe-diverse { + base placement-diversity; + description + "PE diversity."; + } + + identity pop-diverse { + base placement-diversity; + description + "Point of Presence (POP) diversity."; + } + + identity linecard-diverse { + base placement-diversity; + description + "Linecard diversity."; + } + + identity same-pe { + base placement-diversity; + description + "Having sites connected on the same PE."; + } + + identity same-bearer { + base placement-diversity; + description + "Having sites connected using the same bearer."; + } + + /* + * Identities related to service types + */ + + identity service-type { + description + "Base identity for service types."; + } + + identity l3vpn { + base service-type; + description + "L3VPN service."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)"; + } + + identity vpls { + base service-type; + description + "Virtual Private LAN Service (VPLS)."; + reference + "RFC 4761: Virtual Private LAN Service (VPLS) Using BGP for + Auto-Discovery and Signaling + RFC 4762: Virtual Private LAN Service (VPLS) Using Label + Distribution Protocol (LDP) Signaling"; + } + + identity vpws { + base service-type; + description + "Virtual Private Wire Service (VPWS)."; + reference + "RFC 4664: Framework for Layer 2 Virtual Private Networks + (L2VPNs), Section 3.1.1"; + } + + identity vpws-evpn { + base service-type; + description + "Ethernet VPN (EVPN) used to support VPWS."; + reference + "RFC 8214: Virtual Private Wire Service Support in + Ethernet VPN"; + } + + identity pbb-evpn { + base service-type; + description + "Provider Backbone Bridging (PBB) EVPN service."; + reference + "RFC 7623: Provider Backbone Bridging Combined with + Ethernet VPN (PBB-EVPN)"; + } + + identity mpls-evpn { + base service-type; + description + "MPLS-based EVPN service."; + reference + "RFC 7432: BGP MPLS-Based Ethernet VPN"; + } + + identity vxlan-evpn { + base service-type; + description + "VXLAN-based EVPN service."; + reference + "RFC 8365: A Network Virtualization Overlay Solution Using + Ethernet VPN (EVPN)"; + } + + /* + * Identities related to VPN signaling types + */ + + identity vpn-signaling-type { + description + "Base identity for VPN signaling types."; + } + + identity bgp-signaling { + base vpn-signaling-type; + description + "Layer 2 VPNs using BGP signaling."; + reference + "RFC 6624: Layer 2 Virtual Private Networks Using BGP for + Auto-Discovery and Signaling + RFC 7432: BGP MPLS-Based Ethernet VPN"; + } + + identity ldp-signaling { + base vpn-signaling-type; + description + "Targeted Label Distribution Protocol (LDP) signaling."; + reference + "RFC 5036: LDP Specification"; + } + + identity l2tp-signaling { + base vpn-signaling-type; + description + "Layer Two Tunneling Protocol (L2TP) signaling."; + reference + "RFC 3931: Layer Two Tunneling Protocol - Version 3 (L2TPv3)"; + } + + /* + * Identities related to routing protocols + */ + + identity routing-protocol-type { + description + "Base identity for routing protocol types."; + } + + identity static-routing { + base routing-protocol-type; + description + "Static routing protocol."; + } + + identity bgp-routing { + if-feature "rtg-bgp"; + base routing-protocol-type; + description + "BGP routing protocol."; + reference + "RFC 4271: A Border Gateway Protocol 4 (BGP-4)"; + } + + identity ospf-routing { + if-feature "rtg-ospf"; + base routing-protocol-type; + description + "OSPF routing protocol."; + reference + "RFC 4577: OSPF as the Provider/Customer Edge Protocol + for BGP/MPLS IP Virtual Private Networks (VPNs) + RFC 6565: OSPFv3 as a Provider Edge to Customer Edge + (PE-CE) Routing Protocol"; + } + + identity rip-routing { + if-feature "rtg-rip"; + base routing-protocol-type; + description + "RIP routing protocol."; + reference + "RFC 2453: RIP Version 2 + RFC 2080: RIPng for IPv6"; + } + + identity isis-routing { + if-feature "rtg-isis"; + base routing-protocol-type; + description + "IS-IS routing protocol."; + reference + "ISO10589: Information technology - Telecommunications and + information exchange between systems - + Intermediate System to Intermediate System + intra-domain routeing information exchange + protocol for use in conjunction with the protocol + for providing the connectionless-mode network + service (ISO 8473)"; + } + + identity vrrp-routing { + if-feature "rtg-vrrp"; + base routing-protocol-type; + description + "VRRP protocol. + + This is to be used when LANs are directly connected to + PEs."; + reference + "RFC 5798: Virtual Router Redundancy Protocol (VRRP) + Version 3 for IPv4 and IPv6"; + } + + identity direct-routing { + base routing-protocol-type; + description + "Direct routing. + + This is to be used when LANs are directly connected to PEs + and must be advertised in the VPN."; + } + + identity any-routing { + base routing-protocol-type; + description + "Any routing protocol. + + For example, this can be used to set policies that apply + to any routing protocol in place."; + } + + identity isis-level { + if-feature "rtg-isis"; + description + "Base identity for the IS-IS level."; + reference + "ISO10589: Information technology - Telecommunications and + information exchange between systems - + Intermediate System to Intermediate System + intra-domain routeing information exchange + protocol for use in conjunction with the protocol + for providing the connectionless-mode network + service (ISO 8473)"; + } + + identity level-1 { + base isis-level; + description + "IS-IS Level 1."; + } + + identity level-2 { + base isis-level; + description + "IS-IS Level 2."; + } + + identity level-1-2 { + base isis-level; + description + "IS-IS Levels 1 and 2."; + } + + identity bfd-session-type { + if-feature "bfd"; + description + "Base identity for the BFD session type."; + } + + identity classic-bfd { + base bfd-session-type; + description + "Classic BFD."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD)"; + } + + identity s-bfd { + base bfd-session-type; + description + "Seamless BFD."; + reference + "RFC 7880: Seamless Bidirectional Forwarding Detection + (S-BFD)"; + } + + /* + * Identities related to route import and export policies + */ + + identity ie-type { + description + "Base identity for import/export routing profiles. + These profiles can be reused between VPN nodes."; + } + + identity import { + base ie-type; + description + "Import routing profile."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks + (VPNs), Section 4.3.1"; + } + + identity export { + base ie-type; + description + "Export routing profile."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks + (VPNs), Section 4.3.1"; + } + + identity import-export { + base ie-type; + description + "Import/export routing profile."; + } + + /* + * Identities related to bandwidth and QoS + */ + + identity bw-direction { + description + "Base identity for the bandwidth direction."; + } + + identity inbound-bw { + if-feature "inbound-bw"; + base bw-direction; + description + "Inbound bandwidth."; + } + + identity outbound-bw { + if-feature "outbound-bw"; + base bw-direction; + description + "Outbound bandwidth."; + } + + identity bw-type { + description + "Base identity for the bandwidth type."; + } + + identity bw-per-cos { + if-feature "qos"; + base bw-type; + description + "The bandwidth is per CoS."; + } + + identity bw-per-port { + base bw-type; + description + "The bandwidth is per a given site network access."; + } + + identity bw-per-site { + base bw-type; + description + "The bandwidth is per site. It is applicable to all the + site network accesses within a site."; + } + + identity bw-per-service { + base bw-type; + description + "The bandwidth is per VPN service."; + } + + identity qos-profile-direction { + if-feature "qos"; + description + "Base identity for the QoS profile direction."; + } + + identity site-to-wan { + base qos-profile-direction; + description + "From the customer site to the provider's network. + This is typically the CE-to-PE direction."; + } + + identity wan-to-site { + base qos-profile-direction; + description + "From the provider's network to the customer site. + This is typically the PE-to-CE direction."; + } + + identity both { + base qos-profile-direction; + description + "Both the WAN-to-site direction and the site-to-WAN + direction."; + } + + /* + * Identities related to underlay transport instances + */ + + identity transport-instance-type { + description + "Base identity for underlay transport instance types."; + } + + identity virtual-network { + base transport-instance-type; + description + "Virtual network."; + reference + "RFC 8453: Framework for Abstraction and Control of TE + Networks (ACTN)"; + } + + identity enhanced-vpn { + base transport-instance-type; + description + "Enhanced VPN (VPN+). VPN+ is an approach that is + based on existing VPN and Traffic Engineering (TE) + technologies but adds characteristics that specific + services require over and above classical VPNs."; + reference + "draft-ietf-teas-enhanced-vpn-09: + A Framework for Enhanced Virtual Private Network + (VPN+) Services"; + } + + identity ietf-network-slice { + base transport-instance-type; + description + "IETF network slice. An IETF network slice + is a logical network topology connecting a number of + endpoints using a set of shared or dedicated network + resources that are used to satisfy specific service + objectives."; + reference + "draft-ietf-teas-ietf-network-slices-05: + Framework for IETF Network Slices"; + } + + /* + * Identities related to protocol types. These types are + * typically used to identify the underlay transport. + */ + + identity protocol-type { + description + "Base identity for protocol types."; + } + + identity ip-in-ip { + base protocol-type; + description + "Transport is based on IP in IP."; + reference + "RFC 2003: IP Encapsulation within IP + RFC 2473: Generic Packet Tunneling in IPv6 Specification"; + } + + identity ip-in-ipv4 { + base ip-in-ip; + description + "Transport is based on IP over IPv4."; + reference + "RFC 2003: IP Encapsulation within IP"; + } + + identity ip-in-ipv6 { + base ip-in-ip; + description + "Transport is based on IP over IPv6."; + reference + "RFC 2473: Generic Packet Tunneling in IPv6 Specification"; + } + + identity gre { + base protocol-type; + description + "Transport is based on Generic Routing Encapsulation + (GRE)."; + reference + "RFC 1701: Generic Routing Encapsulation (GRE) + RFC 1702: Generic Routing Encapsulation over IPv4 networks + RFC 7676: IPv6 Support for Generic Routing Encapsulation + (GRE)"; + } + + identity gre-v4 { + base gre; + description + "Transport is based on GRE over IPv4."; + reference + "RFC 1702: Generic Routing Encapsulation over IPv4 + networks"; + } + + identity gre-v6 { + base gre; + description + "Transport is based on GRE over IPv6."; + reference + "RFC 7676: IPv6 Support for Generic Routing Encapsulation + (GRE)"; + } + + identity vxlan-trans { + base protocol-type; + description + "Transport is based on VXLANs."; + reference + "RFC 7348: Virtual eXtensible Local Area Network (VXLAN): + A Framework for Overlaying Virtualized Layer 2 + Networks over Layer 3 Networks"; + } + + identity geneve { + base protocol-type; + description + "Transport is based on Generic Network Virtualization + Encapsulation (Geneve)."; + reference + "RFC 8926: Geneve: Generic Network Virtualization + Encapsulation"; + } + + identity ldp { + base protocol-type; + description + "Transport is based on LDP."; + reference + "RFC 5036: LDP Specification"; + } + + identity mpls-in-udp { + base protocol-type; + description + "Transport is based on MPLS in UDP."; + reference + "RFC 7510: Encapsulating MPLS in UDP"; + } + + identity sr { + base protocol-type; + description + "Transport is based on Segment Routing (SR)."; + reference + "RFC 8660: Segment Routing with the MPLS Data Plane + RFC 8663: MPLS Segment Routing over IP + RFC 8754: IPv6 Segment Routing Header (SRH)"; + } + + identity sr-mpls { + base sr; + description + "Transport is based on SR with the MPLS data plane."; + reference + "RFC 8660: Segment Routing with the MPLS Data Plane"; + } + + identity srv6 { + base sr; + description + "Transport is based on SR over IPv6."; + reference + "RFC 8754: IPv6 Segment Routing Header (SRH)"; + } + + identity sr-mpls-over-ip { + base sr; + description + "Transport is based on SR over MPLS over IP."; + reference + "RFC 8663: MPLS Segment Routing over IP"; + } + + identity rsvp-te { + base protocol-type; + description + "Transport setup relies upon RSVP-TE."; + reference + "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels"; + } + + identity bgp-lu { + base protocol-type; + description + "Transport setup relies upon BGP-based labeled prefixes."; + reference + "RFC 8277: Using BGP to Bind MPLS Labels to Address Prefixes"; + } + + identity unknown { + base protocol-type; + description + "Unknown protocol type."; + } + + /* + * Identities related to encapsulation types + */ + + identity encapsulation-type { + description + "Base identity for encapsulation types."; + } + + identity priority-tagged { + base encapsulation-type; + description + "Priority-tagged interface."; + } + + identity dot1q { + if-feature "dot1q"; + base encapsulation-type; + description + "dot1Q encapsulation."; + } + + identity qinq { + if-feature "qinq"; + base encapsulation-type; + description + "QinQ encapsulation."; + } + + identity qinany { + if-feature "qinany"; + base encapsulation-type; + description + "QinAny encapsulation."; + } + + identity vxlan { + if-feature "vxlan"; + base encapsulation-type; + description + "VXLAN encapsulation."; + } + + identity ethernet-type { + base encapsulation-type; + description + "Ethernet encapsulation type."; + } + + identity vlan-type { + base encapsulation-type; + description + "VLAN encapsulation type."; + } + + identity untagged-int { + base encapsulation-type; + description + "Untagged interface type."; + } + + identity tagged-int { + base encapsulation-type; + description + "Tagged interface type."; + } + + identity lag-int { + if-feature "lag-interface"; + base encapsulation-type; + description + "LAG interface type."; + } + + /* + * Identities related to VLAN tags + */ + + identity tag-type { + description + "Base identity for VLAN tag types."; + } + + identity c-vlan { + base tag-type; + description + "Indicates a Customer VLAN (C-VLAN) tag, normally using + the 0x8100 Ethertype."; + } + + identity s-vlan { + base tag-type; + description + "Indicates a Service VLAN (S-VLAN) tag."; + } + + identity s-c-vlan { + base tag-type; + description + "Uses both an S-VLAN tag and a C-VLAN tag."; + } + + /* + * Identities related to VXLANs + */ + + identity vxlan-peer-mode { + if-feature "vxlan"; + description + "Base identity for VXLAN peer modes."; + } + + identity static-mode { + base vxlan-peer-mode; + description + "VXLAN access in the static mode."; + } + + identity bgp-mode { + base vxlan-peer-mode; + description + "VXLAN access by BGP EVPN learning."; + } + + /* + * Identities related to multicast + */ + + identity multicast-gp-address-mapping { + if-feature "multicast"; + description + "Base identity for multicast group mapping types."; + } + + identity static-mapping { + base multicast-gp-address-mapping; + description + "Static mapping, i.e., an interface is attached to the + multicast group as a static member."; + } + + identity dynamic-mapping { + base multicast-gp-address-mapping; + description + "Dynamic mapping, i.e., an interface is added to the + multicast group as a result of snooping."; + } + + identity multicast-tree-type { + if-feature "multicast"; + description + "Base identity for multicast tree types."; + } + + identity ssm-tree-type { + base multicast-tree-type; + description + "Source-Specific Multicast (SSM) tree type."; + } + + identity asm-tree-type { + base multicast-tree-type; + description + "Any-Source Multicast (ASM) tree type."; + } + + identity bidir-tree-type { + base multicast-tree-type; + description + "Bidirectional tree type."; + } + + identity multicast-rp-discovery-type { + if-feature "multicast"; + description + "Base identity for Rendezvous Point (RP) discovery types."; + } + + identity auto-rp { + base multicast-rp-discovery-type; + description + "Auto-RP discovery type."; + } + + identity static-rp { + base multicast-rp-discovery-type; + description + "Static type."; + } + + identity bsr-rp { + base multicast-rp-discovery-type; + description + "Bootstrap Router (BSR) discovery type."; + } + + identity group-management-protocol { + if-feature "multicast"; + description + "Base identity for multicast group management protocols."; + } + + identity igmp-proto { + base group-management-protocol; + description + "IGMP."; + reference + "RFC 1112: Host Extensions for IP Multicasting + RFC 2236: Internet Group Management Protocol, Version 2 + RFC 3376: Internet Group Management Protocol, Version 3"; + } + + identity mld-proto { + base group-management-protocol; + description + "MLD."; + reference + "RFC 2710: Multicast Listener Discovery (MLD) for IPv6 + RFC 3810: Multicast Listener Discovery Version 2 (MLDv2) + for IPv6"; + } + + identity pim-proto { + if-feature "pim"; + base routing-protocol-type; + description + "PIM."; + reference + "RFC 7761: Protocol Independent Multicast - Sparse Mode + (PIM-SM): Protocol Specification (Revised)"; + } + + identity igmp-version { + if-feature "igmp"; + description + "Base identity for indicating the IGMP version."; + } + + identity igmpv1 { + base igmp-version; + description + "IGMPv1."; + reference + "RFC 1112: Host Extensions for IP Multicasting"; + } + + identity igmpv2 { + base igmp-version; + description + "IGMPv2."; + reference + "RFC 2236: Internet Group Management Protocol, Version 2"; + } + + identity igmpv3 { + base igmp-version; + description + "IGMPv3."; + reference + "RFC 3376: Internet Group Management Protocol, Version 3"; + } + + identity mld-version { + if-feature "mld"; + description + "Base identity for indicating the MLD version."; + } + + identity mldv1 { + base mld-version; + description + "MLDv1."; + reference + "RFC 2710: Multicast Listener Discovery (MLD) for IPv6"; + } + + identity mldv2 { + base mld-version; + description + "MLDv2."; + reference + "RFC 3810: Multicast Listener Discovery Version 2 (MLDv2) + for IPv6"; + } + + /* + * Identities related to traffic types + */ + + identity tf-type { + description + "Base identity for traffic types."; + } + + identity multicast-traffic { + base tf-type; + description + "Multicast traffic."; + } + + identity broadcast-traffic { + base tf-type; + description + "Broadcast traffic."; + } + + identity unknown-unicast-traffic { + base tf-type; + description + "Unknown unicast traffic."; + } + + /* + * Identities related to customer applications + */ + + identity customer-application { + description + "Base identity for customer applications."; + } + + identity web { + base customer-application; + description + "Web applications (e.g., HTTP, HTTPS)."; + } + + identity mail { + base customer-application; + description + "Mail application."; + } + + identity file-transfer { + base customer-application; + description + "File transfer application (e.g., FTP, Secure FTP (SFTP))."; + } + + identity database { + base customer-application; + description + "Database application."; + } + + identity social { + base customer-application; + description + "Social-network application."; + } + + identity games { + base customer-application; + description + "Gaming application."; + } + + identity p2p { + base customer-application; + description + "Peer-to-peer application."; + } + + identity network-management { + base customer-application; + description + "Management application (e.g., Telnet, syslog, SNMP)."; + } + + identity voice { + base customer-application; + description + "Voice application."; + } + + identity video { + base customer-application; + description + "Video-conference application."; + } + + identity embb { + base customer-application; + description + "Enhanced Mobile Broadband (eMBB) application. + Note that eMBB applications demand network performance + with a wide variety of such characteristics as data rate, + latency, loss rate, reliability, and many other + parameters."; + } + + identity urllc { + base customer-application; + description + "Ultra-Reliable and Low Latency Communications (URLLC) + application. Note that URLLC applications demand + network performance with a wide variety of such + characteristics as latency, reliability, and many other + parameters."; + } + + identity mmtc { + base customer-application; + description + "Massive Machine Type Communications (mMTC) application. + Note that mMTC applications demand network performance + with a wide variety of such characteristics as data rate, + latency, loss rate, reliability, and many other + parameters."; + } + + /* + * Identities related to service bundling + */ + + identity bundling-type { + description + "The base identity for the bundling type. It supports a + subset or all Customer Edge VLAN IDs (CE-VLAN IDs) + associated with an L2VPN service."; + } + + identity multi-svc-bundling { + base bundling-type; + description + "Multi-service bundling, i.e., multiple CE-VLAN IDs + can be associated with an L2VPN service at a site."; + } + + identity one2one-bundling { + base bundling-type; + description + "One-to-one service bundling, i.e., each L2VPN can + be associated with only one CE-VLAN ID at a site."; + } + + identity all2one-bundling { + base bundling-type; + description + "All-to-one bundling, i.e., all CE-VLAN IDs are mapped + to one L2VPN service."; + } + + /* + * Identities related to Ethernet services + */ + + identity control-mode { + description + "Base identity for the type of control mode used with the + Layer 2 Control Protocol (L2CP)."; + } + + identity peer { + base control-mode; + description + "'peer' mode, i.e., participate in the protocol towards + the CE. Peering is common for the Link Aggregation Control + Protocol (LACP) and the Ethernet Local Management Interface + (E-LMI) and, occasionally, for the Link Layer Discovery + Protocol (LLDP). For VPLSs and VPWSs, the subscriber can + also request that the peer service provider enable + spanning tree."; + } + + identity tunnel { + base control-mode; + description + "'tunnel' mode, i.e., pass to the egress or destination + site. For Ethernet Private Lines (EPLs), the expectation + is that L2CP frames are tunneled."; + } + + identity discard { + base control-mode; + description + "'Discard' mode, i.e., discard the frame."; + } + + identity neg-mode { + description + "Base identity for the type of negotiation mode."; + } + + identity full-duplex { + base neg-mode; + description + "Full-duplex negotiation mode."; + } + + identity auto-neg { + base neg-mode; + description + "Auto-negotiation mode."; + } + + /******** VPN-related type ********/ + + typedef vpn-id { + type string; + description + "Defines an identifier that is used with a VPN module. + For example, this can be a service identifier, a node + identifier, etc."; + } + + /******* VPN-related reusable groupings *******/ + + grouping vpn-description { + description + "Provides common VPN information."; + leaf vpn-id { + type vpn-common:vpn-id; + description + "A VPN identifier that uniquely identifies a VPN. + This identifier has a local meaning, e.g., within + a service provider network."; + } + leaf vpn-name { + type string; + description + "Used to associate a name with the service + in order to facilitate the identification of + the service."; + } + leaf vpn-description { + type string; + description + "Textual description of a VPN."; + } + leaf customer-name { + type string; + description + "Name of the customer that actually uses the VPN."; + } + } + + grouping vpn-profile-cfg { + description + "Grouping for VPN profile configuration."; + container valid-provider-identifiers { + description + "Container for valid provider profile identifiers."; + list external-connectivity-identifier { + if-feature "external-connectivity"; + key "id"; + description + "List of profile identifiers that uniquely identify + profiles governing how external connectivity is + provided to a VPN. A profile indicates the type of + external connectivity (Internet, cloud, etc.), the + sites/nodes that are associated with a connectivity + profile, etc. A profile can also indicate filtering + rules and/or address translation rules. Such features + may involve PE, P, or dedicated nodes as a function + of the deployment."; + leaf id { + type string; + description + "Identification of an external connectivity profile. + The profile only has significance within the service + provider's administrative domain."; + } + } + list encryption-profile-identifier { + key "id"; + description + "List of encryption profile identifiers."; + leaf id { + type string; + description + "Identification of the encryption profile to be used. + The profile only has significance within the service + provider's administrative domain."; + } + } + list qos-profile-identifier { + key "id"; + description + "List of QoS profile identifiers."; + leaf id { + type string; + description + "Identification of the QoS profile to be used. The + profile only has significance within the service + provider's administrative domain."; + } + } + list bfd-profile-identifier { + key "id"; + description + "List of BFD profile identifiers."; + leaf id { + type string; + description + "Identification of the BFD profile to be used. The + profile only has significance within the service + provider's administrative domain."; + } + } + list forwarding-profile-identifier { + key "id"; + description + "List of forwarding profile identifiers."; + leaf id { + type string; + description + "Identification of the forwarding profile to be used. + The profile only has significance within the service + provider's administrative domain."; + } + } + list routing-profile-identifier { + key "id"; + description + "List of routing profile identifiers."; + leaf id { + type string; + description + "Identification of the routing profile to be used by + the routing protocols within sites, VPN network + accesses, or VPN nodes for referring to VRF's + import/export policies. + + The profile only has significance within the service + provider's administrative domain."; + } + } + nacm:default-deny-write; + } + } + + grouping oper-status-timestamp { + description + "This grouping defines some operational parameters for the + service."; + leaf status { + type identityref { + base operational-status; + } + config false; + description + "Operational status."; + } + leaf last-change { + type yang:date-and-time; + config false; + description + "Indicates the actual date and time of the service status + change."; + } + } + + grouping service-status { + description + "Service status grouping."; + container status { + description + "Service status."; + container admin-status { + description + "Administrative service status."; + leaf status { + type identityref { + base administrative-status; + } + description + "Administrative service status."; + } + leaf last-change { + type yang:date-and-time; + description + "Indicates the actual date and time of the service + status change."; + } + } + container oper-status { + config false; + description + "Operational service status."; + uses oper-status-timestamp; + } + } + } + + grouping underlay-transport { + description + "This grouping defines the type of underlay transport for + the VPN service or how that underlay is set. It can + include an identifier for an abstract transport instance to + which the VPN is grafted or indicate a technical + implementation that is expressed as an ordered list of + protocols."; + choice type { + description + "A choice based on the type of underlay transport + constraints."; + case abstract { + description + "Indicates that the transport constraint is an abstract + concept."; + leaf transport-instance-id { + type string; + description + "An optional identifier of the abstract transport + instance."; + } + leaf instance-type { + type identityref { + base transport-instance-type; + } + description + "Indicates a transport instance type. For example, + it can be a VPN+, an IETF network slice, a virtual + network, etc."; + } + } + case protocol { + description + "Indicates a list of protocols."; + leaf-list protocol { + type identityref { + base protocol-type; + } + ordered-by user; + description + "A client-ordered list of transport protocols."; + } + } + } + } + + grouping vpn-route-targets { + description + "A grouping that specifies Route Target (RT) import/export + rules used in a BGP-enabled VPN."; + reference + "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs) + RFC 4664: Framework for Layer 2 Virtual Private Networks + (L2VPNs)"; + list vpn-target { + key "id"; + description + "RTs. AND/OR operations may be defined based on the + assigned RTs."; + leaf id { + type uint8; + description + "Identifies each VPN target."; + } + list route-targets { + key "route-target"; + description + "List of RTs."; + leaf route-target { + type rt-types:route-target; + description + "Conveys an RT value."; + } + } + leaf route-target-type { + type rt-types:route-target-type; + mandatory true; + description + "Import/export type of the RT."; + } + } + container vpn-policies { + description + "VPN service policies. 'vpn-policies' contains references + to the import and export policies to be associated with + the VPN service."; + leaf import-policy { + type string; + description + "Identifies the import policy."; + } + leaf export-policy { + type string; + description + "Identifies the export policy."; + } + } + } + + grouping route-distinguisher { + description + "Grouping for Route Distinguishers (RDs)."; + choice rd-choice { + description + "RD choice between several options for providing the RD + value."; + case directly-assigned { + description + "Explicitly assigns an RD value."; + leaf rd { + type rt-types:route-distinguisher; + description + "Indicates an RD value that is explicitly assigned."; + } + } + case directly-assigned-suffix { + description + "The value of the Assigned Number subfield of the RD. + The Administrator subfield of the RD will be + based on other configuration information such as the + Router ID or Autonomous System Number (ASN)."; + leaf rd-suffix { + type uint16; + description + "Indicates the value of the Assigned Number + subfield that is explicitly assigned."; + } + } + case auto-assigned { + description + "The RD is auto-assigned."; + container rd-auto { + description + "The RD is auto-assigned."; + choice auto-mode { + description + "Indicates the auto-assignment mode. The RD can be + automatically assigned with or without + indicating a pool from which the RD should be + taken. + + For both cases, the server will auto-assign an RD + value 'auto-assigned-rd' and use that value + operationally."; + case from-pool { + leaf rd-pool-name { + type string; + description + "The auto-assignment will be made from the pool + identified by 'rd-pool-name'."; + } + } + case full-auto { + leaf auto { + type empty; + description + "Indicates that an RD is fully auto-assigned."; + } + } + } + leaf auto-assigned-rd { + type rt-types:route-distinguisher; + config false; + description + "The value of the auto-assigned RD."; + } + } + } + case auto-assigned-suffix { + description + "The value of the Assigned Number subfield will be + auto-assigned. The Administrator subfield will be + based on other configuration information such as the + Router ID or ASN."; + container rd-auto-suffix { + description + "The Assigned Number subfield is auto-assigned."; + choice auto-mode { + description + "Indicates the auto-assignment mode of the + Assigned Number subfield. This number can be + automatically assigned with or without indicating a + pool from which the value should be taken. + + For both cases, the server will auto-assign + 'auto-assigned-rd-suffix' and use that value to + build the RD that will be used operationally."; + case from-pool { + leaf rd-pool-name { + type string; + description + "The assignment will be made from the pool + identified by 'rd-pool-name'."; + } + } + case full-auto { + leaf auto { + type empty; + description + "Indicates that the Assigned Number subfield is + fully auto-assigned."; + } + } + } + leaf auto-assigned-rd-suffix { + type uint16; + config false; + description + "Includes the value of the Assigned Number subfield + that is auto-assigned."; + } + } + } + case no-rd { + description + "Uses the 'empty' type to indicate that the RD has no + value and is not to be auto-assigned."; + leaf no-rd { + type empty; + description + "No RD is assigned."; + } + } + } + } + + grouping vpn-components-group { + description + "Grouping definition to assign group IDs to associate + VPN nodes, sites, or network accesses."; + container groups { + description + "Lists the groups to which a VPN node, a site, or a + network access belongs."; + list group { + key "group-id"; + description + "List of group IDs."; + leaf group-id { + type string; + description + "The group ID to which a VPN node, a site, or a + network access belongs."; + } + } + } + } + + grouping placement-constraints { + description + "Constraints related to placement of a network access."; + list constraint { + key "constraint-type"; + description + "List of constraints."; + leaf constraint-type { + type identityref { + base placement-diversity; + } + description + "Diversity constraint type."; + } + container target { + description + "The constraint will apply against this list of + groups."; + choice target-flavor { + description + "Choice for the group definition."; + case id { + list group { + key "group-id"; + description + "List of groups."; + leaf group-id { + type string; + description + "The constraint will apply against this + particular group ID."; + } + } + } + case all-accesses { + leaf all-other-accesses { + type empty; + description + "The constraint will apply against all other + network accesses of a site."; + } + } + case all-groups { + leaf all-other-groups { + type empty; + description + "The constraint will apply against all other + groups managed by the customer."; + } + } + } + } + } + } + + grouping ports { + description + "Choice of specifying source or destination port numbers."; + choice source-port { + description + "Choice of specifying the source port or referring to a + group of source port numbers."; + container source-port-range-or-operator { + description + "Source port definition."; + uses packet-fields:port-range-or-operator; + } + } + choice destination-port { + description + "Choice of specifying a destination port or referring to a + group of destination port numbers."; + container destination-port-range-or-operator { + description + "Destination port definition."; + uses packet-fields:port-range-or-operator; + } + } + } + + grouping qos-classification-policy { + description + "Configuration of the traffic classification policy."; + list rule { + key "id"; + ordered-by user; + description + "List of marking rules."; + leaf id { + type string; + description + "An identifier of the QoS classification policy rule."; + } + choice match-type { + default "match-flow"; + description + "Choice for classification."; + case match-flow { + choice l3 { + description + "Either IPv4 or IPv6."; + container ipv4 { + description + "Rule set that matches the IPv4 header."; + uses packet-fields:acl-ip-header-fields; + uses packet-fields:acl-ipv4-header-fields; + } + container ipv6 { + description + "Rule set that matches the IPv6 header."; + uses packet-fields:acl-ip-header-fields; + uses packet-fields:acl-ipv6-header-fields; + } + } + choice l4 { + description + "Includes Layer-4-specific information. + This version focuses on TCP and UDP."; + container tcp { + description + "Rule set that matches the TCP header."; + uses packet-fields:acl-tcp-header-fields; + uses ports; + } + container udp { + description + "Rule set that matches the UDP header."; + uses packet-fields:acl-udp-header-fields; + uses ports; + } + } + } + case match-application { + leaf match-application { + type identityref { + base customer-application; + } + description + "Defines the application to match."; + } + } + } + leaf target-class-id { + type string; + description + "Identification of the class of service. This + identifier is internal to the administration."; + } + } + } +} diff --git a/src/nbi/service/ietf_sap_topology/yang/ietf-yang-types@2013-07-15.yang b/src/nbi/service/ietf_sap_topology/yang/ietf-yang-types@2013-07-15.yang new file mode 100644 index 000000000..956562a7b --- /dev/null +++ b/src/nbi/service/ietf_sap_topology/yang/ietf-yang-types@2013-07-15.yang @@ -0,0 +1,475 @@ + module ietf-yang-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; + prefix "yang"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of counter and gauge types ***/ + + typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; + } + + typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + /*** collection of identifier-related types ***/ + + typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; + } + + typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; + } + + /*** collection of types related to date and time***/ + + typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + + (a) The date-and-time type does not allow negative years. + + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; + } + + typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + + The associated timeticks schema node must be specified + in the description of any schema node using this type. + + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of generic address types ***/ + + typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of XML-specific types ***/ + + typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; + } + + /*** collection of string types ***/ + + typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; + } + + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; + } + + typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; + } + } diff --git a/src/nbi/service/tfs_api/Resources.py b/src/nbi/service/tfs_api/Resources.py index b3fef450e..536daca8d 100644 --- a/src/nbi/service/tfs_api/Resources.py +++ b/src/nbi/service/tfs_api/Resources.py @@ -15,26 +15,54 @@ import json import logging from typing import Dict, List +import grpc from flask.json import jsonify from flask_restful import Resource, request from werkzeug.exceptions import BadRequest -from common.proto.context_pb2 import Empty, LinkTypeEnum +from common.proto.context_pb2 import Empty, LinkTypeEnum, Service, ServiceTypeEnum, ConfigActionEnum, ConfigRule +from common.proto.e2eorchestrator_pb2 import E2EOrchestratorRequest from common.tools.descriptor.Tools import format_device_custom_config_rules, format_service_custom_config_rules from common.tools.grpc.Tools import grpc_message_to_json from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient +from e2e_orchestrator.client.E2EOrchestratorClient import E2EOrchestratorClient from service.client.ServiceClient import ServiceClient from slice.client.SliceClient import SliceClient from vnt_manager.client.VNTManagerClient import VNTManagerClient + from .Tools import ( format_grpc_to_json, grpc_connection_id, grpc_context, grpc_context_id, grpc_device, grpc_device_id, grpc_link, grpc_link_id, grpc_policy_rule_id, + grpc_optical_spectrum_reservation, grpc_optical_spectrum_reservation_id, grpc_service_id, grpc_service, grpc_slice, grpc_slice_id, grpc_topology, grpc_topology_id ) LOGGER = logging.getLogger(__name__) +_GRPC_TO_HTTP_STATUS = { + grpc.StatusCode.INVALID_ARGUMENT: 400, + grpc.StatusCode.FAILED_PRECONDITION: 400, + grpc.StatusCode.NOT_FOUND: 404, + grpc.StatusCode.ALREADY_EXISTS: 409, + grpc.StatusCode.PERMISSION_DENIED: 403, + grpc.StatusCode.UNAUTHENTICATED: 401, + grpc.StatusCode.UNAVAILABLE: 503, + grpc.StatusCode.DEADLINE_EXCEEDED: 504, +} + + +def _format_grpc_error(exc : grpc.RpcError): + grpc_status = exc.code() + http_status = _GRPC_TO_HTTP_STATUS.get(grpc_status, 500) + details = exc.details() if hasattr(exc, 'details') else str(exc) + LOGGER.warning('Mapping gRPC error to HTTP status: grpc_status=%s http_status=%s details=%s', + grpc_status, http_status, details) + return { + 'error': grpc_status.name if grpc_status is not None else 'UNKNOWN', + 'message': details, + }, http_status + class _Resource(Resource): def __init__(self) -> None: @@ -345,6 +373,88 @@ class OpticalLink(_Resource): def get(self, link_uuid : str): return format_grpc_to_json(self.context_client.GetOpticalLink(grpc_link_id(link_uuid))) +class OpticalSpectrumReservations(_Resource): + def get(self, context_uuid : str): + return format_grpc_to_json( + self.context_client.ListOpticalSpectrumReservations(grpc_context_id(context_uuid)) + ) + + def post(self, context_uuid : str): + json_requests = request.get_json() + if 'reservations' in json_requests: + json_requests = json_requests['reservations'] + if isinstance(json_requests, dict): + json_requests = [json_requests] + for reservation in json_requests: + if context_uuid != reservation['reservation_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + try: + return jsonify([ + grpc_message_to_json(self.context_client.SetOpticalSpectrumReservation( + grpc_optical_spectrum_reservation(reservation) + )) + for reservation in json_requests + ]) + except grpc.RpcError as exc: + return _format_grpc_error(exc) + +class OpticalSpectrumReservation(_Resource): + def get(self, context_uuid : str, reservation_uuid : str): + return format_grpc_to_json(self.context_client.GetOpticalSpectrumReservation( + grpc_optical_spectrum_reservation_id(context_uuid, reservation_uuid) + )) + + def put(self, context_uuid : str, reservation_uuid : str): + reservation = request.get_json() + if context_uuid != reservation['reservation_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + if reservation_uuid != reservation['reservation_id']['reservation_uuid']['uuid']: + raise BadRequest('Mismatching reservation_uuid') + try: + return format_grpc_to_json(self.context_client.SetOpticalSpectrumReservation( + grpc_optical_spectrum_reservation(reservation) + )) + except grpc.RpcError as exc: + return _format_grpc_error(exc) + + def delete(self, context_uuid : str, reservation_uuid : str): + try: + return format_grpc_to_json(self.context_client.ReleaseOpticalSpectrumReservation( + grpc_optical_spectrum_reservation_id(context_uuid, reservation_uuid) + )) + except grpc.RpcError as exc: + return _format_grpc_error(exc) + +class OpticalSpectrumReservationConsume(_Resource): + def post(self, context_uuid : str, reservation_uuid : str): + reservation = request.get_json() + if reservation is None: + reservation = { + 'reservation_id': { + 'context_id': {'context_uuid': {'uuid': context_uuid}}, + 'reservation_uuid': {'uuid': reservation_uuid}, + }, + } + if context_uuid != reservation['reservation_id']['context_id']['context_uuid']['uuid']: + raise BadRequest('Mismatching context_uuid') + if reservation_uuid != reservation['reservation_id']['reservation_uuid']['uuid']: + raise BadRequest('Mismatching reservation_uuid') + try: + return format_grpc_to_json(self.context_client.ConsumeOpticalSpectrumReservation( + grpc_optical_spectrum_reservation(reservation) + )) + except grpc.RpcError as exc: + return _format_grpc_error(exc) + +class OpticalSpectrumReservationRelease(_Resource): + def post(self, context_uuid : str, reservation_uuid : str): + try: + return format_grpc_to_json(self.context_client.ReleaseOpticalSpectrumReservation( + grpc_optical_spectrum_reservation_id(context_uuid, reservation_uuid) + )) + except grpc.RpcError as exc: + return _format_grpc_error(exc) + class ConnectionIds(_Resource): def get(self, context_uuid : str, service_uuid : str): return format_grpc_to_json(self.context_client.ListConnectionIds(grpc_service_id(context_uuid, service_uuid))) @@ -368,3 +478,48 @@ class PolicyRules(_Resource): class PolicyRule(_Resource): def get(self, policy_rule_uuid : str): return format_grpc_to_json(self.context_client.GetPolicyRule(grpc_policy_rule_id(policy_rule_uuid))) + +class E2epathcomp(Resource): + def __init__(self): + super().__init__() + self.e2e_client = E2EOrchestratorClient() + + def post(self): + data = request.get_json() + LOGGER.info(f"Received E2E Optical Path Computation request: {json.dumps(data, indent=2)}") + + try: + # Construct a Service protobuf to encapsulate the intent for the E2E Orchestrator + service = Service() + service.service_id.service_uuid.uuid = "e2e-optical-service" + service.service_id.context_id.context_uuid.uuid = "admin" + service.service_type = ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY + + # Pack the original JSON payload into a config rule so E2E Orchestrator and PathComp can access it + config_rule = ConfigRule() + config_rule.action = ConfigActionEnum.CONFIGACTION_SET + config_rule.custom.resource_key = "intent" + config_rule.custom.resource_value = json.dumps(data) + service.service_config.config_rules.append(config_rule) + + req = E2EOrchestratorRequest(service=service) + + LOGGER.info("Sending request to E2E Orchestrator Compute...") + reply = self.e2e_client.Compute(req) + + reply_json = grpc_message_to_json(reply) + + # Check if there is an optical_path_result injected by PathComp + if reply.services: + for cr in reply.services[0].service_config.config_rules: + if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == "optical_path_result": + LOGGER.info("Found optical_path_result, returning it directly.") + return json.loads(cr.custom.resource_value), 200 + + LOGGER.info(f"Received reply from E2E Orchestrator: {json.dumps(reply_json)}") + # The NBI returns the standard protobuf JSON response if no custom result is found + return reply_json, 200 + + except Exception as e: + LOGGER.error(f"Error calling E2E Orchestrator: {str(e)}", exc_info=True) + return {"status": "error", "message": str(e)}, 500 diff --git a/src/nbi/service/tfs_api/Tools.py b/src/nbi/service/tfs_api/Tools.py index 390ef9b01..e11620f8e 100644 --- a/src/nbi/service/tfs_api/Tools.py +++ b/src/nbi/service/tfs_api/Tools.py @@ -16,6 +16,7 @@ from typing import Dict from flask.json import jsonify from common.proto.context_pb2 import ( ConnectionId, Context, ContextId, Device, DeviceId, Link, LinkId, + OpticalSpectrumReservation, OpticalSpectrumReservationId, ServiceId, Slice, SliceId, Topology, TopologyId, Service ) from common.proto.policy_pb2 import PolicyRule, PolicyRuleId @@ -54,6 +55,15 @@ def grpc_link_id(link_uuid): def grpc_link(json_link : Dict): return Link(**json_link) +def grpc_optical_spectrum_reservation_id(context_uuid, reservation_uuid): + return OpticalSpectrumReservationId( + context_id=json_context_id(context_uuid), + reservation_uuid={'uuid': reservation_uuid}, + ) + +def grpc_optical_spectrum_reservation(json_reservation : Dict): + return OpticalSpectrumReservation(**json_reservation) + def grpc_service_id(context_uuid, service_uuid): return ServiceId(**json_service_id(service_uuid, context_id=json_context_id(context_uuid))) diff --git a/src/nbi/service/tfs_api/__init__.py b/src/nbi/service/tfs_api/__init__.py index a33a3a525..2bcf431ec 100644 --- a/src/nbi/service/tfs_api/__init__.py +++ b/src/nbi/service/tfs_api/__init__.py @@ -20,11 +20,15 @@ from .Resources import ( DummyContexts, Link, LinkIds, Links, OpticalLink, OpticalLinks, + OpticalSpectrumReservation, OpticalSpectrumReservationConsume, + OpticalSpectrumReservationRelease, OpticalSpectrumReservations, PolicyRule, PolicyRuleIds, PolicyRules, Service, ServiceIds, Services, Slice, SliceIds, Slices, - Topologies, Topology, TopologyDetails, TopologyIds + Topologies, Topology, TopologyDetails, TopologyIds, + E2epathcomp ) + ENDPOINT_PREFIX = 'tfs_api.' URL_PREFIX = '/tfs-api' @@ -32,6 +36,7 @@ URL_PREFIX = '/tfs-api' # Use 'path' type since some identifiers might contain char '/' and Flask is unable to recognize them in 'string' type. _RESOURCES = [ # (endpoint_name, resource_class, resource_url) + ('api.e2e_path_computation', E2epathcomp, '/e2e_path_computation'), ('api.context_ids', ContextIds, '/context_ids'), ('api.contexts', Contexts, '/contexts'), ('api.dummy_contexts', DummyContexts, '/dummy_contexts'), @@ -59,6 +64,14 @@ _RESOURCES = [ ('api.link', Link, '/link/'), ('api.optical_links', OpticalLinks, '/optical_links'), ('api.optical_link', OpticalLink, '/optical_link/'), + ('api.optical_spectrum_reservations', OpticalSpectrumReservations, + '/context//optical_spectrum_reservations'), + ('api.optical_spectrum_reservation', OpticalSpectrumReservation, + '/context//optical_spectrum_reservation/'), + ('api.optical_spectrum_reservation_consume', OpticalSpectrumReservationConsume, + '/context//optical_spectrum_reservation//consume'), + ('api.optical_spectrum_reservation_release', OpticalSpectrumReservationRelease, + '/context//optical_spectrum_reservation//release'), ('api.connection_ids', ConnectionIds, '/context//service//connection_ids'), ('api.connections', Connections, '/context//service//connections'), diff --git a/src/nbi/tests/test_tfs_api.py b/src/nbi/tests/test_tfs_api.py index 25158fa2a..d4a97fa09 100644 --- a/src/nbi/tests/test_tfs_api.py +++ b/src/nbi/tests/test_tfs_api.py @@ -41,7 +41,7 @@ from nbi.service.NbiApplication import NbiApplication from .PrepareTestScenario import ( # pylint: disable=unused-import # be careful, order of symbols is important here! nbi_application, context_client, - do_rest_get_request + do_rest_delete_request, do_rest_get_request, do_rest_post_request, do_rest_put_request ) @@ -175,6 +175,170 @@ def test_rest_get_optical_link( validate_optical_link(reply) +# ----- Optical Spectrum Reservation ---------------------------------------------------------------------------------- + +def _optical_spectrum_reservation(context_uuid : str, reservation_uuid : str): + return { + 'reservation_id': { + 'context_id': {'context_uuid': {'uuid': context_uuid}}, + 'reservation_uuid': {'uuid': reservation_uuid}, + }, + 'topology_id': { + 'context_id': {'context_uuid': {'uuid': context_uuid}}, + 'topology_uuid': {'uuid': DEFAULT_TOPOLOGY_NAME}, + }, + 'optical_link_ids': [ + {'link_uuid': {'uuid': 'OL:R1/502==R2/501'}}, + ], + 'band': 'c_slots', + 'n_start': 10, + 'n_end': 25, + 'required_slots': 16, + 'owner_id': 'nbi-unit-test', + 'correlation_id': reservation_uuid, + 'status': 1, + } + +def _validate_optical_spectrum_reservation(message, reservation_uuid : str, status : str): + assert isinstance(message, dict) + assert message['reservation_id']['reservation_uuid']['uuid'] == reservation_uuid + assert message['band'] == 'c_slots' + assert message['n_start'] == 10 + assert message['n_end'] == 25 + assert message['required_slots'] == 16 + assert message['status'] == status + assert len(message['optical_link_ids']) == 1 + +def test_rest_optical_spectrum_reservation_lifecycle( + nbi_application : NbiApplication # pylint: disable=redefined-outer-name +) -> None: + context_uuid = urllib.parse.quote(DEFAULT_CONTEXT_NAME) + reservation_uuid = 'reservation-nbi-a' + reservation_uuid_quoted = urllib.parse.quote(reservation_uuid, safe='') + reservation = _optical_spectrum_reservation(DEFAULT_CONTEXT_NAME, reservation_uuid) + + reply = do_rest_post_request( + '/tfs-api/context/{:s}/optical_spectrum_reservations'.format(context_uuid), + reservation + ) + assert isinstance(reply, list) + assert len(reply) == 1 + assert reply[0]['reservation_uuid']['uuid'] == reservation_uuid + + reply = do_rest_get_request( + '/tfs-api/context/{:s}/optical_spectrum_reservations'.format(context_uuid) + ) + assert isinstance(reply, dict) + assert len(reply['reservations']) == 1 + _validate_optical_spectrum_reservation( + reply['reservations'][0], reservation_uuid, status='OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED' + ) + + reply = do_rest_get_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}'.format( + context_uuid, reservation_uuid_quoted + ) + ) + _validate_optical_spectrum_reservation( + reply, reservation_uuid, status='OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED' + ) + + overlap_uuid = 'reservation-nbi-overlap' + overlap_reservation = _optical_spectrum_reservation(DEFAULT_CONTEXT_NAME, overlap_uuid) + overlap_reservation['n_start'] = 20 + overlap_reservation['n_end'] = 30 + overlap_reservation['required_slots'] = 11 + overlap_reservation['correlation_id'] = overlap_uuid + reply = do_rest_post_request( + '/tfs-api/context/{:s}/optical_spectrum_reservations'.format(context_uuid), + overlap_reservation, + expected_status_codes={409} + ) + assert reply['error'] == 'ALREADY_EXISTS' + assert 'overlapping spectrum reservation' in reply['message'] + + occupied_uuid = 'reservation-nbi-occupied' + occupied_reservation = _optical_spectrum_reservation(DEFAULT_CONTEXT_NAME, occupied_uuid) + occupied_reservation['n_start'] = 0 + occupied_reservation['n_end'] = 0 + occupied_reservation['required_slots'] = 1 + occupied_reservation['correlation_id'] = occupied_uuid + reply = do_rest_post_request( + '/tfs-api/context/{:s}/optical_spectrum_reservations'.format(context_uuid), + occupied_reservation, + expected_status_codes={409} + ) + assert reply['error'] == 'ALREADY_EXISTS' + assert 'is not available on optical link' in reply['message'] + + reservation['owner_id'] = 'nbi-unit-test-updated' + reply = do_rest_put_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}'.format( + context_uuid, reservation_uuid_quoted + ), + reservation + ) + assert reply['reservation_uuid']['uuid'] == reservation_uuid + + reply = do_rest_get_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}'.format( + context_uuid, reservation_uuid_quoted + ) + ) + _validate_optical_spectrum_reservation( + reply, reservation_uuid, status='OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED' + ) + assert reply['owner_id'] == 'nbi-unit-test-updated' + + consume_request = { + 'reservation_id': reservation['reservation_id'], + 'service_id': { + 'context_id': {'context_uuid': {'uuid': DEFAULT_CONTEXT_NAME}}, + 'service_uuid': {'uuid': 'SVC:R1/200==R2/200'}, + }, + } + reply = do_rest_post_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}/consume'.format( + context_uuid, reservation_uuid_quoted + ), + consume_request + ) + assert reply['reservation_uuid']['uuid'] == reservation_uuid + + reply = do_rest_get_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}'.format( + context_uuid, reservation_uuid_quoted + ) + ) + _validate_optical_spectrum_reservation( + reply, reservation_uuid, status='OPTICALSPECTRUMRESERVATIONSTATUS_CONSUMED' + ) + assert reply['service_id']['service_uuid']['uuid'] == 'SVC:R1/200==R2/200' + + reply = do_rest_post_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}/release'.format( + context_uuid, reservation_uuid_quoted + ) + ) + assert reply == {} + + reply = do_rest_get_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}'.format( + context_uuid, reservation_uuid_quoted + ) + ) + _validate_optical_spectrum_reservation( + reply, reservation_uuid, status='OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED' + ) + + reply = do_rest_delete_request( + '/tfs-api/context/{:s}/optical_spectrum_reservation/{:s}'.format( + context_uuid, reservation_uuid_quoted + ) + ) + assert reply == {} + + # ----- Service -------------------------------------------------------------------------------------------------------- def test_rest_get_service_ids( diff --git a/src/nbi/tests/test_tfs_api_grpc_error_mapping.py b/src/nbi/tests/test_tfs_api_grpc_error_mapping.py new file mode 100644 index 000000000..c201e46f9 --- /dev/null +++ b/src/nbi/tests/test_tfs_api_grpc_error_mapping.py @@ -0,0 +1,54 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from nbi.service.tfs_api.Resources import _format_grpc_error +import grpc + + +class _FakeRpcError(grpc.RpcError): + def __init__(self, code, details): + super().__init__() + self._code = code + self._details = details + + def code(self): + return self._code + + def details(self): + return self._details + + +def _mapped_error(code, details='mapped error'): + return _format_grpc_error(_FakeRpcError(code, details)) + + +def test_grpc_already_exists_maps_to_http_conflict(): + reply, status = _mapped_error(grpc.StatusCode.ALREADY_EXISTS, 'overlapping spectrum reservation') + assert status == 409 + assert reply['error'] == 'ALREADY_EXISTS' + assert reply['message'] == 'overlapping spectrum reservation' + + +def test_grpc_invalid_argument_maps_to_http_bad_request(): + reply, status = _mapped_error(grpc.StatusCode.INVALID_ARGUMENT, 'invalid optical link') + assert status == 400 + assert reply['error'] == 'INVALID_ARGUMENT' + assert reply['message'] == 'invalid optical link' + + +def test_grpc_not_found_maps_to_http_not_found(): + reply, status = _mapped_error(grpc.StatusCode.NOT_FOUND, 'reservation not found') + assert status == 404 + assert reply['error'] == 'NOT_FOUND' + assert reply['message'] == 'reservation not found' diff --git a/src/opticalattackdetector/.gitlab-ci.yml b/src/opticalattackdetector/.gitlab-ci.yml index 2496c7be3..c24f3a1b2 100644 --- a/src/opticalattackdetector/.gitlab-ci.yml +++ b/src/opticalattackdetector/.gitlab-ci.yml @@ -20,6 +20,7 @@ build opticalattackdetector: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/opticalattackmanager/.gitlab-ci.yml b/src/opticalattackmanager/.gitlab-ci.yml index b5c7b4065..ac6759edc 100644 --- a/src/opticalattackmanager/.gitlab-ci.yml +++ b/src/opticalattackmanager/.gitlab-ci.yml @@ -20,6 +20,7 @@ build opticalattackmanager: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/opticalattackmitigator/.gitlab-ci.yml b/src/opticalattackmitigator/.gitlab-ci.yml index 0a39b8c72..b5619e388 100644 --- a/src/opticalattackmitigator/.gitlab-ci.yml +++ b/src/opticalattackmitigator/.gitlab-ci.yml @@ -20,6 +20,7 @@ build opticalattackmitigator: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/opticalcontroller/.gitlab-ci.yml b/src/opticalcontroller/.gitlab-ci.yml index d73eb8002..c322f043f 100644 --- a/src/opticalcontroller/.gitlab-ci.yml +++ b/src/opticalcontroller/.gitlab-ci.yml @@ -20,6 +20,7 @@ build opticalcontroller: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py index c2a4ff338..da65ad81c 100644 --- a/src/opticalcontroller/OpticalController.py +++ b/src/opticalcontroller/OpticalController.py @@ -13,7 +13,7 @@ # limitations under the License. import logging, time -from flask import Flask +from flask import Flask, request from flask import render_template from common.DeviceTypes import DeviceTypeEnum from flask_restplus import Resource, Api @@ -97,7 +97,16 @@ class AddFlexLightpath(Resource): # rsa.g.printGraph() if rsa is not None: - flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band, obx_idx, pref) + reservation = request.args.get("reservation") + if reservation is None and request.args.get("reservation_band") is not None: + reservation = { + "band": request.args.get("reservation_band"), + "n_start": request.args.get("reservation_start"), + "n_end": request.args.get("reservation_end"), + } + flow_id, optical_band_id = rsa.rsa_fs_computation( + src, dst, bitrate, bidir, band, obx_idx, pref, reservation=reservation + ) if flow_id is not None: if rsa.db_flows[flow_id]["op-mode"] == 0: return 'No path found', 404 diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py index 8842ee826..d9c73a1d3 100644 --- a/src/opticalcontroller/RSA.py +++ b/src/opticalcontroller/RSA.py @@ -650,10 +650,13 @@ class RSA(): return fiber_list #function invoked for lightpaths and OB - def select_slots_and_ports(self, links, n_slots, c, l, s, bidir, preferred=None): + def select_slots_and_ports(self, links, n_slots, c, l, s, bidir, preferred=None, reservation=None): if debug: print (links, n_slots, c, l, s, bidir, self.c_slot_number, self.l_slot_number, self.s_slot_number) - band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, preferred) + band, slots = slot_selection( + c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, + preferred, reservation=reservation + ) if debug: print (band, slots) if band is None: @@ -722,10 +725,13 @@ class RSA(): return t_flows, band, slots, {}, {} #function ivoked for fs lightpaths only - def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id): + def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id, reservation=None): if debug: print(self.links_dict) - band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number) + band, slots = slot_selection( + c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number, + reservation=reservation + ) if band is None: print("ERROR: No slots available in the three bands") return None, None, None, None, None @@ -989,7 +995,7 @@ class RSA(): #self.db_flows[flow_id]["parent_opt_band"] = 0 #self.db_flows[flow_id]["new_optical_band"] = 0 - def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None, preferred=None): + def create_optical_band(self, links, path, bidir, num_slots, old_band_x=None, preferred=None, reservation=None): print("INFO: Creating optical-band of {} slots".format(num_slots)) if self.opt_band_id == 0: self.opt_band_id += 1 @@ -1044,7 +1050,9 @@ class RSA(): print(l_slots) print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: - flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir, preferred) + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports( + links, num_slots, c_slots, l_slots, s_slots, bidir, preferred, reservation=reservation + ) if debug: print(flow_list, band_range, slots, fiber_f, fiber_b) f0, band = frequency_converter(band_range, slots) @@ -1239,7 +1247,7 @@ class RSA(): self.null_values(self.flow_id) return self.flow_id - def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id, preferred=None): + def rsa_fs_computation(self, src, dst, rate, bidir, band, bandx_id, preferred=None, reservation=None): if band is not None: num_slots_ob = map_band_to_slot(band) print(band, num_slots_ob) @@ -1263,7 +1271,9 @@ class RSA(): if len(path) < 1: self.null_values_ob(self.opt_band_id) return self.opt_band_id, [] - optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, old_band_x, preferred) + optical_band_id, temp_links = self.create_optical_band( + links, path, bidir, num_slots_ob, old_band_x, preferred, reservation=reservation + ) return None, optical_band_id print("INFO: TP to TP connection") if self.flow_id == 0: @@ -1321,7 +1331,7 @@ class RSA(): flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, - ob_id) + ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) @@ -1381,7 +1391,7 @@ class RSA(): temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, - ob_id) + ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) @@ -1435,7 +1445,7 @@ class RSA(): flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, - ob_id) + ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) @@ -1501,7 +1511,7 @@ class RSA(): temp_links2, num_slots, c_slots, l_slots, s_slots, bidir, - ob_id) + ob_id, reservation=reservation) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) @@ -1546,7 +1556,7 @@ class RSA(): print("INFO: optical-band width specified") #if no OB I create a new one links, path = self.compute_path(src, dst) - optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob) + optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob, reservation=reservation) op, num_slots = map_rate_to_slot(rate) if debug: print(temp_links) @@ -1556,8 +1566,9 @@ class RSA(): print(l_slots) print(s_slots) if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0: - flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links, num_slots, c_slots, - l_slots, s_slots, bidir, optical_band_id) + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs( + temp_links, num_slots, c_slots, l_slots, s_slots, bidir, optical_band_id, reservation=reservation + ) f0, band = frequency_converter(band_range, slots) if debug: print(f0, band) diff --git a/src/opticalcontroller/tests/test_spectrum_reservation.py b/src/opticalcontroller/tests/test_spectrum_reservation.py new file mode 100644 index 000000000..e19e319e9 --- /dev/null +++ b/src/opticalcontroller/tests/test_spectrum_reservation.py @@ -0,0 +1,90 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pytest + +from opticalcontroller.tools import parse_slot_reservation, slot_selection + + +def test_parse_compact_optical_spectrum_reservation(): + reservation = parse_slot_reservation("C_BAND:51-66") + + assert reservation == {"band": "c_slots", "n_start": 51, "n_end": 66} + + +def test_parse_dict_optical_spectrum_reservation(): + reservation = parse_slot_reservation({"band": "l_slots", "n_start": "4", "n_end": "11"}) + + assert reservation == {"band": "l_slots", "n_start": 4, "n_end": 11} + + +def test_slot_selection_without_reservation_keeps_first_fit(): + band, slots = slot_selection( + c=list(range(0, 10)), + l=list(range(20, 30)), + s=list(range(40, 50)), + n_slots=4, + Nc=10, + Nl=10, + Ns=10, + ) + + assert band == "c_slots" + assert slots == [0, 1, 2, 3] + + +def test_slot_selection_with_reservation_consumes_requested_band_and_range(): + band, slots = slot_selection( + c=list(range(0, 100)), + l=list(range(0, 100)), + s=list(range(0, 100)), + n_slots=4, + Nc=100, + Nl=100, + Ns=100, + reservation={"band": "l_slots", "n_start": 20, "n_end": 30}, + ) + + assert band == "l_slots" + assert slots == [20, 21, 22, 23] + + +def test_slot_selection_with_unavailable_reservation_returns_none(): + band, slots = slot_selection( + c=[0, 1, 2, 3], + l=[10, 11, 13, 14], + s=[20, 21, 22, 23], + n_slots=3, + Nc=4, + Nl=4, + Ns=4, + reservation={"band": "l_slots", "n_start": 10, "n_end": 12}, + ) + + assert band is None + assert slots is None + + +def test_slot_selection_rejects_too_narrow_reservation(): + with pytest.raises(ValueError): + slot_selection( + c=list(range(0, 100)), + l=[], + s=[], + n_slots=4, + Nc=100, + Nl=0, + Ns=0, + reservation={"band": "c_slots", "n_start": 20, "n_end": 22}, + ) diff --git a/src/opticalcontroller/tools.py b/src/opticalcontroller/tools.py index c15fcafa0..8a335c4b3 100644 --- a/src/opticalcontroller/tools.py +++ b/src/opticalcontroller/tools.py @@ -13,7 +13,7 @@ # limitations under the License. import json, logging, numpy as np -from typing import Dict, List, Tuple +from typing import Dict, List, Optional, Tuple from opticalcontroller.variables import * from context.client.ContextClient import ContextClient from common.proto.context_pb2 import TopologyId , LinkId , OpticalLink , OpticalLinkDetails @@ -252,9 +252,68 @@ def get_links_to_node(topology, node): return result -def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None): +def _normalize_reservation_band(band: str) -> str: + normalized_band = str(band).strip().lower().replace("-", "_") + if normalized_band in {"c", "c_band", "c_slots"}: + return "c_slots" + if normalized_band in {"l", "l_band", "l_slots"}: + return "l_slots" + if normalized_band in {"s", "s_band", "s_slots"}: + return "s_slots" + raise ValueError("Unsupported optical spectrum band: {:s}".format(str(band))) + + +def parse_slot_reservation(reservation) -> Optional[Dict[str, int]]: + if reservation is None: + return None + + if isinstance(reservation, dict): + if len(reservation) == 0: + return None + band = reservation.get("band") + n_start = reservation.get("n_start", reservation.get("start")) + n_end = reservation.get("n_end", reservation.get("end")) + else: + reservation_text = str(reservation).strip() + if len(reservation_text) == 0: + return None + if reservation_text.startswith("{"): + return parse_slot_reservation(json.loads(reservation_text)) + if ":" not in reservation_text or "-" not in reservation_text: + raise ValueError( + "Optical spectrum reservation must be ':-' or JSON" + ) + band, slot_range = reservation_text.split(":", maxsplit=1) + n_start, n_end = slot_range.split("-", maxsplit=1) + + band = _normalize_reservation_band(band) + n_start = int(n_start) + n_end = int(n_end) + if n_start < 0 or n_end < n_start: + raise ValueError( + "Invalid optical spectrum reservation range: {:d}-{:d}".format(n_start, n_end) + ) + return {"band": band, "n_start": n_start, "n_end": n_end} + + +def _select_reserved_slots(available_slots: List[int], n_slots: int, reservation: Dict[str, int]) -> Optional[List[int]]: + requested_slots = list(range(reservation["n_start"], reservation["n_end"] + 1)) + if len(requested_slots) < n_slots: + raise ValueError( + "Optical spectrum reservation provides {:d} slots, but {:d} are required".format( + len(requested_slots), n_slots + ) + ) + + selected_slots = requested_slots[0:n_slots] + if not list_in_list(selected_slots, sorted(available_slots)): + return None + return selected_slots + + +def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None, reservation=None): # First Fit - + reservation = parse_slot_reservation(reservation) if isinstance(n_slots, int): slot_c = n_slots slot_l = n_slots @@ -263,6 +322,18 @@ def slot_selection(c, l, s, n_slots, Nc, Nl, Ns, preferred=None): slot_c = Nc slot_l = Nl slot_s = Ns + if reservation is not None: + band = reservation["band"] + if band == "c_slots": + selected_slots = _select_reserved_slots(c, slot_c, reservation) + elif band == "l_slots": + selected_slots = _select_reserved_slots(l, slot_l, reservation) + else: + selected_slots = _select_reserved_slots(s, slot_s, reservation) + if selected_slots is None: + return None, None + return band, selected_slots + if preferred == None or preferred == "ANY": if len(c) >= slot_c: return "c_slots", c[0: slot_c] @@ -372,4 +443,3 @@ def set_link_update (fib:dict,link:dict,test="updating"): except Exception as err: print (f"setOpticalLink {err}") - diff --git a/src/osm_client/.gitlab-ci.yml b/src/osm_client/.gitlab-ci.yml index 5a96d8fef..63bb96a40 100644 --- a/src/osm_client/.gitlab-ci.yml +++ b/src/osm_client/.gitlab-ci.yml @@ -21,6 +21,7 @@ build osm_client: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -64,6 +65,7 @@ unit_test osm_client: - docker buildx prune --force # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: diff --git a/src/pathcomp/.gitlab-ci.yml b/src/pathcomp/.gitlab-ci.yml index 81cfab345..2915a1f98 100644 --- a/src/pathcomp/.gitlab-ci.yml +++ b/src/pathcomp/.gitlab-ci.yml @@ -20,6 +20,7 @@ build pathcomp: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # This first build tags the builder resulting image to prevent being removed by dangling image removal command @@ -59,6 +60,7 @@ unit_test pathcomp-backend: needs: - build pathcomp before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep ${IMAGE_NAME}-frontend; then docker rm -f ${IMAGE_NAME}-frontend; else echo "${IMAGE_NAME}-frontend image is not in the system"; fi @@ -107,6 +109,7 @@ unit_test pathcomp-frontend: needs: - build pathcomp before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create --driver=bridge teraflowbridge; fi - if docker container ls | grep ${IMAGE_NAME}-frontend; then docker rm -f ${IMAGE_NAME}-frontend; else echo "${IMAGE_NAME}-frontend image is not in the system"; fi diff --git a/src/pathcomp/frontend/service/OpticalPathComp.py b/src/pathcomp/frontend/service/OpticalPathComp.py new file mode 100644 index 000000000..20d4dc5eb --- /dev/null +++ b/src/pathcomp/frontend/service/OpticalPathComp.py @@ -0,0 +1,443 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging +import uuid + +import requests +from common.proto.context_pb2 import ConfigActionEnum, ConfigRule, Service +from common.proto.pathcomp_pb2 import PathCompReply + +from .TopologyTools import get_device_with_driver + +LOGGER = logging.getLogger(__name__) + +def safe_get(d, keys, default=None): + for key in keys: + if isinstance(d, dict): + d = d.get(key, default) + else: + return default + return d + + +def group_block(group, action, group_id_override=None, node=None): + active = "true" if action == 'create' else "false" + group_id = group_id_override if group_id_override is not None else group.get("group-id", group.get("digital_sub_carriers_group_id", 1)) + + if node == "leaf": + return { + "digital_sub_carriers_group_id": group_id, + "digital_sub_carrier_id": [ + {'sub_carrier_id': 1, 'active': active}, + {'sub_carrier_id': 2, 'active': active}, + {'sub_carrier_id': 3, 'active': active}, + {'sub_carrier_id': 4, 'active': active} + ] + } + else: + return { + "digital_sub_carriers_group_id": group_id, + "digital_sub_carrier_id": [ + { + "sub_carrier_id": sid, + "active": active, + } + for sid in group.get("subcarrier-id", []) + ] + } + +def compute_optical_path(service: Service) -> PathCompReply: + # Extract intent from config rules + intent_str = "" + for cr in service.service_config.config_rules: + if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == "intent": + intent_str = cr.custom.resource_value + break + + intent = json.loads(intent_str) if intent_str else {} + action = "create" # Default action + + # Extract src (sender) and dst (receivers) from intent + services = intent.get("ietf-network-slice-service:network-slice-services", {}).get("slice-service", []) + source = None + destination = None + + for srv in services: + c_groups = srv.get("connection-groups", {}).get("connection-group", []) + for cg in c_groups: + constructs = cg.get("connectivity-construct", []) + for construct in constructs: + source = construct.get("p2mp-sender-sdp") + destination = construct.get("p2mp-receiver-sdp") + if source and destination: + break + if source and destination: + break + if source and destination: + break + + if not source or not destination: + raise Exception("Missing p2mp-sender-sdp or p2mp-receiver-sdp parameters in the intent") + + if isinstance(source, str): + sources_list = [source] + else: + sources_list = list(source) + + if isinstance(destination, str): + destinations_list = [destination] + else: + destinations_list = list(destination) + + # In optical networks, the leaves are often the "sources" of light for the computation or vice-versa. + # Based on user's instruction: sources = receivers, destinations = sender + payload = { + "sources": destinations_list, + "destinations": sources_list, + "bitrate": 100, + "bidirectional": True, + "band": 200, + "subcarriers_per_source": [4] * len(destinations_list) + } + + url = "http://10.30.7.66:31060/OpticalTFS/restconf/operations/tapi-path-computation:compute-p2mp" + headers = { + "Content-Type": "application/json", + "Accept": "*/*" + } + + # resp = requests.post(url, headers=headers, json=payload, timeout=15) + # resp.raise_for_status() + # resp_json = resp.json() + + # MOCK RESPONSE (If the Optical Controller is down) + resp_json = { + "tapi-connectivity:connectivity-service": { + "connection": [ + { + "optical-connection-attributes": { + "central-frequency": 195000000000000, + "Tx-power": 0, + "modulation": { + "modulation-technique": "DP-16QAM", + "operational-mode": 9, + "port": "port-1" + }, + "digital-subcarrier-spacing": 300000000, + "subcarrier-attributes": { + "digital-subcarrier-group": [ + { + "group-id": 1, + "modulation-technique": "DP-QPSK", + "central-frequency": 195006250, + "operational-mode": 4, + "Tx-power": -99, + "group-size": 4, + "port": "port-1", + "subcarrier-id": [1, 2, 3, 4] + }, + { + "group-id": 2, + "modulation-technique": "DP-QPSK", + "central-frequency": 195018750, + "operational-mode": 4, + "Tx-power": -99, + "group-size": 4, + "port": "port-3", + "subcarrier-id": [5, 6, 7, 8] + }, + { + "group-id": 3, + "modulation-technique": "DP-QPSK", + "central-frequency": 195031250, + "operational-mode": 4, + "Tx-power": -99, + "group-size": 4, + "port": "port-5", + "subcarrier-id": [9, 10, 11, 12] + } + ] + } + }, + "end-point": [ + { + "direction": "BIDIRECTIONAL", + "layer-protocol-name": "PHOTONIC_MEDIA", + "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_MC", + "local-id": "T1.1", + "service-interface-point": { + "service-interface-point-uuid": "T2.1" + }, + "tapi-photonic-media:media-channel-connectivity-service-end-point-spec": { + "mc-config": { + "spectrum": { + "center-frequency": 195000000000000, + "frequency-constraint": { + "adjustment-granularity": "G_6_25GHZ", + "grid-type": "FLEX" + } + } + } + } + }, + { + "direction": "BIDIRECTIONAL", + "layer-protocol-name": "PHOTONIC_MEDIA", + "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_MC", + "local-id": "T2.1", + "service-interface-point": { + "service-interface-point-uuid": "T1.1" + }, + "tapi-photonic-media:media-channel-connectivity-service-end-point-spec": { + "mc-config": { + "spectrum": { + "center-frequency": 195006250, + "frequency-constraint": { + "adjustment-granularity": "G_6_25GHZ", + "grid-type": "FLEX" + } + } + } + } + }, + { + "direction": "BIDIRECTIONAL", + "layer-protocol-name": "PHOTONIC_MEDIA", + "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_MC", + "local-id": "T1.2", + "service-interface-point": { + "service-interface-point-uuid": "T2.1" + }, + "tapi-photonic-media:media-channel-connectivity-service-end-point-spec": { + "mc-config": { + "spectrum": { + "center-frequency": 195018750, + "frequency-constraint": { + "adjustment-granularity": "G_6_25GHZ", + "grid-type": "FLEX" + } + } + } + } + }, + { + "direction": "BIDIRECTIONAL", + "layer-protocol-name": "PHOTONIC_MEDIA", + "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_MC", + "local-id": "T2.1", + "service-interface-point": { + "service-interface-point-uuid": "T1.2" + }, + "tapi-photonic-media:media-channel-connectivity-service-end-point-spec": { + "mc-config": { + "spectrum": { + "center-frequency": 195018750, + "frequency-constraint": { + "adjustment-granularity": "G_6_25GHZ", + "grid-type": "FLEX" + } + } + } + } + }, + { + "direction": "BIDIRECTIONAL", + "layer-protocol-name": "PHOTONIC_MEDIA", + "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_MC", + "local-id": "T1.3", + "service-interface-point": { + "service-interface-point-uuid": "T2.1" + }, + "tapi-photonic-media:media-channel-connectivity-service-end-point-spec": { + "mc-config": { + "spectrum": { + "center-frequency": 195031250, + "frequency-constraint": { + "adjustment-granularity": "G_6_25GHZ", + "grid-type": "FLEX" + } + } + } + } + }, + { + "direction": "BIDIRECTIONAL", + "layer-protocol-name": "PHOTONIC_MEDIA", + "layer-protocol-qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_MC", + "local-id": "T2.1", + "service-interface-point": { + "service-interface-point-uuid": "T1.3" + }, + "tapi-photonic-media:media-channel-connectivity-service-end-point-spec": { + "mc-config": { + "spectrum": { + "center-frequency": 195031250, + "frequency-constraint": { + "adjustment-granularity": "G_6_25GHZ", + "grid-type": "FLEX" + } + } + } + } + } + ] + } + ] + } + } + + # Generate Rules + src_name = source # T2.1 + dest_list = destinations_list # T1.1, T1.2 + # Extract destinations from response end-points if available + try: + endpoints = resp_json.get("tapi-connectivity:connectivity-service", {}).get("connection", [{}])[0].get("end-point", []) + extracted_dests = [] + for ep in endpoints: + local_id = ep.get("local-id") + if local_id and local_id != src_name and local_id not in extracted_dests: + extracted_dests.append(local_id) + if extracted_dests: + dest_list = extracted_dests + except Exception: + pass + + dest_str = ",".join(dest_list) + config_rules = [] + + network_slice_uuid_str = f"{src_name}_to_{dest_str}" + tunnel_uuid = str(uuid.uuid5(uuid.NAMESPACE_DNS, network_slice_uuid_str)) + + provisionamiento = { + "network-slice-uuid": network_slice_uuid_str, + "viability": True, + "actions": [] + } + try: + attributes = resp_json.get("tapi-connectivity:connectivity-service", {}).get("connection", [{}])[0].get("optical-connection-attributes", {}) + groups = attributes.get("subcarrier-attributes", {}).get("digital-subcarrier-group", []) + operational_mode = attributes.get("modulation", {}).get("operational-mode", 9) + except Exception: + # Provide fallback if mock doesn't match perfectly + groups = resp_json.get("digital-subcarrier-groups", []) + operational_mode = resp_json.get("op-mode", 9) + + hub_groups = [ + group_block(group, action, group_id_override=index + 1) + for index, group in enumerate(groups) + ] + + hub_freq_raw = attributes.get("central-frequency", 195000000000000) + hub_freq = int(hub_freq_raw / 1e6) if hub_freq_raw > 1e10 else int(hub_freq_raw) + + hub = { + "name": "channel-1", + "frequency": hub_freq, + "target_output_power": attributes.get("Tx-power", 0), + "operational_mode": operational_mode, + "operation": "merge", + "digital_sub_carriers_group": hub_groups + } + + leaves = [] + print("dest_list:", dest_list) + print("groups:", groups) + for dest, group in zip(dest_list, groups): + port = group.get("port", "port-1") + if port.startswith("port-"): + name = f"channel-{port.split('-')[1]}" + else: + name = "channel-1" + + freq_raw = group.get("central-frequency", 195006250) + freq = int(freq_raw / 1e6) if freq_raw > 1e10 else int(freq_raw) + + leaf = { + "name": name, + "frequency": freq, + "target_output_power": group.get("Tx-power", 0), + "operational_mode": int(group.get("operational-mode", operational_mode)), + "operation": "merge", + "digital_sub_carriers_group": [group_block(group, action, group_id_override=1, node="leaf")] + } + leaves.append(leaf) + + final_json = {"components": [hub] + leaves} + + # Add transceiver activation action + provisionamiento["actions"].append({ + "type": "XR_AGENT_ACTIVATE_TRANSCEIVER", + "layer": "OPTICAL", + "content": final_json, + "controller-uuid": "IPoWDM Controller" + }) + + # Extract IP configuration from intent for L3 VPN setup + nodes = {} + sdp_list = intent.get('ietf-network-slice-service:network-slice-services', {}).get('slice-service', [{}])[0].get('sdps', {}).get('sdp', []) + + for sdp in sdp_list: + node = sdp.get('id') + attachments = sdp.get('attachment-circuits', {}).get('attachment-circuit', []) + for ac in attachments: + ip = ac.get('ac-ipv4-address', None) + prefix = ac.get('ac-ipv4-prefix-length', None) + vlan = 500 # Fixed VLAN ID + nodes[node] = { + "ip-address": ip, + "ip-mask": prefix, + "vlan-id": vlan + } + + # Add L3 VPN configuration action for P2MP topology + if src_name in nodes: + content = { + "tunnel-uuid": tunnel_uuid, + "src-node-uuid": src_name, + "src-ip-address": nodes[src_name]["ip-address"], + "src-ip-mask": str(nodes[src_name]["ip-mask"]), + "src-vlan-id": nodes[src_name]["vlan-id"], + } + + for i, dest in enumerate(dest_list): + if dest in nodes: + content[f"dest{i+1}-node-uuid"] = dest + content[f"dest{i+1}-ip-address"] = nodes[dest]["ip-address"] + content[f"dest{i+1}-ip-mask"] = str(nodes[dest]["ip-mask"]) + content[f"dest{i+1}-vlan-id"] = nodes[dest]["vlan-id"] + controller_ip = get_device_with_driver() + + provisionamiento["actions"].append({ + "type": "CONFIG_VPNL3", + "layer": "IP", + "content": content, + "controller_uuid": controller_ip + }) + + config_rules.append(provisionamiento) + + reply = PathCompReply() + reply_svc = Service() + reply_svc.CopyFrom(service) + + cr = ConfigRule() + cr.action = ConfigActionEnum.CONFIGACTION_SET + cr.custom.resource_key = "optical_path_result" + cr.custom.resource_value = json.dumps(config_rules) + reply_svc.service_config.config_rules.append(cr) + reply.services.append(reply_svc) + + return reply diff --git a/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py index 4e832c258..d7e3f2daf 100644 --- a/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py +++ b/src/pathcomp/frontend/service/PathCompServiceServicerImpl.py @@ -28,6 +28,8 @@ from pathcomp.frontend.Config import is_forecaster_enabled #from context.client.ContextClient import ContextClient from pathcomp.frontend.service.TopologyTools import get_pathcomp_topology_details from pathcomp.frontend.service.algorithms.Factory import get_algorithm +from pathcomp.frontend.service.OpticalPathComp import compute_optical_path +from common.proto.context_pb2 import ServiceTypeEnum LOGGER = logging.getLogger(__name__) @@ -45,6 +47,11 @@ class PathCompServiceServicerImpl(PathCompServiceServicer): def Compute(self, request : PathCompRequest, context : grpc.ServicerContext) -> PathCompReply: LOGGER.debug('[Compute] begin ; request = {:s}'.format(grpc_message_to_json_string(request))) + if len(request.services) > 0 and request.services[0].service_type == ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY: + LOGGER.info('[Compute] Intercepting OPTICAL_CONNECTIVITY request...') + return compute_optical_path(request.services[0]) + + #context_client = ContextClient() # TODO: improve definition of topologies; for interdomain the current topology design might be not convenient #if (len(request.services) == 1) and is_inter_domain(context_client, request.services[0].service_endpoint_ids): diff --git a/src/pathcomp/frontend/service/TopologyTools.py b/src/pathcomp/frontend/service/TopologyTools.py index 036f85a56..cf3e0dd9d 100644 --- a/src/pathcomp/frontend/service/TopologyTools.py +++ b/src/pathcomp/frontend/service/TopologyTools.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import logging, math +import logging, math, os, socket, requests from typing import Dict, Optional from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME, ServiceNameEnum from common.Settings import ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, find_environment_variables, get_env_var_name @@ -25,6 +25,7 @@ from common.tools.grpc.Tools import grpc_message_to_json_string from context.client.ContextClient import ContextClient from forecaster.client.ForecasterClient import ForecasterClient + LOGGER = logging.getLogger(__name__) def get_service_schedule(service : Service) -> Optional[Constraint_Schedule]: @@ -96,3 +97,36 @@ def get_pathcomp_topology_details(request : PathCompRequest, allow_forecasting : link.attributes.total_capacity_gbps = total_capacity_gbps return topology_details + +# The HOST IP of the TFS controller is needed to query the devices and get the +# IP address of the controller to be used in the path provisioning. +ENVVAR_TFS_API_HOST = '10.95.89.50' + + + +def get_device_with_driver(driver_name: str = 'DEVICEDRIVER_IETF_L3VPN', timeout: int = 10): + """Query the TFS controller REST API and return the _connect/address value of the first device with the given driver. + + Example: GET http:///tfs-api/devices + + Returns the _connect/address string or None. + """ + url = f'http://{ENVVAR_TFS_API_HOST}:80/tfs-api/devices' + try: + logging.debug("Requesting devices from %s", url) + resp = requests.get(url, timeout=timeout) + resp.raise_for_status() + data = resp.json() + except Exception as e: + logging.warning("Error fetching devices from %s: %s", url, e) + return None + + devices = data.get('devices', []) if isinstance(data, dict) else [] + for dev in devices: + drivers = dev.get('device_drivers') or [] + if isinstance(drivers, list) and driver_name in drivers: + device_name = dev.get('name') + return device_name + + logging.info("No device with driver %s found on %s", driver_name, url) + return None diff --git a/src/pluggables/.gitlab-ci.yml b/src/pluggables/.gitlab-ci.yml index 22bab8252..e924096ed 100644 --- a/src/pluggables/.gitlab-ci.yml +++ b/src/pluggables/.gitlab-ci.yml @@ -20,6 +20,7 @@ build pluggables: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/policy/.gitlab-ci.yml b/src/policy/.gitlab-ci.yml index 673966c09..d4396dec5 100644 --- a/src/policy/.gitlab-ci.yml +++ b/src/policy/.gitlab-ci.yml @@ -22,6 +22,7 @@ build policy: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - export POL_IMAGE_TAG=$(grep -m1 '' ./src/$IMAGE_NAME_POLICY/pom.xml | grep -oP '(?<=>).*(?=<)') @@ -49,6 +50,7 @@ unit_test policy: needs: - build policy before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker rm ${REPORTS_CONTAINER} || true script: diff --git a/src/qkd_app/.gitlab-ci.yml b/src/qkd_app/.gitlab-ci.yml index 32ae18f44..c5e0b33cc 100644 --- a/src/qkd_app/.gitlab-ci.yml +++ b/src/qkd_app/.gitlab-ci.yml @@ -19,6 +19,7 @@ build qkd_app: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/qos_profile/.gitlab-ci.yml b/src/qos_profile/.gitlab-ci.yml index 68b14b43d..5085c8a39 100644 --- a/src/qos_profile/.gitlab-ci.yml +++ b/src/qos_profile/.gitlab-ci.yml @@ -20,6 +20,7 @@ build qos_profile: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test qos_profile: needs: - build qos_profile before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY # Do Docker cleanup diff --git a/src/service/.gitlab-ci.yml b/src/service/.gitlab-ci.yml index e54948a03..4443b7e00 100644 --- a/src/service/.gitlab-ci.yml +++ b/src/service/.gitlab-ci.yml @@ -20,6 +20,7 @@ build service: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test service: needs: - build service before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create --driver=bridge teraflowbridge; fi diff --git a/src/service/service/ServiceServiceServicerImpl.py b/src/service/service/ServiceServiceServicerImpl.py index 35b279ab3..b7864f521 100644 --- a/src/service/service/ServiceServiceServicerImpl.py +++ b/src/service/service/ServiceServiceServicerImpl.py @@ -47,6 +47,7 @@ from .tools.OpticalTools import ( get_optical_band, refresh_opticalcontroller, DelFlexLightpath , extend_optical_band, reconfig_flex_lightpath, adapt_reply_ob, add_alien_flex_lightpath ) +from .tools.OpticalSpectrumReservation import parse_optical_spectrum_reservation_constraints @@ -54,6 +55,7 @@ LOGGER = logging.getLogger(__name__) METRICS_POOL = MetricsPool('Service', 'RPC') + class ServiceServiceServicerImpl(ServiceServiceServicer): def __init__(self, service_handler_factory : ServiceHandlerFactory) -> None: LOGGER.debug('Creating Servicer...') @@ -296,11 +298,16 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): alien = 0 alien_band = 0 alien_optical_band_id = 0 + spectrum_reservation = parse_optical_spectrum_reservation_constraints(service.service_constraints) for constraint in service.service_constraints: + if constraint.WhichOneof('constraint') != 'custom': + continue if "alien" in constraint.custom.constraint_type: alien = 1 break for constraint in service.service_constraints: + if constraint.WhichOneof('constraint') != 'custom': + continue if alien == 1: if "alien_spectrum" in constraint.custom.constraint_type: alien_band = int(constraint.custom.constraint_value) @@ -338,11 +345,17 @@ class ServiceServiceServicerImpl(ServiceServiceServicer): reply_txt = add_alien_flex_lightpath(src, ports[0], dst, ports[1], alien_band, alien_optical_band_id, bidir) else: if oc_type == 1: - reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, preferred, ob_band, dj_optical_band_id) + reply_txt = add_flex_lightpath( + src, dst, bitrate, bidir, preferred, ob_band, dj_optical_band_id, + spectrum_reservation=spectrum_reservation + ) elif oc_type == 2: reply_txt = add_lightpath(src, dst, bitrate, bidir) else: - reply_txt = add_flex_lightpath(src, dst, bitrate, bidir, preferred, ob_band, dj_optical_band_id) + reply_txt = add_flex_lightpath( + src, dst, bitrate, bidir, preferred, ob_band, dj_optical_band_id, + spectrum_reservation=spectrum_reservation + ) if reply_txt is None: return service_with_uuids.service_id reply_json = json.loads(reply_txt) diff --git a/src/service/service/tools/OpticalSpectrumReservation.py b/src/service/service/tools/OpticalSpectrumReservation.py new file mode 100644 index 000000000..d4e360840 --- /dev/null +++ b/src/service/service/tools/OpticalSpectrumReservation.py @@ -0,0 +1,75 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Dict, Optional + +from common.method_wrappers.ServiceExceptions import InvalidArgumentException + + +def normalize_optical_spectrum_band(band: str) -> str: + normalized_band = str(band).strip().lower().replace("-", "_") + if normalized_band in {"c", "c_band", "c_slots"}: + return "c_slots" + if normalized_band in {"l", "l_band", "l_slots"}: + return "l_slots" + if normalized_band in {"s", "s_band", "s_slots"}: + return "s_slots" + raise InvalidArgumentException('optical spectrum band', str(band)) + + +def parse_optical_spectrum_reservation_text(reservation_text: str) -> Dict: + if ":" not in reservation_text or "-" not in reservation_text: + raise InvalidArgumentException( + 'optical-spectrum-reservation', reservation_text, + extra_details="Expected ':-'" + ) + band, slot_range = reservation_text.split(":", maxsplit=1) + n_start, n_end = slot_range.split("-", maxsplit=1) + reservation = { + "band": normalize_optical_spectrum_band(band), + "n_start": int(n_start), + "n_end": int(n_end), + } + if reservation["n_start"] < 0 or reservation["n_end"] < reservation["n_start"]: + raise InvalidArgumentException('optical-spectrum-reservation', reservation_text) + return reservation + + +def parse_optical_spectrum_reservation_constraints(service_constraints) -> Optional[Dict]: + reservation = {} + for constraint in service_constraints: + if constraint.WhichOneof('constraint') != 'custom': + continue + constraint_type = constraint.custom.constraint_type + constraint_value = constraint.custom.constraint_value + if constraint_type == 'optical-spectrum-reservation': + return parse_optical_spectrum_reservation_text(constraint_value) + if constraint_type == 'optical-spectrum-band': + reservation['band'] = normalize_optical_spectrum_band(constraint_value) + elif constraint_type == 'optical-spectrum-n-start': + reservation['n_start'] = int(constraint_value) + elif constraint_type == 'optical-spectrum-n-end': + reservation['n_end'] = int(constraint_value) + + if len(reservation) == 0: + return None + missing_fields = {'band', 'n_start', 'n_end'} - set(reservation.keys()) + if len(missing_fields) > 0: + raise InvalidArgumentException( + 'optical spectrum reservation', str(reservation), + extra_details='Missing fields: {:s}'.format(', '.join(sorted(missing_fields))) + ) + if reservation["n_start"] < 0 or reservation["n_end"] < reservation["n_start"]: + raise InvalidArgumentException('optical spectrum reservation', str(reservation)) + return reservation diff --git a/src/service/service/tools/OpticalTools.py b/src/service/service/tools/OpticalTools.py index fe277e83d..e13615497 100644 --- a/src/service/service/tools/OpticalTools.py +++ b/src/service/service/tools/OpticalTools.py @@ -14,7 +14,8 @@ # import functools, json, logging, requests, uuid -from typing import Dict, List, Tuple +from typing import Dict, List, Optional, Tuple +from urllib.parse import urlencode from common.method_wrappers.ServiceExceptions import NotFoundException from common.proto.context_pb2 import( ConfigActionEnum, ConfigRule, ConfigRule_Custom, Connection, ContextId, @@ -136,7 +137,9 @@ def reconfig_flex_lightpath(flow_id) -> str: return reply_bid_txt -def add_flex_lightpath(src, dst, bitrate, bidir, pref, ob_band, dj_optical_band_id) -> str: +def add_flex_lightpath( + src, dst, bitrate, bidir, pref, ob_band, dj_optical_band_id, spectrum_reservation: Optional[Dict] = None +) -> str: if not TESTING: urlx = "" headers = {"Content-Type": "application/json"} @@ -156,6 +159,13 @@ def add_flex_lightpath(src, dst, bitrate, bidir, pref, ob_band, dj_optical_band_ urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(prefs), str(bidir), str(ob_band)) else: urlx = "{:s}/AddFlexLightpath/{:s}/{:s}/{:s}/{:s}/{:s}/{:s}/{:s}".format(base_url, src, dst, str(bitrate), str(prefs), str(bidir), str(ob_band), str(dj_optical_band_id)) + if spectrum_reservation is not None: + query = { + 'reservation_band': spectrum_reservation['band'], + 'reservation_start': str(spectrum_reservation['n_start']), + 'reservation_end': str(spectrum_reservation['n_end']), + } + urlx = '{:s}?{:s}'.format(urlx, urlencode(query)) r = requests.put(urlx, headers=headers) LOGGER.debug(f"addpathlight {r}") reply = r.text diff --git a/src/service/tests/test_optical_spectrum_reservation.py b/src/service/tests/test_optical_spectrum_reservation.py new file mode 100644 index 000000000..fa1074d3b --- /dev/null +++ b/src/service/tests/test_optical_spectrum_reservation.py @@ -0,0 +1,74 @@ +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from common.proto.context_pb2 import Constraint, Constraint_Custom +from service.service.tools.OpticalSpectrumReservation import parse_optical_spectrum_reservation_constraints +from service.service.tools import OpticalTools + + +def test_parse_compact_service_reservation_constraint(): + constraints = [ + Constraint(custom=Constraint_Custom( + constraint_type="optical-spectrum-reservation", + constraint_value="c_slots:51-66", + )) + ] + + reservation = parse_optical_spectrum_reservation_constraints(constraints) + + assert reservation == {"band": "c_slots", "n_start": 51, "n_end": 66} + + +def test_parse_split_service_reservation_constraints(): + constraints = [ + Constraint(custom=Constraint_Custom(constraint_type="optical-spectrum-band", constraint_value="L_BAND")), + Constraint(custom=Constraint_Custom(constraint_type="optical-spectrum-n-start", constraint_value="8")), + Constraint(custom=Constraint_Custom(constraint_type="optical-spectrum-n-end", constraint_value="23")), + ] + + reservation = parse_optical_spectrum_reservation_constraints(constraints) + + assert reservation == {"band": "l_slots", "n_start": 8, "n_end": 23} + + +def test_add_flex_lightpath_forwards_reservation_query(monkeypatch): + captured = {} + + class Response: + text = "{}" + + def put(url, headers=None): + captured["url"] = url + captured["headers"] = headers + return Response() + + monkeypatch.setattr(OpticalTools, "get_optical_controller_base_url", lambda: "http://optical/OpticalTFS") + monkeypatch.setattr(OpticalTools.requests, "put", put) + monkeypatch.setattr(OpticalTools, "TESTING", False) + + OpticalTools.add_flex_lightpath( + "T1", + "T2", + 100, + 0, + "ANY", + None, + None, + spectrum_reservation={"band": "c_slots", "n_start": 51, "n_end": 66}, + ) + + assert captured["url"].startswith("http://optical/OpticalTFS/AddFlexLightpath/T1/T2/100/ANY/0?") + assert "reservation_band=c_slots" in captured["url"] + assert "reservation_start=51" in captured["url"] + assert "reservation_end=66" in captured["url"] diff --git a/src/simap_connector/.gitlab-ci.yml b/src/simap_connector/.gitlab-ci.yml index 7d116db51..e4361fcb8 100644 --- a/src/simap_connector/.gitlab-ci.yml +++ b/src/simap_connector/.gitlab-ci.yml @@ -20,6 +20,7 @@ build simap_connector: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/slice/.gitlab-ci.yml b/src/slice/.gitlab-ci.yml index c25256c9a..4b7026b4f 100644 --- a/src/slice/.gitlab-ci.yml +++ b/src/slice/.gitlab-ci.yml @@ -20,6 +20,7 @@ build slice: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/telemetry/.gitlab-ci.yml b/src/telemetry/.gitlab-ci.yml index 71e387df4..d4a8fe900 100644 --- a/src/telemetry/.gitlab-ci.yml +++ b/src/telemetry/.gitlab-ci.yml @@ -20,6 +20,7 @@ build telemetry: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # This first build tags the builder resulting image to prevent being removed by dangling image removal command @@ -57,6 +58,7 @@ unit_test telemetry-backend: needs: - build telemetry before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep kafka; then docker rm -f kafka; else echo "Kafka container is not in the system"; fi @@ -125,6 +127,7 @@ unit_test telemetry-frontend: needs: - build telemetry before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep crdb; then docker rm -f crdb; else echo "CockroachDB container is not in the system"; fi diff --git a/src/tests/acl_end2end/.gitlab-ci.yml b/src/tests/acl_end2end/.gitlab-ci.yml index 302819aef..49ad4ad42 100644 --- a/src/tests/acl_end2end/.gitlab-ci.yml +++ b/src/tests/acl_end2end/.gitlab-ci.yml @@ -19,6 +19,7 @@ build acl_end2end: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,83 +47,16 @@ end2end_test acl_end2end: #needs: # - build acl_end2end before_script: - # Cleanup old ContainerLab scenarios - - containerlab destroy --all --cleanup || true - - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # Download Docker image to run the test - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest" - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - # Deploy ContainerLab Scenario - RUNNER_PATH=`pwd` #- cd $PWD/src/tests/${TEST_NAME} @@ -140,6 +74,9 @@ end2end_test acl_end2end: # Dump configuration of the firewall (before any configuration) - containerlab exec --name acl_end2end --label clab-node-name=firewall --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh + # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml @@ -256,15 +193,17 @@ end2end_test acl_end2end: after_script: # Dump configuration of the firewall (on after_script) - - containerlab exec --name acl_end2end --label clab-node-name=firewall --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + - mkdir -p src/tests/${TEST_NAME}/logs + - containerlab exec --name acl_end2end --label clab-node-name=firewall --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_firewall-running-config.log 2>&1 || true # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server + - ./deploy/show.sh + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice-server.log 2>&1 || true # Clean up - RUNNER_PATH=`pwd` @@ -274,12 +213,7 @@ end2end_test acl_end2end: - sudo rm -rf clab-acl_end2end/ .acl_end2end.clab.yml.bak || true - cd $RUNNER_PATH - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -289,3 +223,5 @@ end2end_test acl_end2end: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/ecoc22/.gitlab-ci.yml b/src/tests/ecoc22/.gitlab-ci.yml index 176301630..56db69560 100644 --- a/src/tests/ecoc22/.gitlab-ci.yml +++ b/src/tests/ecoc22/.gitlab-ci.yml @@ -19,6 +19,7 @@ build ecoc22: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,79 +47,18 @@ end2end_test ecoc22: #needs: # - build ecoc22 before_script: - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # Download Docker image to run the test - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest" - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components @@ -126,7 +66,6 @@ end2end_test ecoc22: #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml - #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml - source src/tests/${TEST_NAME}/deploy_specs.sh @@ -158,22 +97,18 @@ end2end_test ecoc22: after_script: # Dump TeraFlowSDN component logs + - mkdir -p src/tests/${TEST_NAME}/logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/sliceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server + - ./deploy/show.sh + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice-server.log 2>&1 || true # Clean up - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -183,3 +118,5 @@ end2end_test ecoc22: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/ecoc22/deploy_specs.sh b/src/tests/ecoc22/deploy_specs.sh index 0963b2c73..f3caf89b2 100755 --- a/src/tests/ecoc22/deploy_specs.sh +++ b/src/tests/ecoc22/deploy_specs.sh @@ -21,7 +21,7 @@ export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" # Set the list of components, separated by spaces, you want to build images for, and deploy. #export TFS_COMPONENTS="context device pathcomp service slice nbi webui load_generator" -export TFS_COMPONENTS="context device pathcomp service slice nbi webui" +export TFS_COMPONENTS="context device pathcomp service nbi webui" # Uncomment to activate Monitoring #export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" diff --git a/src/tests/eucnc24/.gitlab-ci.yml b/src/tests/eucnc24/.gitlab-ci.yml index 794f858e1..2521dd1e6 100644 --- a/src/tests/eucnc24/.gitlab-ci.yml +++ b/src/tests/eucnc24/.gitlab-ci.yml @@ -19,6 +19,7 @@ build eucnc24: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,83 +47,16 @@ end2end_test eucnc24: #needs: # - build eucnc24 before_script: - # Cleanup old ContainerLab scenarios - - containerlab destroy --all --cleanup || true - - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # Download Docker image to run the test - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest" - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - # Deploy ContainerLab Scenario - RUNNER_PATH=`pwd` #- cd $PWD/src/tests/${TEST_NAME} @@ -142,6 +76,9 @@ end2end_test eucnc24: - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh + # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml @@ -287,17 +224,19 @@ end2end_test eucnc24: after_script: # Dump configuration of the routers (on after_script) - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r1 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + - mkdir -p src/tests/${TEST_NAME}/logs + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r1 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r1-running-config.log 2>&1 || true + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r2-running-config.log 2>&1 || true + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r3-running-config.log 2>&1 || true # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server + - ./deploy/show.sh + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice-server.log 2>&1 || true # Clean up - RUNNER_PATH=`pwd` @@ -307,12 +246,7 @@ end2end_test eucnc24: - sudo rm -rf clab-${TEST_NAME}/ .${TEST_NAME}.clab.yml.bak || true - cd $RUNNER_PATH - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -322,3 +256,5 @@ end2end_test eucnc24: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/l2_vpn_gnmi_oc/.gitlab-ci.yml b/src/tests/l2_vpn_gnmi_oc/.gitlab-ci.yml index 5fe373607..52fbb9f57 100644 --- a/src/tests/l2_vpn_gnmi_oc/.gitlab-ci.yml +++ b/src/tests/l2_vpn_gnmi_oc/.gitlab-ci.yml @@ -19,6 +19,7 @@ build l2_vpn_gnmi_oc: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,83 +47,16 @@ end2end_test l2_vpn_gnmi_oc: #needs: # - build l2_vpn_gnmi_oc before_script: - # Cleanup old ContainerLab scenarios - - containerlab destroy --all --cleanup || true - - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # Download Docker image to run the test - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest" - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - # Deploy ContainerLab Scenario - RUNNER_PATH=`pwd` #- cd $PWD/src/tests/${TEST_NAME} @@ -142,6 +76,9 @@ end2end_test l2_vpn_gnmi_oc: - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh + # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml @@ -303,17 +240,19 @@ end2end_test l2_vpn_gnmi_oc: after_script: # Dump configuration of the routers (on after_script) - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r1 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + - mkdir -p src/tests/${TEST_NAME}/logs + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r1 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r1-running-config.log 2>&1 || true + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r2-running-config.log 2>&1 || true + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r3-running-config.log 2>&1 || true # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server + - ./deploy/show.sh + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice-server.log 2>&1 || true # Clean up - RUNNER_PATH=`pwd` @@ -323,12 +262,7 @@ end2end_test l2_vpn_gnmi_oc: - sudo rm -rf clab-${TEST_NAME}/ .${TEST_NAME}.clab.yml.bak || true - cd $RUNNER_PATH - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -338,3 +272,5 @@ end2end_test l2_vpn_gnmi_oc: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/ofc22/.gitlab-ci.yml b/src/tests/ofc22/.gitlab-ci.yml index 4bd6ada0b..84b94c02c 100644 --- a/src/tests/ofc22/.gitlab-ci.yml +++ b/src/tests/ofc22/.gitlab-ci.yml @@ -19,6 +19,7 @@ build ofc22: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,79 +47,18 @@ end2end_test ofc22: #needs: # - build ofc22 before_script: - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # Download Docker image to run the test - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest" - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components @@ -126,7 +66,6 @@ end2end_test ofc22: #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml - #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/monitoringservice.yaml @@ -160,25 +99,20 @@ end2end_test ofc22: after_script: # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - rm -rf src/tests/${TEST_NAME}/component_logs - - mkdir -p src/tests/${TEST_NAME}/component_logs - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/contextservice -c server > src/tests/${TEST_NAME}/component_logs/contextservice.log 2>&1 || true - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/deviceservice -c server > src/tests/${TEST_NAME}/component_logs/deviceservice.log 2>&1 || true - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/component_logs/pathcompservice-frontend.log 2>&1 || true - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/serviceservice -c server > src/tests/${TEST_NAME}/component_logs/serviceservice.log 2>&1 || true - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/sliceservice -c server > src/tests/${TEST_NAME}/component_logs/sliceservice.log 2>&1 || true - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/nbiservice -c server > src/tests/${TEST_NAME}/component_logs/nbiservice.log 2>&1 || true - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/monitoringservice -c server > src/tests/${TEST_NAME}/component_logs/monitoringservice.log 2>&1 || true - - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/ztpservice -c ztpservice > src/tests/${TEST_NAME}/component_logs/ztpservice.log 2>&1 || true + - ./deploy/show.sh + - rm -rf src/tests/${TEST_NAME}/logs + - mkdir -p src/tests/${TEST_NAME}/logs + - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice.log 2>&1 || true + - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice.log 2>&1 || true + - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice.log 2>&1 || true + - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice.log 2>&1 || true + - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/monitoringservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_monitoringservice.log 2>&1 || true + - kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/ztpservice -c ztpservice > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_ztpservice.log 2>&1 || true # Clean up - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -189,4 +123,4 @@ end2end_test ofc22: reports: junit: ./src/tests/${TEST_NAME}/report_*.xml paths: - - ./src/tests/${TEST_NAME}/component_logs/*.log + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/ofc22/deploy_specs.sh b/src/tests/ofc22/deploy_specs.sh index 04ad48125..5330572ab 100755 --- a/src/tests/ofc22/deploy_specs.sh +++ b/src/tests/ofc22/deploy_specs.sh @@ -21,7 +21,7 @@ export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" # Set the list of components, separated by spaces, you want to build images for, and deploy. #export TFS_COMPONENTS="context device pathcomp service slice nbi webui load_generator" -export TFS_COMPONENTS="context device pathcomp service slice nbi webui" +export TFS_COMPONENTS="context device pathcomp service nbi webui" # Uncomment to activate Monitoring export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" diff --git a/src/tests/ofc24/.gitlab-ci.yml b/src/tests/ofc24/.gitlab-ci.yml index c32f0900d..7f8ec8bde 100644 --- a/src/tests/ofc24/.gitlab-ci.yml +++ b/src/tests/ofc24/.gitlab-ci.yml @@ -19,6 +19,7 @@ build ofc24: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,58 +47,10 @@ end2end_test ofc24: #needs: # - build ofc24 before_script: - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: @@ -106,22 +59,6 @@ end2end_test ofc24: - docker pull asgamb1/oc23bgp.img:latest - docker pull asgamb1/flexscale-node.img:latest - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - # Deploy Optical Device Node Agents - > docker network create -d bridge --subnet=172.254.253.0/24 --gateway=172.254.253.254 @@ -159,13 +96,15 @@ end2end_test ofc24: - docker ps -a + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh + # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml - #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml - source src/tests/${TEST_NAME}/deploy_specs.sh @@ -197,29 +136,26 @@ end2end_test ofc24: after_script: # Dump Optical Device Node Agents container status and logs - - docker ps -a - - docker logs na-t1 - - docker logs na-t2 - - docker logs na-r1 - - docker logs na-r2 + - mkdir -p src/tests/${TEST_NAME}/logs + - docker ps -a > src/tests/${TEST_NAME}/logs/runner_docker-ps.log 2>&1 || true + - docker logs na-t1 > src/tests/${TEST_NAME}/logs/agent_na-t1.log 2>&1 || true + - docker logs na-t2 > src/tests/${TEST_NAME}/logs/agent_na-t2.log 2>&1 || true + - docker logs na-r1 > src/tests/${TEST_NAME}/logs/agent_na-r1.log 2>&1 || true + - docker logs na-r2 > src/tests/${TEST_NAME}/logs/agent_na-r2.log 2>&1 || true # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/opticalcontrollerservice -c server + - ./deploy/show.sh + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/opticalcontrollerservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_opticalcontrollerservice-server.log 2>&1 || true # Clean up - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -229,3 +165,5 @@ end2end_test ofc24: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/ofc25-camara-agg-net-controller/.gitlab-ci.yml b/src/tests/ofc25-camara-agg-net-controller/.gitlab-ci.yml index f5d8c20be..8cacc948e 100644 --- a/src/tests/ofc25-camara-agg-net-controller/.gitlab-ci.yml +++ b/src/tests/ofc25-camara-agg-net-controller/.gitlab-ci.yml @@ -22,6 +22,8 @@ end2end_test ofc25_camara_agg_net: stage: end2end_test # Disable to force running it after all other tasks before_script: + - bash scripts/ci_cleanup_gitlab_runner.sh + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - HOST_IP=$(kubectl get nodes -o json | jq -r '.items[].status.addresses[] | select(.type=="InternalIP") | .address') - sed -i "s/IP_NET_IP/${HOST_IP}/g" src/tests/${TEST_NAME}/data/agg-net-descriptor.json @@ -33,9 +35,8 @@ end2end_test ofc25_camara_agg_net: - docker run -d --name ${IP_NAME} -p ${IP_PORT}:8443 ${IP_NAME}:latest script: - # Check MicroK8s is ready - - microk8s status --wait-ready - - kubectl get pods --all-namespaces + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh - source src/tests/${TEST_NAME}/deploy_specs.sh @@ -64,13 +65,14 @@ end2end_test ofc25_camara_agg_net: ${TEST_NAME}:latest /var/teraflow/run-agg-net-ietf-slice-operations.sh after_script: - - kubectl --namespace tfs logs deployment/contextservice -c server - - kubectl --namespace tfs logs deployment/deviceservice -c server - - kubectl --namespace tfs logs deployment/pathcompservice -c frontend - - kubectl --namespace tfs logs deployment/serviceservice -c server - - kubectl --namespace tfs logs deployment/sliceservice -c server - - kubectl --namespace tfs logs deployment/nbiservice -c server - - docker logs ${IP_NAME} + - mkdir -p src/tests/${TEST_NAME}/logs + - kubectl --namespace tfs logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_contextservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_deviceservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_tfs_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace tfs logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_serviceservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/sliceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_sliceservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_nbiservice-server.log 2>&1 || true + - docker logs ${IP_NAME} > src/tests/${TEST_NAME}/logs/agent_${IP_NAME}.log 2>&1 || true # Destroy Scenario - kubectl delete namespaces tfs || true @@ -89,3 +91,5 @@ end2end_test ofc25_camara_agg_net: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/ofc25-camara-e2e-controller/.gitlab-ci.yml b/src/tests/ofc25-camara-e2e-controller/.gitlab-ci.yml index bfeb6fad7..41a8b7f92 100644 --- a/src/tests/ofc25-camara-e2e-controller/.gitlab-ci.yml +++ b/src/tests/ofc25-camara-e2e-controller/.gitlab-ci.yml @@ -24,6 +24,8 @@ end2end_test ofc25_camara_e2e: stage: end2end_test # Disable to force running it after all other tasks before_script: + - bash scripts/ci_cleanup_gitlab_runner.sh + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - HOST_IP=$(kubectl get nodes -o json | jq -r '.items[].status.addresses[] | select(.type=="InternalIP") | .address') - sed -i "s/AGG_NET_IP/${HOST_IP}/g" src/tests/${TEST_NAME}/data/camara-e2e-topology.json @@ -40,9 +42,8 @@ end2end_test ofc25_camara_e2e: - docker run -d --name ${AGG_NET_NAME} -p ${AGG_NET_PORT}:8443 ${AGG_NET_NAME}:latest script: - # Check MicroK8s is ready - - microk8s status --wait-ready - - kubectl get pods --all-namespaces + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh - source src/tests/${TEST_NAME}/deploy_specs.sh @@ -71,16 +72,17 @@ end2end_test ofc25_camara_e2e: ${TEST_NAME}:latest /var/teraflow/run-e2e-ietf-slice-operations.sh after_script: - - kubectl --namespace tfs logs deployment/contextservice -c server - - kubectl --namespace tfs logs deployment/deviceservice -c server - - kubectl --namespace tfs logs deployment/pathcompservice -c frontend - - kubectl --namespace tfs logs deployment/serviceservice -c server - - kubectl --namespace tfs logs deployment/sliceservice -c server - - kubectl --namespace tfs logs deployment/nbiservice -c server + - mkdir -p src/tests/${TEST_NAME}/logs + - kubectl --namespace tfs logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_contextservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_deviceservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_tfs_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace tfs logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_serviceservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/sliceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_sliceservice-server.log 2>&1 || true + - kubectl --namespace tfs logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs_nbiservice-server.log 2>&1 || true - - docker logs ${NCE_NAME} + - docker logs ${NCE_NAME} > src/tests/${TEST_NAME}/logs/agent_${NCE_NAME}.log 2>&1 || true - - docker logs ${AGG_NET_NAME} + - docker logs ${AGG_NET_NAME} > src/tests/${TEST_NAME}/logs/agent_${AGG_NET_NAME}.log 2>&1 || true # Destroy Scenario - kubectl delete namespaces tfs || true @@ -100,3 +102,5 @@ end2end_test ofc25_camara_e2e: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/ofc25/.gitlab-ci.yml b/src/tests/ofc25/.gitlab-ci.yml index b05ffae4d..4777cf4dd 100644 --- a/src/tests/ofc25/.gitlab-ci.yml +++ b/src/tests/ofc25/.gitlab-ci.yml @@ -19,6 +19,7 @@ build ofc25: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,63 +47,10 @@ end2end_test ofc25: #needs: # - build ofc25 before_script: - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Delete secondary ingress controllers - - kubectl delete -f src/tests/${TEST_NAME}/nginx-ingress-controller-opt.yaml --ignore-not-found - - kubectl delete -f src/tests/${TEST_NAME}/nginx-ingress-controller-ip.yaml --ignore-not-found - - kubectl delete -f src/tests/${TEST_NAME}/nginx-ingress-controller-e2e.yaml --ignore-not-found - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: @@ -111,22 +59,6 @@ end2end_test ofc25: - docker pull asgamb1/oc23bgp.img:latest - docker pull asgamb1/flexscale-node.img:latest - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - # Deploy Optical Device Node Agents - > docker network create -d bridge --subnet=172.254.253.0/24 --gateway=172.254.253.254 @@ -170,13 +102,20 @@ end2end_test ofc25: #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml - #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/opticalcontrollerservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/e2e_orchestratorservice.yaml #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/vnt_managerservice.yaml + # Delete secondary ingress controllers + - kubectl delete -f src/tests/${TEST_NAME}/nginx-ingress-controller-opt.yaml --ignore-not-found + - kubectl delete -f src/tests/${TEST_NAME}/nginx-ingress-controller-ip.yaml --ignore-not-found + - kubectl delete -f src/tests/${TEST_NAME}/nginx-ingress-controller-e2e.yaml --ignore-not-found + + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh + # ===== Deploy Optical TeraFlowSDN ================================================== - source src/tests/${TEST_NAME}/deploy_specs_opt.sh @@ -274,44 +213,46 @@ end2end_test ofc25: $CI_REGISTRY_IMAGE/${TEST_NAME}:latest after_script: + - source src/tests/${TEST_NAME}/deploy_specs_opt.sh + - ./deploy/show.sh + - source src/tests/${TEST_NAME}/deploy_specs_ip.sh + - ./deploy/show.sh + - source src/tests/${TEST_NAME}/deploy_specs_e2e.sh + - ./deploy/show.sh + # Persist TeraFlowSDN and node-agent logs as artifacts instead of dumping them into the CI job log - mkdir -p src/tests/${TEST_NAME}/logs - - kubectl logs --namespace tfs-e2e deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/e2e-contextservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-e2e deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/e2e-deviceservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-e2e deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/e2e-serviceservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-e2e deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/e2e-pathcompservice-frontend.log 2>&1 || true - - kubectl logs --namespace tfs-e2e deployment/pathcompservice -c backend > src/tests/${TEST_NAME}/logs/e2e-pathcompservice-backend.log 2>&1 || true - - kubectl logs --namespace tfs-e2e deployment/webuiservice -c server > src/tests/${TEST_NAME}/logs/e2e-webuiservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-e2e deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/e2e-nbiservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-e2e deployment/e2e-orchestratorservice -c server > src/tests/${TEST_NAME}/logs/e2e-e2e-orchestratorservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/ip-contextservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/ip-deviceservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/ip-serviceservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/ip-pathcompservice-frontend.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/pathcompservice -c backend > src/tests/${TEST_NAME}/logs/ip-pathcompservice-backend.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/webuiservice -c server > src/tests/${TEST_NAME}/logs/ip-webuiservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/ip-nbiservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-ip deployment/vnt-managerservice -c server > src/tests/${TEST_NAME}/logs/ip-vnt-managerservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/opt-contextservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/opt-deviceservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/opt-serviceservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/opt-pathcompservice-frontend.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/pathcompservice -c backend > src/tests/${TEST_NAME}/logs/opt-pathcompservice-backend.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/webuiservice -c server > src/tests/${TEST_NAME}/logs/opt-webuiservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/opt-nbiservice-server.log 2>&1 || true - - kubectl logs --namespace tfs-opt deployment/opticalcontrollerservice -c server > src/tests/${TEST_NAME}/logs/opt-opticalcontrollerservice-server.log 2>&1 || true - - docker logs na-t1 > src/tests/${TEST_NAME}/logs/na-na-t1.log 2>&1 || true - - docker logs na-t2 > src/tests/${TEST_NAME}/logs/na-na-t2.log 2>&1 || true - - docker logs na-r1 > src/tests/${TEST_NAME}/logs/na-na-r1.log 2>&1 || true - - docker logs na-r2 > src/tests/${TEST_NAME}/logs/na-na-r2.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_contextservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_deviceservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_serviceservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_pathcompservice-frontend.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/pathcompservice -c backend > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_pathcompservice-backend.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/webuiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_webuiservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_nbiservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-e2e deployment/e2e-orchestratorservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-e2e_e2e-orchestratorservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_contextservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_deviceservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_serviceservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_pathcompservice-frontend.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/pathcompservice -c backend > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_pathcompservice-backend.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/webuiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_webuiservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_nbiservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-ip deployment/vnt-managerservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-ip_vnt-managerservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_contextservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_deviceservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_serviceservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_pathcompservice-frontend.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/pathcompservice -c backend > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_pathcompservice-backend.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/webuiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_webuiservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_nbiservice-server.log 2>&1 || true + - kubectl logs --namespace tfs-opt deployment/opticalcontrollerservice -c server > src/tests/${TEST_NAME}/logs/tfs_tfs-opt_opticalcontrollerservice-server.log 2>&1 || true + - docker logs na-t1 > src/tests/${TEST_NAME}/logs/agent_na-t1.log 2>&1 || true + - docker logs na-t2 > src/tests/${TEST_NAME}/logs/agent_na-t2.log 2>&1 || true + - docker logs na-r1 > src/tests/${TEST_NAME}/logs/agent_na-r1.log 2>&1 || true + - docker logs na-r2 > src/tests/${TEST_NAME}/logs/agent_na-r2.log 2>&1 || true # Clean up - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh - kubectl delete namespaces tfs-ip tfs-opt tfs-e2e --ignore-not-found - kubectl delete -f src/tests/${TEST_NAME}/nginx-ingress-controller-opt.yaml --ignore-not-found diff --git a/src/tests/ofc25/deploy_all_in_one.sh b/src/tests/ofc25/deploy_all_in_one.sh index bf37a34fe..d41b085a4 100755 --- a/src/tests/ofc25/deploy_all_in_one.sh +++ b/src/tests/ofc25/deploy_all_in_one.sh @@ -41,7 +41,6 @@ kubectl get pods --all-namespaces #yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/deviceservice.yaml #yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="frontend").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/pathcompservice.yaml #yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/serviceservice.yaml -#yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/sliceservice.yaml #yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/nbiservice.yaml #yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/e2eorchestratorservice.yaml #yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/vntmservice.yaml diff --git a/src/tests/osm_end2end/.gitlab-ci.yml b/src/tests/osm_end2end/.gitlab-ci.yml index 66e4eef9e..1df4b90cb 100644 --- a/src/tests/osm_end2end/.gitlab-ci.yml +++ b/src/tests/osm_end2end/.gitlab-ci.yml @@ -19,6 +19,7 @@ build osm_end2end: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,83 +47,16 @@ end2end_test osm_end2end: #needs: # - build osm_end2end before_script: - # Cleanup old ContainerLab scenarios - - containerlab destroy --all --cleanup || true - - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: # Download Docker image to run the test - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}:latest" - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - # Deploy ContainerLab Scenario - RUNNER_PATH=`pwd` #- cd $PWD/src/tests/${TEST_NAME} @@ -142,6 +76,9 @@ end2end_test osm_end2end: - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh + # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml @@ -267,19 +204,22 @@ end2end_test osm_end2end: after_script: # Dump configuration of the routers (on after_script) - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r1 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" - - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" + - mkdir -p src/tests/${TEST_NAME}/logs + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r1 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r1-running-config.log 2>&1 || true + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r2-running-config.log 2>&1 || true + - containerlab exec --name ${TEST_NAME} --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'$"show running-config\"" > src/tests/${TEST_NAME}/logs/agent_r3-running-config.log 2>&1 || true # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - rm -rf src/tests/${TEST_NAME}/component_logs - - mkdir -p src/tests/${TEST_NAME}/component_logs - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/component_logs/contextservice.log 2>&1 || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/component_logs/deviceservice.log 2>&1 || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/component_logs/pathcompservice-frontend.log 2>&1 || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/component_logs/serviceservice.log 2>&1 || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/component_logs/nbiservice.log 2>&1 || true + - ./deploy/show.sh + + - rm -rf src/tests/${TEST_NAME}/logs + - mkdir -p src/tests/${TEST_NAME}/logs + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice.log 2>&1 || true # Clean up - RUNNER_PATH=`pwd` @@ -289,12 +229,7 @@ end2end_test osm_end2end: - sudo rm -rf clab-${TEST_NAME}/ .${TEST_NAME}.clab.yml.bak || true - cd $RUNNER_PATH - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -305,4 +240,4 @@ end2end_test osm_end2end: reports: junit: ./src/tests/${TEST_NAME}/report_*.xml paths: - - ./src/tests/${TEST_NAME}/component_logs/*.log + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/osm_end2end/run-local.sh b/src/tests/osm_end2end/run-local.sh index 3e7a01b74..62e631801 100755 --- a/src/tests/osm_end2end/run-local.sh +++ b/src/tests/osm_end2end/run-local.sh @@ -21,7 +21,7 @@ TEST_NAME="osm_end2end" IMAGE_TAG="${OSM_E2E_IMAGE:-${TEST_NAME}:local}" RESULTS_DIR="${OSM_E2E_RESULTS_DIR:-${SCRIPT_DIR}/local_results}" -COMPONENT_LOGS_DIR="${RESULTS_DIR}/component_logs" +LOGS_DIR="${RESULTS_DIR}/logs" CLAB_TMP_DIR="${OSM_E2E_CLAB_TMPDIR:-/tmp/clab/${TEST_NAME}}" RUNTIME_ENV_FILE="${REPO_ROOT}/tfs_runtime_env_vars.sh" @@ -173,16 +173,17 @@ dump_router_configs() { local label=$1 local slug slug="$(echo "${label}" | tr ' /' '__')" + mkdir -p "${LOGS_DIR}" { echo "==== ${label} ====" clab exec --name "${TEST_NAME}" --label clab-node-name=r1 --cmd "Cli --command \"enable"$'\n'"show running-config\"" clab exec --name "${TEST_NAME}" --label clab-node-name=r2 --cmd "Cli --command \"enable"$'\n'"show running-config\"" clab exec --name "${TEST_NAME}" --label clab-node-name=r3 --cmd "Cli --command \"enable"$'\n'"show running-config\"" - } | tee "${RESULTS_DIR}/router-config-${slug}.log" + } | tee "${LOGS_DIR}/agent_router-config-${slug}.log" } -dump_component_logs() { - mkdir -p "${COMPONENT_LOGS_DIR}" +dump_tfs_logs() { + mkdir -p "${LOGS_DIR}" local namespace="${TFS_K8S_NAMESPACE:-tfs}" local components=( contextservice:server @@ -196,7 +197,7 @@ dump_component_logs() { deployment="${entry%%:*}" container="${entry##*:}" kctl --namespace "${namespace}" logs "deployment/${deployment}" -c "${container}" \ - > "${COMPONENT_LOGS_DIR}/${deployment}.log" 2>&1 || true + > "${LOGS_DIR}/tfs_${namespace}_${deployment}-${container}.log" 2>&1 || true done } @@ -334,7 +335,7 @@ run_all() { dump_router_configs "after onboarding scenario" run_variant_cycle "untagged" "dc1_untagged" "172.16.1.10" "172.16.1.1" "172.16.3.1" "172.16.3.10" run_variant_cycle "tagged" "dc3_tagged" "172.17.1.10" "172.17.1.1" "172.17.3.1" "172.17.3.10" - dump_component_logs + dump_tfs_logs } main() { @@ -349,7 +350,7 @@ main() { onboarding) run_onboarding ;; untagged) run_variant_cycle "untagged" "dc1_untagged" "172.16.1.10" "172.16.1.1" "172.16.3.1" "172.16.3.10" ;; tagged) run_variant_cycle "tagged" "dc3_tagged" "172.17.1.10" "172.17.1.1" "172.17.3.1" "172.17.3.10" ;; - logs) dump_component_logs ;; + logs) dump_tfs_logs ;; destroy-clab) destroy_clab ;; -h|--help|help) usage ;; *) diff --git a/src/tests/qkd_end2end/.gitlab-ci.yml b/src/tests/qkd_end2end/.gitlab-ci.yml index becf525a8..694feca17 100644 --- a/src/tests/qkd_end2end/.gitlab-ci.yml +++ b/src/tests/qkd_end2end/.gitlab-ci.yml @@ -19,6 +19,7 @@ build qkd_end2end: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "${TEST_NAME}:latest" -f ./src/tests/${TEST_NAME}/Dockerfile . @@ -46,58 +47,10 @@ end2end_test qkd_end2end: #needs: # - build qkd_end2end before_script: - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: @@ -160,21 +113,8 @@ end2end_test qkd_end2end: - curl "http://172.254.250.103:8080/restconf/data/etsi-qkd-sdn-node:" - echo - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components @@ -314,40 +254,30 @@ end2end_test qkd_end2end: after_script: # Dump logs of the QKD Nodes (after_script) - - docker ps -a - - docker logs qkd-node-01 - - docker logs qkd-node-02 - - docker logs qkd-node-03 + - mkdir -p src/tests/${TEST_NAME}/logs + - docker ps -a > src/tests/${TEST_NAME}/logs/runner_docker-ps.log 2>&1 || true + - docker logs qkd-node-01 > src/tests/${TEST_NAME}/logs/agent_qkd-node-01.log 2>&1 || true + - docker logs qkd-node-02 > src/tests/${TEST_NAME}/logs/agent_qkd-node-02.log 2>&1 || true + - docker logs qkd-node-03 > src/tests/${TEST_NAME}/logs/agent_qkd-node-03.log 2>&1 || true # Dump configuration of the QKD Nodes (after_script) - - echo "[QKD-NODE-01] Config after_script:" - - curl "http://172.254.250.101:8080/restconf/data/etsi-qkd-sdn-node:" - - echo - - echo "[QKD-NODE-02] Config after_script:" - - curl "http://172.254.250.102:8080/restconf/data/etsi-qkd-sdn-node:" - - echo - - echo "[QKD-NODE-03] Config after_script:" - - curl "http://172.254.250.103:8080/restconf/data/etsi-qkd-sdn-node:" - - echo + - curl "http://172.254.250.101:8080/restconf/data/etsi-qkd-sdn-node:" > src/tests/${TEST_NAME}/logs/agent_qkd-node-01-config.json 2>&1 || true + - curl "http://172.254.250.102:8080/restconf/data/etsi-qkd-sdn-node:" > src/tests/${TEST_NAME}/logs/agent_qkd-node-02-config.json 2>&1 || true + - curl "http://172.254.250.103:8080/restconf/data/etsi-qkd-sdn-node:" > src/tests/${TEST_NAME}/logs/agent_qkd-node-03-config.json 2>&1 || true # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/qkd-appservice -c server + - ./deploy/show.sh + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/qkd-appservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_qkd-appservice-server.log 2>&1 || true # Clean up - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -357,3 +287,5 @@ end2end_test qkd_end2end: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/* diff --git a/src/tests/ryu-openflow/.gitlab-ci.yml b/src/tests/ryu-openflow/.gitlab-ci.yml index e8803e5b1..a23a35503 100644 --- a/src/tests/ryu-openflow/.gitlab-ci.yml +++ b/src/tests/ryu-openflow/.gitlab-ci.yml @@ -20,6 +20,7 @@ build ryu-openflow: IMAGE_TAG: 'mr$CI_MERGE_REQUEST_IID' stage: build before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker ps -aq | xargs -r docker rm -f script: @@ -57,58 +58,10 @@ end2end_test ryu-openflow: #needs: # - build ryu-openflow before_script: - # Do Docker cleanup - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker image prune --force - - docker network prune --force - - docker volume prune --all --force - - docker buildx prune --force - - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - - # Always delete Kubernetes namespaces - - export K8S_NAMESPACES=$(kubectl get namespace -o jsonpath='{.items[*].metadata.name}') - - echo "K8S_NAMESPACES=${K8S_NAMESPACES}" - - - export OLD_NATS_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^nats') - - echo "OLD_NATS_NAMESPACES=${OLD_NATS_NAMESPACES}" - - > - for ns in ${OLD_NATS_NAMESPACES}; do - if [[ "$ns" == nats* ]]; then - if helm3 status "$ns" &>/dev/null; then - helm3 uninstall "$ns" -n "$ns" - else - echo "Release '$ns' not found, skipping..." - fi - fi - done - - export OLD_NAMESPACES=$(echo "${K8S_NAMESPACES}" | tr ' ' '\n' | grep -E '^(tfs|crdb|qdb|kafka|nats)') - - echo "OLD_NAMESPACES=${OLD_NAMESPACES}" - - kubectl delete namespace ${OLD_NAMESPACES} || true - - # Clean-up Kubernetes Failed pods - - > - kubectl get pods --all-namespaces --no-headers --field-selector=status.phase=Failed - -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name | - xargs --no-run-if-empty --max-args=2 kubectl delete pod --namespace + - bash scripts/ci_cleanup_gitlab_runner.sh # Login Docker repository + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: @@ -117,22 +70,6 @@ end2end_test ryu-openflow: - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}-mininet:${IMAGE_TAG}" - docker pull "${CI_REGISTRY_IMAGE}/${TEST_NAME}-test:${IMAGE_TAG}" - # Check MicroK8s is ready - - microk8s status --wait-ready - - LOOP_MAX_ATTEMPTS=10 - - LOOP_COUNTER=0 - - > - while ! kubectl get pods --all-namespaces &> /dev/null; do - printf "%c" "." - sleep 1 - LOOP_COUNTER=$((LOOP_COUNTER + 1)) - if [ "$LOOP_COUNTER" -ge "$LOOP_MAX_ATTEMPTS" ]; then - echo "Max attempts reached, exiting the loop." - exit 1 - fi - done - - kubectl get pods --all-namespaces - # Deploy Docker network - > docker network create --driver bridge --subnet=172.254.252.0/24 --gateway=172.254.252.254 @@ -221,6 +158,9 @@ end2end_test ryu-openflow: - docker exec mininet bash -c "ovs-ofctl dump-flows s4" - docker exec mininet bash -c "ovs-ofctl dump-flows s5" + # Prepare Kubernetes storage and registry + - bash scripts/ci_prepare_microk8s_storage_registry.sh + # Configure TeraFlowSDN deployment # Uncomment if DEBUG log level is needed for the components #- yq -i '((select(.kind=="Deployment").spec.template.spec.containers.[] | select(.name=="server").env.[]) | select(.name=="LOG_LEVEL").value) |= "DEBUG"' manifests/contextservice.yaml @@ -430,34 +370,31 @@ end2end_test ryu-openflow: after_script: # Dump configuration of the switches (OpenFlow rules configured) (on after_script) - - docker exec mininet bash -c "ovs-vsctl show" || true - - docker exec mininet ovs-ofctl dump-flows s1 || true - - docker exec mininet ovs-ofctl dump-flows s2 || true - - docker exec mininet ovs-ofctl dump-flows s3 || true - - docker exec mininet ovs-ofctl dump-flows s4 || true - - docker exec mininet ovs-ofctl dump-flows s5 || true + - mkdir -p src/tests/${TEST_NAME}/logs + - docker exec mininet bash -c "ovs-vsctl show" > src/tests/${TEST_NAME}/logs/agent_mininet-ovs-vsctl-show.log 2>&1 || true + - docker exec mininet ovs-ofctl dump-flows s1 > src/tests/${TEST_NAME}/logs/agent_mininet-s1-flows.log 2>&1 || true + - docker exec mininet ovs-ofctl dump-flows s2 > src/tests/${TEST_NAME}/logs/agent_mininet-s2-flows.log 2>&1 || true + - docker exec mininet ovs-ofctl dump-flows s3 > src/tests/${TEST_NAME}/logs/agent_mininet-s3-flows.log 2>&1 || true + - docker exec mininet ovs-ofctl dump-flows s4 > src/tests/${TEST_NAME}/logs/agent_mininet-s4-flows.log 2>&1 || true + - docker exec mininet ovs-ofctl dump-flows s5 > src/tests/${TEST_NAME}/logs/agent_mininet-s5-flows.log 2>&1 || true # Dump Ryu and Mininet logs (on after_script) - - docker ps -a + - docker ps -a > src/tests/${TEST_NAME}/logs/runner_docker-ps.log 2>&1 || true #- docker logs mininet - - docker logs ryu + - docker logs ryu > src/tests/${TEST_NAME}/logs/agent_ryu.log 2>&1 || true # Dump TeraFlowSDN component logs - source src/tests/${TEST_NAME}/deploy_specs.sh - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server || true - - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server || true + - ./deploy/show.sh + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_contextservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/deviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_deviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/pathcompservice -c frontend > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_pathcompservice-frontend.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/serviceservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_serviceservice-server.log 2>&1 || true + - kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/nbiservice -c server > src/tests/${TEST_NAME}/logs/tfs_${TFS_K8S_NAMESPACE}_nbiservice-server.log 2>&1 || true # Clean up - kubectl delete namespaces tfs || true - - docker ps --all --quiet | xargs --no-run-if-empty docker stop - - docker container prune --force - - docker ps --all --quiet | xargs --no-run-if-empty docker rm --force - - docker network prune --force - - docker volume prune --all --force - - docker image prune --force + - bash scripts/ci_cleanup_gitlab_runner.sh #coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' rules: @@ -467,3 +404,5 @@ end2end_test ryu-openflow: when: always reports: junit: ./src/tests/${TEST_NAME}/report_*.xml + paths: + - ./src/tests/${TEST_NAME}/logs/*.log diff --git a/src/tests/spectrum_negotiation/README.md b/src/tests/spectrum_negotiation/README.md new file mode 100644 index 000000000..7b439b1a8 --- /dev/null +++ b/src/tests/spectrum_negotiation/README.md @@ -0,0 +1,41 @@ +# Spectrum Negotiation Integration Tests + +This folder contains executable integration-test seeds for the optical +spectrum reservation workflow used by the prototype. + +These tests are intentionally not wired into GitLab CI yet. They require a +running TeraFlowSDN deployment with: + +- TFS-API reachable over HTTP. +- At least one context and topology loaded. +- Optical links exposed through `/tfs-api/optical_links`. +- Optical spectrum reservation endpoints exposed through `/tfs-api/context//...`. + +## Live Reservation Validation + +Run against a local TFS deployment: + +```bash +python3 src/tests/spectrum_negotiation/live_reservation_validation.py +``` + +Run against a specific testbed node: + +```bash +python3 src/tests/spectrum_negotiation/live_reservation_validation.py \ + --base-url http://172.16.0.101/tfs-api +``` + +The script validates: + +- TFS-API context and topology discovery. +- Optical link inventory discovery. +- Creation of a temporary optical spectrum reservation. +- Retrieval of the reservation in `RESERVED` state. +- Rejection of an overlapping reservation. +- Rejection of a reservation over an unavailable slot. +- Release of the temporary reservation. +- Final cleanup verification that no active `codex-live-test` reservation remains. + +Expected rejection status for overlapping or occupied-slot requests is HTTP +`409 Conflict`, mapped from gRPC `ALREADY_EXISTS`. diff --git a/src/tests/spectrum_negotiation/live_reservation_validation.py b/src/tests/spectrum_negotiation/live_reservation_validation.py new file mode 100644 index 000000000..7329abfad --- /dev/null +++ b/src/tests/spectrum_negotiation/live_reservation_validation.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import json +import time +import urllib.error +import urllib.parse +import urllib.request + +DEFAULT_BASE_URL = 'http://127.0.0.1/tfs-api' +OWNER_ID = 'codex-live-test' + + +def http_request(base_url, method, path, payload=None, timeout=15): + data = None + headers = {} + if payload is not None: + data = json.dumps(payload).encode('utf-8') + headers['Content-Type'] = 'application/json' + request = urllib.request.Request(base_url + path, data=data, headers=headers, method=method) + try: + with urllib.request.urlopen(request, timeout=timeout) as response: + body = response.read().decode('utf-8') + return response.status, json.loads(body) if body else None + except urllib.error.HTTPError as exc: + body = exc.read().decode('utf-8') + try: + payload = json.loads(body) if body else None + except json.JSONDecodeError: + payload = body + return exc.code, payload + + +def first_context_and_topology(base_url): + status, contexts = http_request(base_url, 'GET', '/contexts') + assert status == 200, (status, contexts) + assert contexts.get('contexts'), contexts + context = contexts['contexts'][0] + assert context.get('topology_ids'), context + return ( + context['context_id']['context_uuid']['uuid'], + context['topology_ids'][0]['topology_uuid']['uuid'], + ) + + +def optical_link_slots(link): + return link.get('optical_details', {}).get('c_slots', {}) + + +def optical_link_uuid(link): + return link['link_id']['link_uuid']['uuid'] + + +def select_optical_link(base_url, n_start, n_end): + status, optical_links = http_request(base_url, 'GET', '/optical_links') + assert status == 200, (status, optical_links) + links = optical_links.get('optical_links', []) + assert links, 'No optical links exposed by TFS-API' + + candidate = None + unavailable = None + for link in links: + link_uuid = optical_link_uuid(link) + c_slots = optical_link_slots(link) + if candidate is None and all(c_slots.get(str(slot)) == 1 for slot in range(n_start, n_end + 1)): + candidate = (link_uuid, c_slots) + if unavailable is None: + for slot, state in c_slots.items(): + if state != 1: + unavailable = (link_uuid, int(slot), state) + break + if candidate and unavailable: + break + + assert candidate is not None, 'No optical link has the requested validation slots available' + return len(links), candidate[0], unavailable + + +def reservation_payload(context_uuid, topology_uuid, reservation_uuid, link_uuid, n_start, n_end): + return { + 'reservation_id': { + 'context_id': {'context_uuid': {'uuid': context_uuid}}, + 'reservation_uuid': {'uuid': reservation_uuid}, + }, + 'topology_id': { + 'context_id': {'context_uuid': {'uuid': context_uuid}}, + 'topology_uuid': {'uuid': topology_uuid}, + }, + 'optical_link_ids': [{'link_uuid': {'uuid': link_uuid}}], + 'band': 'c_slots', + 'n_start': n_start, + 'n_end': n_end, + 'required_slots': n_end - n_start + 1, + 'owner_id': OWNER_ID, + 'correlation_id': reservation_uuid, + } + + +def active_test_reservations(reply): + reservations = reply.get('reservations', []) + return [ + reservation for reservation in reservations + if reservation.get('owner_id') == OWNER_ID + and reservation.get('status') not in ('OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED', 'RELEASED') + ] + + +def main(): + parser = argparse.ArgumentParser(description='Validate live optical spectrum reservation behavior through TFS-API.') + parser.add_argument('--base-url', default=DEFAULT_BASE_URL, help='TFS-API base URL, default: %(default)s') + parser.add_argument('--n-start', type=int, default=10, help='First validation slot, default: %(default)s') + parser.add_argument('--n-end', type=int, default=25, help='Last validation slot, default: %(default)s') + args = parser.parse_args() + + context_uuid, topology_uuid = first_context_and_topology(args.base_url) + link_count, link_uuid, unavailable = select_optical_link(args.base_url, args.n_start, args.n_end) + list_path = '/context/{:s}/optical_spectrum_reservations'.format(urllib.parse.quote(context_uuid)) + + status, before = http_request(args.base_url, 'GET', list_path) + assert status == 200, (status, before) + + reservation_uuid = 'live-reservation-{:d}'.format(int(time.time())) + reservation = reservation_payload( + context_uuid, topology_uuid, reservation_uuid, link_uuid, args.n_start, args.n_end + ) + created = False + try: + status, create_reply = http_request(args.base_url, 'POST', list_path, reservation) + assert status == 200, (status, create_reply) + created = True + + get_path = '/context/{:s}/optical_spectrum_reservation/{:s}'.format( + urllib.parse.quote(context_uuid), urllib.parse.quote(reservation_uuid) + ) + status, got = http_request(args.base_url, 'GET', get_path) + assert status == 200, (status, got) + assert got.get('status') in ('OPTICALSPECTRUMRESERVATIONSTATUS_RESERVED', 'RESERVED'), got + + overlap_uuid = reservation_uuid + '-overlap' + overlap = reservation_payload( + context_uuid, topology_uuid, overlap_uuid, link_uuid, args.n_start + 10, args.n_end + 5 + ) + status, overlap_reply = http_request(args.base_url, 'POST', list_path, overlap) + assert status == 409, (status, overlap_reply) + + if unavailable is not None: + _, occupied_slot, _ = unavailable + occupied_uuid = reservation_uuid + '-occupied' + occupied = reservation_payload( + context_uuid, topology_uuid, occupied_uuid, link_uuid, occupied_slot, occupied_slot + ) + status, occupied_reply = http_request(args.base_url, 'POST', list_path, occupied) + assert status == 409, (status, occupied_reply) + + finally: + if created: + release_path = '/context/{:s}/optical_spectrum_reservation/{:s}/release'.format( + urllib.parse.quote(context_uuid), urllib.parse.quote(reservation_uuid) + ) + status, release_reply = http_request(args.base_url, 'POST', release_path) + assert status == 200, (status, release_reply) + + get_path = '/context/{:s}/optical_spectrum_reservation/{:s}'.format( + urllib.parse.quote(context_uuid), urllib.parse.quote(reservation_uuid) + ) + status, got = http_request(args.base_url, 'GET', get_path) + assert status == 200, (status, got) + assert got.get('status') in ('OPTICALSPECTRUMRESERVATIONSTATUS_RELEASED', 'RELEASED'), got + + status, after = http_request(args.base_url, 'GET', list_path) + assert status == 200, (status, after) + assert not active_test_reservations(after), after + + print('LIVE_RESERVATION_VALIDATION_OK') + print('context_uuid={:s}'.format(context_uuid)) + print('topology_uuid={:s}'.format(topology_uuid)) + print('optical_links={:d}'.format(link_count)) + print('selected_link={:s}'.format(link_uuid)) + print('reserved_slots={:d}-{:d}'.format(args.n_start, args.n_end)) + + +if __name__ == '__main__': + main() diff --git a/src/tests/tools/mock_osm_nbi/.gitlab-ci.yml b/src/tests/tools/mock_osm_nbi/.gitlab-ci.yml index e27a77617..7d8e66873 100644 --- a/src/tests/tools/mock_osm_nbi/.gitlab-ci.yml +++ b/src/tests/tools/mock_osm_nbi/.gitlab-ci.yml @@ -17,6 +17,7 @@ build mock_osm_nbi: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$CI_REGISTRY_IMAGE/mock-osm-nbi:test" -f ./src/tests/tools/mock_osm_nbi/Dockerfile ./src/tests/tools/mock_osm_nbi diff --git a/src/tests/tools/mock_qkd_node/.gitlab-ci.yml b/src/tests/tools/mock_qkd_node/.gitlab-ci.yml index 23fbb1af7..bc52bec18 100644 --- a/src/tests/tools/mock_qkd_node/.gitlab-ci.yml +++ b/src/tests/tools/mock_qkd_node/.gitlab-ci.yml @@ -17,6 +17,7 @@ build mock_qkd_node: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$CI_REGISTRY_IMAGE/mock-qkd-node:test" -f ./src/tests/tools/mock_qkd_node/Dockerfile ./src/tests/tools/mock_qkd_node diff --git a/src/tests/tools/mock_tfs_nbi_dependencies/.gitlab-ci.yml b/src/tests/tools/mock_tfs_nbi_dependencies/.gitlab-ci.yml index 7ca97363d..2d8ce9d2d 100644 --- a/src/tests/tools/mock_tfs_nbi_dependencies/.gitlab-ci.yml +++ b/src/tests/tools/mock_tfs_nbi_dependencies/.gitlab-ci.yml @@ -17,6 +17,7 @@ build mock_tfs_nbi_dependencies: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$CI_REGISTRY_IMAGE/mock_tfs_nbi_dependencies:test" -f ./src/tests/tools/mock_tfs_nbi_dependencies/Dockerfile . diff --git a/src/tests/tools/simap_datastore/.gitlab-ci.yml b/src/tests/tools/simap_datastore/.gitlab-ci.yml index e426d60f7..73da9e394 100644 --- a/src/tests/tools/simap_datastore/.gitlab-ci.yml +++ b/src/tests/tools/simap_datastore/.gitlab-ci.yml @@ -17,6 +17,7 @@ build simap_datastore: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$CI_REGISTRY_IMAGE/simap-datastore:test" -f ./src/tests/tools/simap_datastore/Dockerfile . diff --git a/src/vnt_manager/.gitlab-ci.yml b/src/vnt_manager/.gitlab-ci.yml index 0016f1af6..c737c51a2 100644 --- a/src/vnt_manager/.gitlab-ci.yml +++ b/src/vnt_manager/.gitlab-ci.yml @@ -20,6 +20,7 @@ build vnt_manager: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . diff --git a/src/webui/.gitlab-ci.yml b/src/webui/.gitlab-ci.yml index 4b0189522..43848c2ab 100644 --- a/src/webui/.gitlab-ci.yml +++ b/src/webui/.gitlab-ci.yml @@ -20,6 +20,7 @@ build webui: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test webui: needs: - build webui before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi diff --git a/src/webui/service/device/routes.py b/src/webui/service/device/routes.py index 23a19278c..e1cfb000a 100644 --- a/src/webui/service/device/routes.py +++ b/src/webui/service/device/routes.py @@ -180,7 +180,20 @@ def detail(device_uuid: str): return render_template( 'device/detail.html', device=device_obj, dde=DeviceDriverEnum, dose=DeviceOperationalStatusEnum) - + +@device.route('detail//update_inventory', methods=['GET', 'POST']) +def update_inventory(device_uuid: str): + try: + device_id = DeviceId() + device_id.device_uuid.uuid = device_uuid + device_client.connect() + device_client.UpdateDeviceInventory(device_id) + device_client.close() + flash(f'Inventory of device "{device_uuid}" was successfully updated.', 'success') + except Exception as e: + flash(f'Problem updating inventory of device "{device_uuid}": {str(e)}', 'danger') + return redirect(url_for('device.detail', device_uuid=device_uuid)) + @device.route('inventory/', methods=['GET', 'POST']) def inventory(device_uuid: str): context_client.connect() diff --git a/src/webui/service/templates/device/detail.html b/src/webui/service/templates/device/detail.html index 75952ba1d..c2b633f01 100644 --- a/src/webui/service/templates/device/detail.html +++ b/src/webui/service/templates/device/detail.html @@ -39,6 +39,12 @@ Delete device +
diff --git a/src/ztp/.gitlab-ci.yml b/src/ztp/.gitlab-ci.yml index 0f2cd6d13..80b813856 100644 --- a/src/ztp/.gitlab-ci.yml +++ b/src/ztp/.gitlab-ci.yml @@ -22,6 +22,7 @@ build ztp: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - export ZTP_IMAGE_TAG=$(grep -m1 '' ./src/$IMAGE_NAME/pom.xml | grep -oP '(?<=>).*(?=<)') @@ -49,6 +50,7 @@ unit_test ztp: needs: - build ztp before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker rm ${REPORTS_CONTAINER} || true script: diff --git a/src/ztp_server/.gitlab-ci.yml b/src/ztp_server/.gitlab-ci.yml index 0a2d6ff2c..6387ac258 100644 --- a/src/ztp_server/.gitlab-ci.yml +++ b/src/ztp_server/.gitlab-ci.yml @@ -20,6 +20,7 @@ build ztp_server: stage: build before_script: - docker image prune --force + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY script: - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . @@ -48,6 +49,7 @@ unit_test ztp_server: needs: - build ztp_server before_script: + - bash scripts/dockerhub_login.sh - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY - docker ps -aq | xargs -r docker rm -f - > -- GitLab From 4febfe156f90895e2e7d812ee94c5f029224b059 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Wed, 17 Jun 2026 12:36:23 +0000 Subject: [PATCH 6/7] Pre-merge code cleanup --- deploy/all.sh | 4 ++-- my_deploy.sh | 12 ++++++------ redeploy.sh | 4 ---- 3 files changed, 8 insertions(+), 12 deletions(-) delete mode 100755 redeploy.sh diff --git a/deploy/all.sh b/deploy/all.sh index cc20f7f3e..ca0beea31 100755 --- a/deploy/all.sh +++ b/deploy/all.sh @@ -257,7 +257,7 @@ bash scripts/dockerhub_login.sh ./deploy/nats.sh # Deploy QuestDB -#./deploy/qdb.sh +./deploy/qdb.sh # Deploy Apache Kafka ./deploy/kafka.sh @@ -266,7 +266,7 @@ bash scripts/dockerhub_login.sh # ./deploy/monitoring.sh # Expose Dashboard -#./deploy/expose_dashboard.sh +./deploy/expose_dashboard.sh # Deploy TeraFlowSDN ./deploy/tfs.sh diff --git a/my_deploy.sh b/my_deploy.sh index 64b0fd06c..6a4918a82 100644 --- a/my_deploy.sh +++ b/my_deploy.sh @@ -43,11 +43,11 @@ export TFS_COMPONENTS="context device pathcomp service nbi webui" # To manage optical connections, "service" requires "opticalcontroller" to be deployed # before "service", thus we "hack" the TFS_COMPONENTS environment variable prepending the # "opticalcontroller" only if "service" is already in TFS_COMPONENTS, and re-export it. -if [[ "$TFS_COMPONENTS" == *"service"* ]]; then - BEFORE="${TFS_COMPONENTS% service*}" - AFTER="${TFS_COMPONENTS#* service}" - export TFS_COMPONENTS="${BEFORE} opticalcontroller service ${AFTER}" -fi +#if [[ "$TFS_COMPONENTS" == *"service"* ]]; then +# BEFORE="${TFS_COMPONENTS% service*}" +# AFTER="${TFS_COMPONENTS#* service}" +# export TFS_COMPONENTS="${BEFORE} opticalcontroller service ${AFTER}" +#fi # Uncomment to activate ZTP #export TFS_COMPONENTS="${TFS_COMPONENTS} ztp" @@ -148,7 +148,7 @@ export CRDB_PASSWORD="tfs123" export CRDB_DEPLOY_MODE="single" # Disable flag for dropping database, if it exists. -export CRDB_DROP_DATABASE_IF_EXISTS="YES" +export CRDB_DROP_DATABASE_IF_EXISTS="" # Disable flag for re-deploying CockroachDB from scratch. export CRDB_REDEPLOY="" diff --git a/redeploy.sh b/redeploy.sh deleted file mode 100755 index d2025ca6b..000000000 --- a/redeploy.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -source my_deploy.sh -./deploy/all.sh -- GitLab From f7b5f31f722005942bba17ea90a379e57f3bd074 Mon Sep 17 00:00:00 2001 From: gifrerenom Date: Thu, 18 Jun 2026 14:33:00 +0000 Subject: [PATCH 7/7] Scripts: - Fix execution permissions --- scripts/dockerhub_k8s_secret.sh | 0 scripts/dockerhub_login.sh | 0 scripts/prune_old_mr_docker_images.sh | 0 scripts/run_tests_locally-device-gnmi-nokia-srlinux-delete.sh | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/dockerhub_k8s_secret.sh mode change 100644 => 100755 scripts/dockerhub_login.sh mode change 100644 => 100755 scripts/prune_old_mr_docker_images.sh mode change 100644 => 100755 scripts/run_tests_locally-device-gnmi-nokia-srlinux-delete.sh diff --git a/scripts/dockerhub_k8s_secret.sh b/scripts/dockerhub_k8s_secret.sh old mode 100644 new mode 100755 diff --git a/scripts/dockerhub_login.sh b/scripts/dockerhub_login.sh old mode 100644 new mode 100755 diff --git a/scripts/prune_old_mr_docker_images.sh b/scripts/prune_old_mr_docker_images.sh old mode 100644 new mode 100755 diff --git a/scripts/run_tests_locally-device-gnmi-nokia-srlinux-delete.sh b/scripts/run_tests_locally-device-gnmi-nokia-srlinux-delete.sh old mode 100644 new mode 100755 -- GitLab