Commit 952b856b authored by Javier Velázquez's avatar Javier Velázquez
Browse files

Merge branch 'feat/3-challenge-3-l2vpn-support' into 'develop'

Merge feat/3-challenge-3-l2vpn-support

See merge request !6
parents c82b2f7a d545ab9b
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# This file is an original contribution from Telefonica Innovación Digital S.L.
# This file includes original contributions from Telefonica Innovación Digital S.L.

import logging, os, json

@@ -48,12 +48,16 @@ PCE_EXTERNAL = False
# Controller Flags
# If True, config is not sent to controllers
DUMMY_MODE = False

#####TERAFLOW#####
# Teraflow IP
TFS_IP = ips.get('TFS_IP')
UPLOAD_TYPE = "NBI"  # "WEBUI" or "NBI"
UPLOAD_TYPE = "WEBUI"  # "WEBUI" or "NBI"
NBI_L2_PATH = "restconf/data/ietf-l2vpn-svc:l2vpn-svc/vpn-services"
# Flag to determine if additional L2VPN configuration support is required for deploying L2VPNs with path selection
TFS_L2VPN_SUPPORT = False

#####IXIA#####
# IXIA NEII IP
IXIA_IP = ips.get('IXIA_IP')

+64 −35
Original line number Diff line number Diff line
@@ -302,7 +302,9 @@ class NSController:
                    if UPLOAD_TYPE == "WEBUI":
                        response = tfs_connector().webui_post(self.tfs_ip, requests)
                    elif UPLOAD_TYPE == "NBI":
                        response = tfs_connector().nbi_post(self.tfs_ip, requests, self.path)
                        for intent in requests["services"]:
                            # Send each separate NBI request
                            response = tfs_connector().nbi_post(self.tfs_ip, intent, self.path)

                            if not response.ok:
                                return self.__send_response(False, code=response.status_code, message=f"Teraflow upload failed. Response: {response.text}")
@@ -855,9 +857,27 @@ class NSController:

        # Extract QoS Profile from intent
        QoSProfile = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["id"]

        vlan_value = 0

        self.answer[self.subnet]["QoS Requirements"] = []
        
        # Populate response with QoS requirements and VLAN from intent
        for i, constraint in enumerate(ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"]):
            bound = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["bound"]
            metric_type = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["metric-type"]
            metric_unit = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["metric-unit"]
            service_constraint ={
                "custom": {
                    "constraint_type": f"{metric_type}[{metric_unit}]",
                    "constraint_value": f"{bound}"
                }
            }
            self.answer[self.subnet]["QoS Requirements"].append(service_constraint["custom"])
        
        vlan_value = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["service-match-criteria"]["match-criterion"][0]["value"]
        self.answer[self.subnet]["VLAN"] = vlan_value

        if UPLOAD_TYPE == "WEBUI":
            # Load L2VPN service template
            self.__load_template(2, os.path.join(TEMPLATES_PATH, "L2-VPN_template_empty.json"))
            tfs_request = json.loads(str(self.__teraflow_template))["services"][0]
@@ -870,20 +890,9 @@ class NSController:
                endpoint["device_id"]["device_uuid"]["uuid"] = origin_router_id if endpoint is tfs_request["service_endpoint_ids"][0] else destination_router_id
                endpoint["endpoint_uuid"]["uuid"] = origin_router_if if endpoint is tfs_request["service_endpoint_ids"][0] else destination_router_if

        self.answer[self.subnet]["QoS Requirements"] = []
            # Add service constraints
        for i, constraint in enumerate(ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"]):
            bound = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["bound"]
            metric_type = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["metric-type"]
            metric_unit = ietf_intent["ietf-network-slice-service:network-slice-services"]["slo-sle-templates"]["slo-sle-template"][0]["slo-policy"]["metric-bound"][i]["metric-unit"]
            service_constraint ={
                "custom": {
                    "constraint_type": f"{metric_type}[{metric_unit}]",
                    "constraint_value": f"{bound}"
                }
            }
            self.answer[self.subnet]["QoS Requirements"].append(service_constraint["custom"])
            tfs_request["service_constraints"].append(service_constraint)
            for constraint in self.answer[self.subnet]["QoS Requirements"]:
                tfs_request["service_constraints"].append({"custom": constraint})

            # Add configuration rules
            for i, config_rule in enumerate(tfs_request["service_config"]["config_rules"][1:], start=1):
@@ -900,9 +909,29 @@ class NSController:
                resource_value["ni_name"] = 'ELAN{:s}'.format(str(vlan_value))
                config_rule["custom"]["resource_key"] = f"/device[{router_id}]/endpoint[{router_if}]/settings"

        # Log and store VLAN information
        elif UPLOAD_TYPE == "NBI":

            # Load IETF L2VPN service template
            self.__load_template(2, os.path.join(TEMPLATES_PATH, "ietfL2VPN_template_empty.json"))
            tfs_request = json.loads(str(self.__teraflow_template))

            # Generate service UUID
            full_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["id"]
            uuid_only = full_id.split("slice-service-")[-1]
            tfs_request["ietf-l2vpn-svc:vpn-service"][0]["vpn-id"] = uuid_only

            # Configure service endpoints
            for site in tfs_request["ietf-l2vpn-svc:vpn-service"][0]["site"]:
                if site is tfs_request["ietf-l2vpn-svc:vpn-service"][0]["site"][0]:
                    site["site-id"] = origin_router_id
                    site["site-location"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["node-id"]
                    site["site-network-access"]["interface"]["ip-address"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["sdp-ip-address"]
                else:
                    site["site-id"] = destination_router_id
                    site["site-location"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["node-id"]
                    site["site-network-access"]["interface"]["ip-address"] = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["sdp-ip-address"]

        logging.info(f"L2VPN Intent realized\n")
        self.answer[self.subnet]["VLAN"] = vlan_value
        return tfs_request
    
    def __tfs_l2vpn_support(self, requests):
@@ -994,7 +1023,7 @@ class NSController:
            dict: A TeraFlow service request for L3VPN configuration.
        """
        # Hardcoded router endpoints
        # TODO should be dynamically determined
        # TODO (should be dynamically determined)
        origin_router_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][0]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"]
        origin_router_if = '0/0/0-GigabitEthernet0/0/0/0'
        destination_router_id = ietf_intent["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["sdps"]["sdp"][1]["attachment-circuits"]["attachment-circuit"][0]["sdp-peering"]["peer-sap-id"]
+7 −9
Original line number Diff line number Diff line
{
  "ietf-l2vpn-svc:vpn-service": [
    {
      "vpn-id": "11327140-7361-41b3-aa45-e84a7fb40be9",
      "vpn-id": "",
      "customer-name": "osm",
      "vpn-svc-type": "vpws",
      "svc-topo": "any-to-any",
      "site": [
        {
          "site-id": "1.1.1.1",
          "site-role": "hub",
          "site-location": "CU-N2",
          "site-id": "",
          "site-location": "",
          "site-network-access": {
            "interface": {
              "ip-address": "10.60.11.3",
              "ip-address": "",
              "encapsulation": "ethernet"
            }
          }
        },
        {
          "site-id": "3.3.3.3",
          "site-role": "spoke",
          "site-location": "AMF-N2",
          "site-id": "",
          "site-location": "",
          "site-network-access": {
            "interface": {
              "ip-address": "10.60.60.105",
              "ip-address": "",
              "encapsulation": "ethernet"
            }
          }
+0 −184
Original line number Diff line number Diff line
{
    "ietf-l3vpn-svc:l3vpn-svc": {
      "sites": {
        "site": [
          {
            "devices": {
              "device": [
                {
                  "device-id": "4.4.4.4",
                  "location": "router4"
                }
              ]
            },
            "locations": {
              "location": [
                {
                  "location-id": "router4"
                }
              ]
            },
            "management": {
              "type": "ietf-l3vpn-svc:provider-managed"
            },
            "routing-protocols": {
              "routing-protocol": [
                {
                  "static": {
                    "cascaded-lan-prefixes": {
                      "ipv4-lan-prefixes": [
                        {
                          "lan": "4.4.4.4/24",
                          "lan-tag": "100",
                          "next-hop": "2.2.2.2"
                        }
                      ]
                    }
                  },
                  "type": "ietf-l3vpn-svc:static"
                }
              ]
            },
            "site-id": "site_router4",
            "site-network-accesses": {
              "site-network-access": [
                {
                  "device-reference": "4.4.4.4",
                  "ip-connection": {
                    "ipv4": {
                      "address-allocation-type": "ietf-l3vpn-svc:static-address",
                      "addresses": {
                        "customer-address": "2.2.2.2",
                        "prefix-length": "24",
                        "provider-address": "4.4.4.4"
                      }
                    }
                  },
                  "service": {
                    "qos": {
                      "qos-profile": {
                        "classes": {
                          "class": [
                            {
                              "bandwidth": {
                                "guaranteed-bw-percent": 100
                              },
                              "class-id": "qos-realtime",
                              "direction": "ietf-l3vpn-svc:both",
                              "latency": {
                                "latency-boundary": 20
                              }
                            }
                          ]
                        }
                      }
                    },
                    "svc-input-bandwidth": 5000000000,
                    "svc-mtu": 1500,
                    "svc-output-bandwidth": 1000000000
                  },
                  "site-network-access-type": "ietf-l3vpn-svc:multipoint",
                  "vpn-attachment": {
                    "site-role": "ietf-l3vpn-svc:hub-role",
                    "vpn-id": "vpn-example"
                  }
                }
              ]
            }
          },
          {
            "devices": {
              "device": [
                {
                  "device-id": "5.5.5.5",
                  "location": "router5"
                }
              ]
            },
            "locations": {
              "location": [
                {
                  "location-id": "router5"
                }
              ]
            },
            "management": {
              "type": "ietf-l3vpn-svc:provider-managed"
            },
            "routing-protocols": {
              "routing-protocol": [
                {
                  "static": {
                    "cascaded-lan-prefixes": {
                      "ipv4-lan-prefixes": [
                        {
                          "lan": "5.5.5.5/24",
                          "lan-tag": "200",
                          "next-hop": "2.2.2.2"
                        }
                      ]
                    }
                  },
                  "type": "ietf-l3vpn-svc:static"
                }
              ]
            },
            "site-id": "site_router5",
            "site-network-accesses": {
              "site-network-access": [
                {
                  "device-reference": "5.5.5.5",
                  "ip-connection": {
                    "ipv4": {
                      "address-allocation-type": "ietf-l3vpn-svc:static-address",
                      "addresses": {
                        "customer-address": "2.2.2.2",
                        "prefix-length": "24",
                        "provider-address": "5.5.5.5"
                      }
                    }
                  },
                  "service": {
                    "qos": {
                      "qos-profile": {
                        "classes": {
                          "class": [
                            {
                              "bandwidth": {
                                "guaranteed-bw-percent": 100
                              },
                              "class-id": "qos-realtime",
                              "direction": "ietf-l3vpn-svc:both",
                              "latency": {
                                "latency-boundary": 10
                              }
                            }
                          ]
                        }
                      }
                    },
                    "svc-input-bandwidth": 1000000000,
                    "svc-mtu": 1500,
                    "svc-output-bandwidth": 5000000000
                  },
                  "site-network-access-type": "ietf-l3vpn-svc:multipoint",
                  "vpn-attachment": {
                    "site-role": "ietf-l3vpn-svc:spoke-role",
                    "vpn-id": "vpn-example"
                  }
                }
              ]
            }
          }
        ]
      },
      "vpn-services": {
        "vpn-service": [
          {
            "vpn-id": "vpn-example"
          }
        ]
      }
    }
  }
  
 No newline at end of file