refactoring to support delete\update of servics. 90/48990/2
authorKonsta Pozdeev <konsta.pozdeev@hpe.com>
Wed, 16 Nov 2016 13:34:11 +0000 (15:34 +0200)
committerDavid Goldberg <gdavid@hpe.com>
Mon, 5 Dec 2016 16:47:36 +0000 (18:47 +0200)
Change-Id: I4fdf5ca4bae9754f7305956f6107e7e0f558477a
Signed-off-by: Konsta Pozdeev <konsta.pozdeev@hpe.com>
30 files changed:
dlux/cpeui/cpeui-module/src/main/resources/cpeui/admin.tpl.html
dlux/cpeui/cpeui-module/src/main/resources/cpeui/cpeui.tpl.html
dlux/cpeui/cpeui-module/src/main/resources/cpeui/dialogs/AddTenant.tpl.html
dlux/cpeui/cpeui-module/src/main/resources/cpeui/services/cpeui.services.js
dlux/cpeui/cpeui-module/src/main/resources/cpeui/tenant.controller.js
dlux/cpeui/cpeui-module/src/main/resources/cpeui/tenant.tpl.html
legato-api/src/main/yang/mef-interfaces.yang
legato-api/src/main/yang/mef-services.yang
netvirt/pom.xml
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcListener.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcUniUtils.java [deleted file]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/GwMacListener.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IGwMacListener.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/ISubnetManager.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IUniPortManager.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcListener.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcUniUtils.java [deleted file]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MdsalUtils.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefInterfaceUtils.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefServicesUtils.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefUtils.java [deleted file]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtUtils.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NetvirtVpnUtils.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/NodeConnectorListener.java
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/SubnetListener.java [new file with mode: 0644]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantEnhancerUtils.java [deleted file]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantUniListener.java [deleted file]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantlessEvcListener.java [deleted file]
netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/UniPortManager.java [new file with mode: 0644]
netvirt/src/main/resources/org/opendaylight/blueprint/netvirt-driver.xml

index bd8756a469bf214dd7a6e30926bcabf8ba95c34d..2903ebaeb07aa32d2e6f93be275eb18fb90ac715 100644 (file)
@@ -75,7 +75,7 @@
                        </thead>
                        <tbody id="ces_table">
                                <tr ng-repeat="item in unis | orderBy: '[\'uni-id\']'">
-                                       <td ng-init="device = ces.filterByField('dev-id',item.device)[0]">{{ device["device-name"] ? device["device-name"] : device["dev-id"]}}</td>
+                                       <td ng-init="device = ces.filterByField('dev-id',item.device)[0]">{{ device["device-name"] ? device["device-name"] : item.device}}</td>
                                        <td>{{ item.prettyID }}</td>
                                        <td ng-if="item['tenant-id'] != undefined" >
                                                {{ item['tenant-id'] }} <button class="btn add-row right" ng-click="linkUniDialog.show($event, {'uni':item['uni-id'], tenants:tenantArray})">Edit</button>
index 3b0ee3c6b7a8af27ef9e4d02175873f3225e927f..512aacdd8d75d9f040d3a93fc79beb49cfb49e77 100644 (file)
@@ -1,61 +1,3 @@
 <div ng-app="">
-    <!--
-    Main Tab
-    -->
     <div ui-view="cpeui" />
-    <!--
-    Tenant Data Tab
-    -->
-    <!-- div class="container" ng-show="isTabSet('main',2)">
-        <h1>L2 Services - Tenant {{ currentTenent.name }}</h1>
-        <div class="menu">
-            <ul id="EVCs-tab" class="nav nav-pills" role="tablist">
-                <li ng-class="{ active: isTabSet('tenantData',1)}" ng-click="setTab('tenantData',1)" >
-                    <a id="evcs-view-tab"> <i class="icon-search"></i> View</a>
-                </li>
-                <li ng-class="{ active: isTabSet('tenantData',2)}" ng-click="setTab('tenantData',2)" >
-                    <a id="evcs-configure-tab" > <i class="icon-wrench"></i> Configure</a>
-                </li>
-                <li ng-class="{ active: isTabSet('tenantData',3)}" ng-click="setTab('tenantData',3)" >
-                    <a id="dashboard-tab" > <i class="icon-signal"></i> Dashboard</a>
-                </li>
-            </ul>
-        </div>
-        <div id="EVCsContent" class="tab-content">
-            <div role="tabpanel" class="tab-pane fade in active" id="evcs-view" ng-show="isTabSet('tenantData',1)" aria-labelledBy="evcs-view-tab">
-                <br></br>
-                <div class="panel panel-primary">
-                    <div class="panel-heading">
-                        <h3 class="panel-title">L2 Services Table</h3>
-                    </div>
-                    <div class="panel-body">
-                        <table class="table table-striped">
-                            <thead>
-                                <tr>
-                                    <th>Service ID</th>
-                                    <th>Service Type</th>
-                                    <th>CEs in Service</th>
-                                    <th>UNIs in Service</th>
-                                </tr>
-                            </thead>
-                            <tbody id="evc_table" />
-                        </table>
-                    </div>
-                </div>
-            </div>
-            <div role="tabpanel" class="tab-pane fade in active" id="evcs-configure" ng-show="isTabSet('tenantData',2)" aria-labelledBy="evcs-configure-tab">
-                <br></br>
-                <div class="panel panel-primary" style="width: 500px;">
-                    <div class="panel-heading">
-                        <h3 class="panel-title">EVCs Actions</h3>
-                    </div>
-                    <div class="panel-body">
-                        <button type="button" class="btn btn-lg" data-toggle="modal" onclick="prepareCreateEVC()" data-target="#createEVCModal">Create EVC</button>
-                        <button type="button" class="btn btn-lg" data-toggle="modal" onclick="prepareRemoveEVC(evcs_list)" data-target="#removeEVCModal">Remove EVC</button>
-                    </div>
-                </div>
-            </div>
-        </div>
-        <button class="btn btn-default pull-right" ng-click="setTab('main',1)" > Back </button>
-    </div -->
 </div>
index 2afdbec96947dc30ed786f40c9177bc1dec1b561..15d1e636c974d46f2cb3d06b89972cc97da6df63 100644 (file)
                <div ng-message="pattern">name must be only numbers and English characters</div>
                <div ng-message="md-maxlength">The name has to be less than 30 characters long.</div>
        </div>
-       
-       
-       
-       
       </md-input-container>      
       </md-content>
       </div>
index b25a9aaee1cb5271d506498e387ddd58c30b7e4b..6e680c1d4bab1125d18fcb4eb373757ee1f13a54 100644 (file)
@@ -138,7 +138,7 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
             // TODO didn't find a better way to keep other uni fields, PATCH method is not supported :(
             $http({
                 method:'GET',
-                url:"/restconf/config/mef-interfaces:mef-interfaces/unis/uni/" + id + "/"
+                url:"/restconf/operational/mef-interfaces:mef-interfaces/unis/uni/" + id + "/"
             }).then(function successCallback(response) {
                 uni = response.data;
                 uni["uni"][0]["tenant-id"] = tenantid;
@@ -162,7 +162,7 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
             var unis;
             $http({
                 method:'GET',
-                url:"/restconf/config/mef-interfaces:mef-interfaces/unis/"
+                url:"/restconf/operational/mef-interfaces:mef-interfaces/unis/"
             }).then(function successCallback(response) {
                 unis = response.data["unis"]["uni"];
                 if (unis != undefined){
@@ -172,13 +172,33 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
                         }
                     }
                 }
-                unis.forEach(function(u) {
-                  u.prettyID = u['uni-id'].split(":")[u['uni-id'].split(":").length - 1];
-                });
-                if (callback != undefined) {
+                var confMap = {}
+                $http({
+                  method:'GET',
+                  url:"/restconf/config/mef-interfaces:mef-interfaces/unis/"
+                }).then(function(response){
+                  var confUnis = response.data["unis"]["uni"];
+                  confUnis.forEach(function(u) {
+                    confMap[u['uni-id']] = u;
+                  });
+                }).finally(function(){
+                  unis.forEach(function(u) {
+                    u.prettyID = u['uni-id'].split(":")[u['uni-id'].split(":").length - 1];
+                    // copy config fields like tenant-id
+                    if (confMap[u['uni-id']]){
+                      for (var attrname in confMap[u['uni-id']]) {
+                        u[attrname] = confMap[u['uni-id']][attrname]; 
+                      }
+                    }
+                  });
+                  if (callback != undefined) {
                     callback(unis);
-                }
+                  }
+                });
             }, function errorCallback(response) {
+              if (response.status == 404) {
+                callback([]);
+              }
                 console.log(response);
             });
         };
@@ -235,13 +255,10 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
           });
       };
 
-      svc.addIpUni = function(uniid, ipuni_id, ip_address, vlan, subnets, callback) {
+      svc.addIpUni = function(uniid, ipuni_id, ip_address, vlan, callback) {
         var data = {"ip-uni":{
           "ip-uni-id": ipuni_id,
-          "ip-address": ip_address,          
-          "subnets":{
-                "subnet":subnets
-          }
+          "ip-address": ip_address
         }};
         if (vlan){
           data["ip-uni"].vlan = vlan;
@@ -257,20 +274,44 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
         });
     };
     
-      svc.addIpUniSubnet = function(uniid, ipuniid, subnet, gateway,
-          callback) {
+    svc.getAllIpUniSubnets = function(callback) {
+      $http({
+          method:'GET',
+          url : "/restconf/config/mef-interfaces:mef-interfaces/subnets/"
+      }).then(function successCallback(response) {
+          var raw_subnets = response.data["subnets"]["subnet"];
+          var subnets ={}
+          raw_subnets.forEach(function(sub){
+            if (subnets[sub["uni-id"]] == undefined) {
+              subnets[sub["uni-id"]] = {};
+            }
+            if (subnets[sub["uni-id"]][sub["ip-uni-id"]] == undefined) {
+              subnets[sub["uni-id"]][sub["ip-uni-id"]] = [];
+            }
+            subnets[sub["uni-id"]][sub["ip-uni-id"]].push(sub);
+          });
+          if (callback != undefined) {
+              callback(subnets);
+          }
+      }, function errorCallback(response) {
+          console.log(response);
+      });
+  };
+
+  svc.addIpUniSubnet = function(uniid, ipuniid, subnet, gateway, callback) {
         var data = {
             "subnet": 
             {
               "subnet": subnet,
+              "uni-id":uniid,
+              "ip-uni-id":ipuniid,
               "gateway": gateway
             }
-          
         };
         $http(
             {
               method : 'POST',
-              url : "/restconf/config/mef-interfaces:mef-interfaces/unis/uni/"+uniid+"/ip-unis/ip-uni/"+ipuniid+"/subnets/",                                
+              url : "/restconf/config/mef-interfaces:mef-interfaces/subnets/",                                
               data : data
             }).then(function successCallback(response) {
           if (callback != undefined) {
@@ -283,7 +324,7 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
         
         $http({
             method:'DELETE',
-            url:"/restconf/config/mef-interfaces:mef-interfaces/unis/uni/"+uniid+"/ip-unis/ip-uni/"+ipuni_id+"/subnets/subnet/"+subnet.replace("/","%2F")+"/"
+            url:"/restconf/config/mef-interfaces:mef-interfaces/subnets/subnet/"+uniid+"/"+ipuni_id+"/"+subnet.replace("/","%2F")+"/"
         }).then(function successCallback(response) {
             if (callback != undefined) {
                 callback();
@@ -305,9 +346,11 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
     svc.getIpUniSubnets = function(uniid, ipuni_id, callback) {
       $http({
           method:'GET',
-          url:"/restconf/config/mef-interfaces:mef-interfaces/unis/uni/"+uniid+"/ip-unis/ip-uni/"+ipuni_id+"/subnets"
+          url:"/restconf/config/mef-interfaces:mef-interfaces/subnets/"
+            //subnet/"+uniid+"/ip-unis/ip-uni/"+ipuni_id+"/subnets"
       }).then(function successCallback(response) {
           subnets = response.data["subnets"]["subnet"];
+          subnets = subnets.filterByField('uni-id',uniid).filterByField('ip-uni-id',ipuni_id);
           if (callback != undefined) {
               callback(subnets);
           }
@@ -440,7 +483,7 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
                       };          
            $http({
               method:'PUT',
-              url:"/restconf/config/mef-services:mef-services/mef-service/" + svcid + "/ipvc/unis/uni/"+uni_id,
+              url:"/restconf/config/mef-services:mef-services/mef-service/" + svcid + "/ipvc/unis/uni/"+uni_id+"/"+ipuni_id,
               data: data
           }).then(function successCallback(response) {
               if (callback != undefined) {
@@ -453,10 +496,10 @@ define(['app/cpeui/cpeui.module'],function(cpeui) {
           });
       };
       
-      svc.deleteIpvcUni = function(svcid, uni_id, callback) {
+      svc.deleteIpvcUni = function(svcid, uni_id, ipuni_id, callback) {
         $http({
            method:'DELETE',
-           url:"/restconf/config/mef-services:mef-services/mef-service/" + svcid + "/ipvc/unis/uni/" + uni_id + "/"
+           url:"/restconf/config/mef-services:mef-services/mef-service/" + svcid + "/ipvc/unis/uni/" + uni_id +"/"+ipuni_id + "/"
        }).then(function successCallback(response) {
            if (callback != undefined) {
                callback();
index 937dbcdf876a191fb5505b898017b0ee22cbd618..41698b4ec3fc35575b6ca0494717b759668f3b68 100644 (file)
@@ -5,7 +5,8 @@ define([ 'app/cpeui/cpeui.module' ], function(cpeui) {
     $scope.unisTables = {};
     $scope.unis = [];
     $scope.ces = [];
-    $scope.ipvcs = []
+    $scope.ipvcs = [];
+    $scope.subnets = {};
     $scope.cesDisplayNames = {};
     $scope.unisMap = {};
     $scope.networkNames = {};
@@ -91,6 +92,9 @@ define([ 'app/cpeui/cpeui.module' ], function(cpeui) {
           }
         });
       });
+      CpeuiSvc.getAllIpUniSubnets(function(subnets){
+        $scope.subnets = subnets;
+      });
     };
 
     $scope.title = function(str) {
@@ -153,7 +157,7 @@ define([ 'app/cpeui/cpeui.module' ], function(cpeui) {
     };
 
     $scope.ipUniDialog = new CpeuiDialogs.Dialog('AddIpUni', {}, function(obj) {
-      CpeuiSvc.addIpUni(obj['uni-id'], obj['ip-uni-id'], obj['ip-address'], obj.vlan, obj.subnets, function() {
+      CpeuiSvc.addIpUni(obj['uni-id'], obj['ip-uni-id'], obj['ip-address'], obj.vlan, function() {
         var uni = $scope.unis.filterByField('uni-id',obj['uni-id'])[0];
         if (uni['ip-unis'] == undefined || uni['ip-unis']['ip-uni'] == undefined){
           uni['ip-unis'] = {'ip-uni':[]};
@@ -177,9 +181,18 @@ define([ 'app/cpeui/cpeui.module' ], function(cpeui) {
 
     $scope.ipUniSubnetDialog = new CpeuiDialogs.Dialog('AddIpUniSubnet', {}, function(obj) {
       CpeuiSvc.addIpUniSubnet(obj.uniid, obj.ipuniid, obj.subnet, obj.gateway, function() {
-          CpeuiSvc.getIpUniSubnets(obj.uniid, obj.ipuniid, function(subnets) {
-            $scope.unis.filterByField('uni-id',obj.uniid)[0]['ip-unis']['ip-uni'].filterByField('ip-uni-id',obj.ipuniid)[0].subnets = {subnet:subnets};
-          });
+        if ($scope.subnets[obj.uniid] == undefined){
+          $scope.subnets[obj.uniid] = {};
+        }
+        if ($scope.subnets[obj.uniid][obj.ipuniid] == undefined){
+          $scope.subnets[obj.uniid][obj.ipuniid] = [];
+        }
+        $scope.subnets[obj.uniid][obj.ipuniid].push({
+          "uni-id": obj.uniid,
+          "ip-uni-id": obj.ipuniid,
+          "subnet": obj.subnet,
+          "gateway": obj.gateway
+        });
       });
     });
 
@@ -190,9 +203,9 @@ define([ 'app/cpeui/cpeui.module' ], function(cpeui) {
           });
         });
       };
-      $scope.deleteIpvcUni = function(svc_id, uni_id) {
+      $scope.deleteIpvcUni = function(svc_id, uni_id, ipuni_id) {
         CpeuiDialogs.confirm(function() {
-          CpeuiSvc.deleteIpvcUni(svc_id, uni_id, function() {
+          CpeuiSvc.deleteIpvcUni(svc_id, uni_id, ipuni_id, function() {
             $scope.updateEvcView();
           });
         });
index f5f7f997f116f75c9c4bef95c4b82b5185d7a69e..73626638f346c3800f1c9162e8272a5119577d61 100644 (file)
                                                                                <td>{{ ipuni.prettyID }}</td>
                                                                                <td>{{serviceIpuni['ip-address']}}</td>
                                                                                <td>{{serviceIpuni.vlan}}</td>
-                                                                               <td class="delete-tr"><button class="btn btn-md btn-danger" ng-click="deleteIpvcUni(ipvc['svc-id'], ipuni['uni-id'])"> <i class="icon-trash"></i> </button></td>
+                                                                               <td class="delete-tr"><button class="btn btn-md btn-danger" ng-click="deleteIpvcUni(ipvc['svc-id'], ipuni['uni-id'], ipuni['ip-uni-id'])"> <i class="icon-trash"></i> </button></td>
                                                                        </tr>                                                                                                                                           
                                                                </tbody>
                                                        </table>
                                                                                <td>{{ ipuni.prettyID }}</td>
                                                                                <td>{{serviceIpuni['ip-address']}}</td>
                                                                                <td>{{serviceIpuni.vlan}}</td>
-                                                                               <td class="delete-tr"><button class="btn btn-md btn-danger" ng-click="deleteIpvcUni(ipvc['svc-id'], ipuni['uni-id'])"> <i class="icon-trash"></i> </button></td>
+                                                                               <td class="delete-tr"><button class="btn btn-md btn-danger" ng-click="deleteIpvcUni(ipvc['svc-id'], ipuni['uni-id'], ipuni['ip-uni-id'])"> <i class="icon-trash"></i> </button></td>
                                                                        </tr>                                                                   
                                                                </tbody>
                                                        </table>
                                                                                <td class="minimal-width">{{ ipuni.vlan }}</td>
                                                                                <td class="minimal-width">{{ ipuni['ip-address'] }}</td>
                                                                                <td>
-                                                                               <button class="btn add-row" ng-click="expandFlags.ipuni[ipuni['ip-uni-id']] = true" ng-if="!expandFlags.ipuni[ipuni['ip-uni-id']]">
+                                                                               <button class="btn add-row" ng-click="expandFlags.ipuni[uni['uni-id']+':'+ipuni['ip-uni-id']] = true" ng-if="!expandFlags.ipuni[uni['uni-id']+':'+ipuni['ip-uni-id']]">
                                                                                        <i class="icon-plus"></i> Show Subnets
                                                                                </button>
-                                                                                       <table class="footable table table-striped inner-table" ng-if="expandFlags.ipuni[ipuni['ip-uni-id']]">
+                                                                                       <table class="footable table table-striped inner-table" ng-if="expandFlags.ipuni[uni['uni-id']+':'+ipuni['ip-uni-id']]">
                                                                                                <thead>
                                                                                                        <tr>
                                                                                                                <th class="minimal-width">
-                                                                                                                       <button class="btn add-row" ng-click="expandFlags.ipuni[ipuni['ip-uni-id']] = false">
+                                                                                                                       <button class="btn add-row" ng-click="expandFlags.ipuni[uni['uni-id']+':'+ipuni['ip-uni-id']] = false">
                                                                                                                                <i class="icon-minus"></i>
                                                                                                                        </button>
                                                                                                                </th>
                                                                                                        </tr>
                                                                                                </thead>
                                                                                                <tbody>
-                                                                                                       <tr ng-repeat="subnet in ipuni['subnets']['subnet'] | orderBy: subnet">
+                                                                                                       <tr ng-repeat="subnet in subnets[uni['uni-id']][ipuni['ip-uni-id']] | orderBy: subnet" ng-if="subnets[uni['uni-id']]">
                                                                                                                <td colspan="2">{{ subnet.subnet }}</td>
                                                                                                                <td>{{ subnet.gateway }}</td>
                                                                                                                <td class="delete-tr"><button class="btn btn-md btn-danger" ng-click="deleteIpUniSubnet(uni['uni-id'],ipuni['ip-uni-id'],subnet.subnet)"> <i class="icon-trash"></i> </button></td>
index c096b6c8a63e9bc1bbbfcc48070af68d64c7f15b..514ac51747c2658e3148b6e740802c3561e910e7 100644 (file)
-module mef-interfaces {\r
-  namespace "http://metroethernetforum.org/ns/yang/mef-interfaces";\r
-  prefix mef-interfaces;\r
-  import ietf-inet-types { prefix inet; }\r
-  import ietf-yang-types { prefix yang; }\r
-  import mef-types { prefix mef-types; }\r
-  import mef-global { prefix mef-global; }\r
-  import mef-topology { prefix mef-topology; }\r
-\r
-  import opendaylight-l2-types { prefix ethertype; }\r
-  // revision-date "2013-08-27";\r
-\r
-  organization "Metro Ethernet Forum";\r
-  contact\r
-    "Web URL: http://metroethernetforum.org/ E-mail: mibs@metroethernetforum.org\r
-    Postal: Metro Ethernet Forum 6033 W. Century Boulevard, Suite\r
-    1107 Los Angeles, CA 90045 U.S.A. Phone: +1 310-642-2800 Fax:\r
-    +1 310-642-2808";\r
-  description\r
-    "This module implements the UNI functionality specified in MEF\r
-    10.3, MEF 6.2, and MEF 7.2. Reference Overview: A number of base\r
-    documents have been used to create the MEF Interfaces YANG Module.\r
-    The following are the abbreviations for the baseline documents:\r
-    [RFC 6991] refers to IETF RFC 6991 'Common YANG Data Types', 2013-07-15\r
-    [RFC 6643] refers to IETF RFC 6643 'Translation of Structure of\r
-    Management Information Version 2 (SMIv2) MIB Modules to YANG Modules',\r
-    2011-11-25 [802.1AB] refers to 'Station and Media Access Control\r
-    Connectivity Discovery', IEEE 802.1AB-2009, September 2009 [802.1q]\r
-    refers to IEEE 802.1Q-2011 'IEEE Standard for Local and metropolitan\r
-    area networks --Media Access Control (MAC) Bridges and Virtual\r
-    Bridged Local Area Networks, August 2011 [802-2001] refers to\r
-    'IEEE Standard for Local and Metropolitan Area Networks: Overview\r
-    and Architecture', IEEE 802-2001, February 2002 [MEF10.3] refers\r
-    to MEF 10.3 'Ethernet Services Attributes Phase 3', October 2013\r
-    [MEF6.2] refers to MEF 6.2 'EVC Ethernet Services Defintions Phase\r
-    3', August 2014 [MEF40] refers to MEF 40 'UNI and EVC Definition\r
-    of Managed Objects', April 2013 [MEF45] refers to MEF 45 'Multi-CEN\r
-    L2CP', August 2014 [MEF7.2] refers to MEF 7.2 'Carrier Ethernet\r
-    Management Information Model', April 2013 [MEF7.3] refers to MEF\r
-    7.3 'Carrier Ethernet Management Information Model', Working Draft\r
-    #1 2015 [RFC 2737] refers to IETF RFC 2737 'Entity MIB (Version\r
-    2)', December 1999 [RFC 2863] refers to IETF RFC 2863 'The Interfaces\r
-    Group MIB', June 2000 [RFC 3419] refers to IETF RFC 3419 'Textual\r
-    Conventions for Transport Addresses', December 2002 [Y.1731] refers\r
-    to ITU-T Y.1731 'OAM functions and mechanisms for Ethernet based\r
-    networks', July 2011 [Q.840.1] refers to ITU-T Q.840.1 'Requirements\r
-    and analysis for NMS-EMS management interface of Ethernet over\r
-    Transport and Metro Ethernet Network(EoT/MEN)' March 2007";\r
-  revision 2015-05-26 {\r
-    description\r
-        "Formal Project Review Draft 1.";\r
-    reference "EVC Ethernet Services Definitions YANG Modules " +\r
-        "(MEF XX), TBD";\r
-  }\r
-  container mef-interfaces {\r
-    description\r
-        "MEF Interfaces";\r
-    container unis {\r
-      description\r
-            "User Network Interface(UNI).";\r
-      list uni {\r
-        must "not(./ingress-bw-profile-per-uni) or " +\r
-                "((./ingress-bw-profile-per-uni) and " +\r
-                "not(./ingress-envelopes))" {\r
-          error-message "If there is a per UNI Ingress Bandwidth " +\r
-                    "Profile, then there cannot be any other Ingress " +\r
-                    "Bandwidth Profiles at that UNI.";\r
-          description\r
-                    "If there is a per UNI Ingress Bandwidth Profile, " +\r
-                    "then there cannot be any other Ingress Bandwidth " +\r
-                    "Profiles at that UNI.";\r
-        }\r
-        must "not(./egress-bw-profile-per-uni) or " +\r
-                "((./egress-bw-profile-per-uni) and " +\r
-                "not(./egress-envelopes))" {\r
-          error-message "If there is a per UNI Egress Bandwidth " +\r
-                    "Profile, then there cannot be any other Egress " +\r
-                    "Bandwidth Profiles at that UNI.";\r
-          description\r
-                    "If there is a per UNI Egress Bandwidth Profile, " +\r
-                    "then there cannot be any other Egress Bandwidth " +\r
-                    "Profiles at that UNI.";\r
-        }\r
-        must "(not(/mef-global:mef-global/mef-global:" +\r
-                "subscribers) and " +\r
-                "not(./subscriber)) or " +\r
-                "(/mef-global:mef-global/mef-global:" +\r
-                "subscribers and " +\r
-                "./subscriber)" {\r
-          error-message "If the Subscribers list has been " +\r
-                    "populated, a UNI must be configured for " +\r
-                    "a single Subscriber.";\r
-          description\r
-                    "[MEF103] [R1] A UNI must be dedicated to a single " +\r
-                    "Subscriber. This must statement is effectively " +\r
-                    "a 'mandatory true' when the Global Subscribers " +\r
-                    "list is being used.";\r
-        }\r
-        must "(not(/mef-global:mef-global/mef-global:cens) and " +\r
-                "not(./cen-id)) or " +\r
-                "(/mef-global:mef-global/mef-global:cens and " +\r
-                "./cen-id)" {\r
-          error-message "If the CENs list has been populated, " +\r
-                    "a UNI must be configured for a single CEN.";\r
-          description\r
-                    "[MEF103] [R57] A UNI must be dedicated to a " +\r
-                    "single CEN. This must statement is effectively " +\r
-                    "a 'mandatory true' when the Global CENs list " +\r
-                    "is being used.";\r
-        }\r
-        key "uni-id";\r
-        description\r
-                "MEF UNI List.";\r
-        reference "[MEF6.2] Section 8.2.2.";\r
-        container ip-unis {\r
-          list ip-uni {\r
-            key "ip-uni-id";\r
-            leaf ip-uni-id {\r
-              type mef-types:identifier45;\r
-            }\r
-            leaf id {\r
-              type mef-types:identifier45;\r
-            }\r
-            leaf ip-address {\r
-              type inet:ip-prefix;\r
-            }\r
-            leaf vlan {\r
-              type ethertype:vlan-id;\r
-            }\r
-            container subnets {\r
-              list subnet {\r
-                key "subnet";\r
-                leaf subnet {\r
-                  type inet:ip-prefix;\r
-                }\r
-                leaf gateway {\r
-                  type inet:ip-address;\r
-                }\r
-              }\r
-            }\r
-          }\r
-        }\r
-        container physical-layers {\r
-          description\r
-                    "The Physical Layer MUST operate in a full duplex " +\r
-                    "mode. It is not configurable.";\r
-          reference "[MEF10.3] Section 9.2, [R61], [R62]";\r
-          container links {\r
-            presence "A UNI must have links.";\r
-            description\r
-                        "The Physical Layer for each physical link " +\r
-                        "implementing the UNI MUST be one of the " +\r
-                        "PHYs listed in IEEE Std 802.3–2012 but " +\r
-                        "excluding 1000BASE-PX-D and 1000BASE-PX-U.";\r
-            reference "[MEF10.3] Section 9.2 [R60]";\r
-            list link {\r
-              must "count(.) >= 1" {\r
-                error-message "A UNI must have at least one " +\r
-                                "physical link configured.";\r
-                description\r
-                                "A UNI must have at least one physical link " +\r
-                                "configured.";\r
-              }\r
-              key "device interface";\r
-              description\r
-                            "A list of all the physical ports associated " +\r
-                            "with this Link Layer.";\r
-              leaf device {\r
-                type leafref {\r
-                  path "/mef-topology:mef-topology/mef-topology:" +\r
-                                    "devices/mef-topology:device/" +\r
-                                    "mef-topology:dev-id";\r
-                }\r
-                description\r
-                                "The Physical Layer for each physical link " +\r
-                                "implementing the UNI MUST be one of the " +\r
-                                "PHYs listed in IEEE Std 802.3–2012 but " +\r
-                                "excluding 1000BASE-PX-D and 1000BASE-PX-U.";\r
-                reference "[MEF10.3] Section 9.2 [R60]";\r
-              }\r
-              leaf interface {\r
-                type leafref {\r
-                  path "/mef-topology:mef-topology/mef-topology:" +\r
-                                    "devices/mef-topology:device" +\r
-                                    "[mef-topology:dev-id = " +\r
-                                    "current()/../device]" +\r
-                                    "/mef-topology:interfaces/mef-topology:" +\r
-                                    "interface/mef-topology:phy";\r
-                }\r
-                description\r
-                                "The Physical Layer for each physical link " +\r
-                                "implementing the UNI MUST be one of the " +\r
-                                "PHYs listed in IEEE Std 802.3–2012 but " +\r
-                                "excluding 1000BASE-PX-D and 1000BASE-PX-U.";\r
-                reference "[MEF10.3] Section 9.2 [R60]";\r
-              }\r
-              leaf ieee8023-phy {\r
-                type identityref {\r
-                  base mef-types:ieee-8023-interface-type;\r
-                }\r
-                must "(. != 'mef-types:" +\r
-                                "ieee8023-1000BASE-PX-D') and " +\r
-                                "(. != 'mef-types:ieee8023-1000BASE-PX-U')" {\r
-                  error-message "The Physical Layer for each " +\r
-                                    "physical link implementing the UNI " +\r
-                                    "cannot be 1000BASE-PX-D and 1000BASE-PX-U.";\r
-                  description\r
-                                    "The Physical Layer for each physical " +\r
-                                    "link implementing the UNI cannot be " +\r
-                                    "1000BASE-PX-D and 1000BASE-PX-U.";\r
-                }\r
-                description\r
-                                "The Physical Layer for each physical link " +\r
-                                "implementing the UNI MUST be one of the " +\r
-                                "PHYs listed in IEEE Std 802.3–2012 but " +\r
-                                "excluding 1000BASE-PX-D and 1000BASE-PX-U.";\r
-                reference "[MEF10.3] Section 9.2 [R60]";\r
-              }\r
-              leaf connection-speed {\r
-                type mef-types:ext-if-physical-layer-type;\r
-                units "bits-per-second";\r
-                default "1G";\r
-                description\r
-                                "Physical Layer Connection Speed (Max Data Rate).";\r
-                reference "[MEF10.3] Section 9.2. [MEF6.2] " +\r
-                                "Section 8.2.2. [MEF20] [R80].";\r
-              }\r
-              leaf phy-auto-neg {\r
-                type mef-types:auto-negotiation-type;\r
-                default "on";\r
-                description\r
-                                "Auto-Negotiation ON/OFF/Auto.";\r
-                reference "[MEF6.2] Section 8.2.2. [MEF20] [R80]. " +\r
-                                "[MEF7.3] Section 10.2.2.";\r
-              }\r
-              leaf sync-mode-enabled {\r
-                type boolean;\r
-                must ".='false' or (.='true' and " +\r
-                                "../clock-accuracy)" {\r
-                  error-message "The quality of the clock " +\r
-                                    "reference must be set if Synchronous " +\r
-                                    "Mode is enabled.";\r
-                  description\r
-                                    "The quality of the clock reference must " +\r
-                                    "be set if Synchronous Mode is enabled.";\r
-                }\r
-                default "false";\r
-                description\r
-                                "Enabled or Disabled for each physical link " +\r
-                                "implementing the UNI.";\r
-                reference "[MEF10.3] Section 9.3. [MEF6.2] " +\r
-                                "Section 8.2.2. [MEF7.3] Section 10.2.2.";\r
-              }\r
-              leaf clock-accuracy {\r
-                type decimal64 {\r
-                  fraction-digits 3;\r
-                }\r
-                units "ppm";\r
-                description\r
-                                "ESMC:Ethernet Equipment Slave Clock Accuracy " +\r
-                                "in PPM. IEEE 802.3 standard specifies " +\r
-                                "that Ethernet clock accuracy is to be less " +\r
-                                "than or equal to +- 4.6 PPM.";\r
-                reference "[MEF10.3] Section 9.3, [R62]. " +\r
-                                "[MEF22.1], [IEEE802.3].";\r
-              }\r
-            }\r
-          }\r
-          leaf number-of-links {\r
-            type uint32 {\r
-              range "1..max";\r
-            }\r
-            must ". = count(../links/link)" {\r
-              error-message "The UNI Number of Links value " +\r
-                            "must match to the number of interfaces " +\r
-                            "in the link list.";\r
-              description\r
-                            "The UNI Number of Links value must match " +\r
-                            "to the number of interfaces in the link list.";\r
-            }\r
-            default "1";\r
-            description\r
-                        "The number of links configured in the links list.";\r
-            reference "[MEF10.3] [R63]. [MEF7.3] Section 10.2.2.";\r
-          }\r
-        }\r
-        container ce-vlans {\r
-          description\r
-                    "Each Device (and by extension UNIs) MUST have list " +\r
-                    "of the CE-VLAN ID including mappings to configured " +\r
-                    "EVCs if assigned. This list of ce-vlans is a " +\r
-                    "complete list of all VLANs associated with this " +\r
-                    "UNI. At the Service Module level, there are two " +\r
-                    "lists: This one and the list of CE-VLAN IDs " +\r
-                    "associated with the EVC's UNI List as part of " +\r
-                    "the MEF Service Definition. ";\r
-          reference "[MEF10.3] Section 9.10, [R77], [R78]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-          list ce-vlan {\r
-            key "vid";\r
-            description\r
-                        "A list of all EC-VLANs allowed ingres or egress " +\r
-                        "on the UNI. This is the UNI-specific CE-VLAN ID " +\r
-                        "listing as part of the Service Level " +\r
-                        "CE-VLAN ID / EVC Map.";\r
-            reference "[MEF10.3] Section 9.10.1.";\r
-            leaf vid {\r
-              type mef-types:vlan-id-type;\r
-              description\r
-                            "The Customer Edge VLAN ID is equivalent " +\r
-                            "to a Static VLAN allowed on that port " +\r
-                            "(ie. Port is not Forbidden). The " +\r
-                            "association with the EVC is part of " +\r
-                            "the EVC configuration.";\r
-              reference "[MEF10.3] Section 9.10.";\r
-            }\r
-          }\r
-        }\r
-        container ingress-envelopes {\r
-          presence "Ingress Bandwidth Profile Envelopes " +\r
-                    "configured.";\r
-          description\r
-                    "UNI Bandwidth Profile Flow Envelopes.";\r
-          reference "[MEF10.3] Section 9.15, Section 12.1. " +\r
-                    "[MEF6.2] Section 8.2.1: [R3]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-          list envelope {\r
-            key "env-id";\r
-            description\r
-                        "UNI Bandwidth Profile Flow Envelope List.";\r
-            reference "[MEF10.3] Section 9.15, Section 12.1. " +\r
-                        "[MEF6.2] Section 8.2.1, [R3], " +\r
-                        "Section 8.2.2, [R4]. [MEF7.3] " +\r
-                        "Section 10.2.2.";\r
-            container bwp-flows {\r
-              presence "Bandwidth Profile configured for " +\r
-                            "this envelope.";\r
-              description\r
-                            "UNI Bandwidth Profile Flows per Envelope.";\r
-              reference "[MEF10.3] Section 12.1. " +\r
-                            "[MEF6.2] Section 10.1.";\r
-              list bwp-flow {\r
-                key "bw-profile";\r
-                ordered-by user;\r
-                description\r
-                                "UNI Bandwidth Profile Flow List per Envelope. " +\r
-                                "The order of entries in the list is user " +\r
-                                "controlled. The first element of the list " +\r
-                                "has the lowest priority and the last " +\r
-                                "element will have the highest priority.";\r
-                reference "[MEF10.3] Section 12.1. " +\r
-                                "[MEF6.2] Section 10.1. " +\r
-                                "[MEF6.2] Section 8.2.1, [R3]. ";\r
-                leaf bw-profile {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:" +\r
-                                        "profiles/mef-global:" +\r
-                                        "ingress-bwp-flows/mef-global:" +\r
-                                        "bwp-flow/mef-global:bw-profile";\r
-                  }\r
-                  must "(../../../../../token-share-enabled = " +\r
-                                    "'true') or " +\r
-                                    "((../../../../../token-share-enabled = " +\r
-                                    "'false') and " +\r
-                                    "(count(../../bwp-flow) = 1))" {\r
-                    error-message "A UNI with Token Share " +\r
-                                        "Disabled MUST have exactly one " +\r
-                                        "Bandwidth Profile Flow per envelope.";\r
-                    description\r
-                                        "A UNI with Token Share Disabled MUST " +\r
-                                        "have exactly one Bandwidth Profile Flow " +\r
-                                        "per envelope.";\r
-                  }\r
-                  must "(../../../coupling-enabled = 'false') or " +\r
-                                    "(/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:" +\r
-                                    "ingress-bwp-flows/mef-global:bwp-flow" +\r
-                                    "[mef-global:bw-profile = current()]/" +\r
-                                    "mef-global:coupling-enabled = 'false')" {\r
-                    error-message "If an Ingress Envelope's " +\r
-                                        "Coupling Flag is Enabled, then " +\r
-                                        "the Coupling Flags must be disabled " +\r
-                                        "for all Bandwidth Profile Flows " +\r
-                                        "mapped to the Envelope.";\r
-                    description\r
-                                        "If an Ingress Envelope's Coupling Flag is " +\r
-                                        "Enabled, then the Coupling Flags must " +\r
-                                        "be disabled for all Bandwidth Profile " +\r
-                                        "Flows mapped to the Envelope.";\r
-                  }\r
-                  description\r
-                                    "If no Ingress Bandwidth Profile per UNI " +\r
-                                    "has been defined (ie. 'No'), then the " +\r
-                                    "behavior has been defined at the Service " +\r
-                                    "Level of the configuration.";\r
-                  reference "[MEF10.3] Section 9.14, " +\r
-                                    "Section 12.1, [R84], [R134]. " +\r
-                                    "[MEF6.2] Section 8.2.1,[R3],[R136]. " +\r
-                                    "Section 8.2.2, 10.1, [R6]. [MEF7.3] " +\r
-                                    "Section 10.2.2.";\r
-                }\r
-              }\r
-            }\r
-            leaf env-id {\r
-              type mef-types:identifier45;\r
-              description\r
-                            "This attribute identifies the Envelope of " +\r
-                            "Bandwidth Profile Parameters.";\r
-              reference "[MEF10.3] Section 12.1.";\r
-            }\r
-            leaf coupling-enabled {\r
-              type boolean;\r
-              must "not(../bwp-flows) or " +\r
-                            "(../bwp-flows/bwp-flow[2]) or " +\r
-                            "(. = 'false')" {\r
-                error-message "When only one Bandwidth Profile " +\r
-                                "Flow is mapped to an envelope, Envelope " +\r
-                                "Coupling must be Disabled.";\r
-                description\r
-                                "When only one Bandwidth Profile Flow is " +\r
-                                "mapped to an envelope, Envelope " +\r
-                                "Coupling must be Disabled.";\r
-              }\r
-              default "false";\r
-              description\r
-                            "The Envelope Coupling Flag (CF) attribute.";\r
-              reference "[MEF10.3] Section 12.1.";\r
-            }\r
-          }\r
-        }\r
-        container egress-envelopes {\r
-          presence "Egress Bandwidth Profile Envelopes configured.";\r
-          description\r
-                    "UNI Bandwidth Profile Flow Envelopes.";\r
-          reference "[MEF10.3] Section 9.15, Section 12.1. " +\r
-                    "[MEF6.2] Section 8.2.1: [R3]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-          list envelope {\r
-            key "env-id";\r
-            description\r
-                        "UNI Bandwidth Profile Flow Envelope List.";\r
-            reference "[MEF10.3] Section 9.15, Section 12.1. " +\r
-                        "[MEF6.2] Section 8.2.1, [R3], " +\r
-                        "Section 8.2.2, [R4]. [MEF7.3] " +\r
-                        "Section 10.2.2.";\r
-            container bwp-flows {\r
-              presence "Bandwidth Profile configured for " +\r
-                            "this envelope.";\r
-              description\r
-                            "UNI Bandwidth Profile Flows per Envelope.";\r
-              reference "[MEF10.3] Section 12.1. [MEF6.2] " +\r
-                            "Section 10.1.";\r
-              list bwp-flow {\r
-                key "bw-profile";\r
-                ordered-by user;\r
-                description\r
-                                "UNI Bandwidth Profile Flow List per Envelope. " +\r
-                                "The order of entries in the list is user " +\r
-                                "controlled. The first element of the list " +\r
-                                "has the lowest priority and the last element " +\r
-                                "will have the highest priority.";\r
-                reference "[MEF10.3] Section 12.1. " +\r
-                                "[MEF6.2] Section 10.1. " +\r
-                                "[MEF6.2] Section 8.2.1, [R3]. ";\r
-                leaf bw-profile {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:" +\r
-                                        "profiles/mef-global:egress-bwp-flows" +\r
-                                        "/mef-global:bwp-flow/" +\r
-                                        "mef-global:bw-profile";\r
-                  }\r
-                  must "(../../../../../token-share-enabled = " +\r
-                                    "'true') or " +\r
-                                    "((../../../../../token-share-enabled = " +\r
-                                    "'false') and " +\r
-                                    "(count(../../bwp-flow) = 1))" {\r
-                    error-message "A UNI with Token Share " +\r
-                                        "Disabled must have exactly one " +\r
-                                        "Bandwidth Profile Flow per envelope.";\r
-                    description\r
-                                        "A UNI with Token Share Disabled must have " +\r
-                                        "exactly one Bandwidth Profile Flow per " +\r
-                                        "envelope.";\r
-                  }\r
-                  must "(../../../coupling-enabled = 'false') or " +\r
-                                    "(/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:" +\r
-                                    "egress-bwp-flows/mef-global:bwp-flow" +\r
-                                    "[mef-global:bw-profile = current()]/" +\r
-                                    "mef-global:coupling-enabled = 'false')" {\r
-                    error-message "If an Egress Envelope's " +\r
-                                        "Coupling Flag is Enabled, then the " +\r
-                                        "Coupling Flags must be disabled " +\r
-                                        "for all Bandwidth Profile Flows " +\r
-                                        "mapped to the Envelope.";\r
-                    description\r
-                                        "If an Egress Envelope's Coupling Flag " +\r
-                                        "is Enabled, then the Coupling Flags must " +\r
-                                        "be disabled for all Bandwidth Profile " +\r
-                                        "Flows mapped to the Envelope.";\r
-                  }\r
-                  description\r
-                                    "UNI Bandwidth Profile Flow per Envelope.";\r
-                  reference "[MEF10.3] Section 12.1. " +\r
-                                    "[MEF6.2] Section 10.1. " +\r
-                                    "[MEF6.2] Section 8.2.1, [R3], [R136]. ";\r
-                }\r
-              }\r
-            }\r
-            leaf env-id {\r
-              type mef-types:identifier45;\r
-              description\r
-                            "This attribute identifies the Envelope of " +\r
-                            "Bandwidth Profile Parameters.";\r
-              reference "[MEF10.3] Section 12.1.";\r
-            }\r
-            leaf coupling-enabled {\r
-              type boolean;\r
-              must "not(../bwp-flows) or " +\r
-                            "(../bwp-flows/bwp-flow[2]) or " +\r
-                            "(. = 'false')" {\r
-                error-message "When only one Bandwidth Profile " +\r
-                                "Flow is mapped to an envelope, " +\r
-                                "Envelope Coupling must be Disabled.";\r
-                description\r
-                                "When only one Bandwidth Profile Flow is " +\r
-                                "mapped to an envelope, Envelope Coupling " +\r
-                                "must be Disabled.";\r
-              }\r
-              default "false";\r
-              description\r
-                            "The Envelope Coupling Flag (CF) attribute.";\r
-              reference "[MEF10.3] Section 12.1.";\r
-            }\r
-          }\r
-        }\r
-        container status {\r
-          description\r
-                    "This group is related to the MEF 7.3 External " +\r
-                    "Network Interface";\r
-          leaf oper-state-enabled {\r
-            type boolean;\r
-            default "false";\r
-            config false;\r
-            description\r
-                        "Operational Status of the Link as " +\r
-                        "Enabled/Disabled.";\r
-            reference "[MEF15]. [MEF7.3] Section 10.1.1.";\r
-          }\r
-          leaf available-status {\r
-            type mef-types:ext-if-availability-type;\r
-            default "not-installed";\r
-            config false;\r
-            description\r
-                        "Availability Status of the Link.";\r
-            reference "[MEF15]. [MEF7.3] Section 10.1.1.";\r
-          }\r
-          leaf physical-layer {\r
-            type mef-types:ext-if-physical-layer-type;\r
-            default "1G";\r
-            config false;\r
-            description\r
-                        "Physical Layer Connection Speed.";\r
-            reference "[MEF15]. [MEF7.3] Section 10.1.1.";\r
-          }\r
-          leaf number-of-links {\r
-            type uint32;\r
-            default "0";\r
-            config false;\r
-            description\r
-                        "A count of the number of physical links in this " +\r
-                        "physical layer.";\r
-            reference "[MEF15]. [MEF7.3] Section 10.1.1.";\r
-          }\r
-          leaf svc-frame-format {\r
-            type mef-types:svc-frame-format-type;\r
-            default "ctag";\r
-            config false;\r
-            description\r
-                        "The format must be that of a MAC Frame specified " +\r
-                        "in IEEE Std 802.3-2012 Clause 3.";\r
-            reference "[MEF10.3] Section 9.6. [MEF15]. " +\r
-                        "[MEF7.2]. [MEF7.3] Section 10.1.1.";\r
-          }\r
-        }\r
-        leaf cen-id {\r
-          when "/mef-global:mef-global/mef-global:cens" {\r
-            description\r
-                        "Only configure when the Global CENs list " +\r
-                        "has been populated.";\r
-          }\r
-          type leafref {\r
-            path "/mef-global:mef-global/mef-global:cens/" +\r
-                        "mef-global:cen/mef-global:cen-id";\r
-          }\r
-          description\r
-                    "A CEN is defined as a network from a Service " +\r
-                    "Provider (SP). The CEN ID must be unique for " +\r
-                    "a specific Service Provider.";\r
-          reference "[MEF10.3] Section 7.";\r
-        }\r
-        leaf uni-id {\r
-          type mef-types:identifier45;\r
-          description\r
-                    " The UNI IDs must be be unique within a specific CEN.";\r
-          reference "[MEF10.3] Section 9.1, [R1], [R57], [R58], " +\r
-                    "[R59]. [MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf uni-type {\r
-          type mef-types:uni-mode-type;\r
-          default "uni";\r
-          description\r
-                    " The UNI Type must be one of {UNI, VUNI}.";\r
-          reference "[MEF10.3] Section 9.1, [R1], [R57], [R58], " +\r
-                    "[R59]. [MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf subscriber {\r
-          when "/mef-global:mef-global/mef-global:subscribers" {\r
-            description\r
-                        "UNI Subscriber Attribute is only configurable " +\r
-                        "when multiple Global Subscribers have been " +\r
-                        "configured.";\r
-          }\r
-          type leafref {\r
-            path "/mef-global:mef-global/mef-global:subscribers/" +\r
-                        "mef-global:subscriber/mef-global:sub-id";\r
-          }\r
-          description\r
-                    "A UNI MUST be dedicated to a single Subscriber. " +\r
-                    "This value can only be configured if the " +\r
-                    "'/mef-global/subscribers/subscriber' list " +\r
-                    "has been populated.";\r
-          reference "[MEF10.3] Section 7.";\r
-        }\r
-        leaf admin-state-enabled {\r
-          type boolean;\r
-          default "true";\r
-          description\r
-                    "Locked/Unlocked is inconsistent with Oper Status " +\r
-                    "and will be confusing.";\r
-          reference "MEF 15. MEF 7.3 Section 10.1.1.";\r
-        }\r
-        leaf mac-address {\r
-          type yang:mac-address;\r
-          description\r
-                    "MAC Address.";\r
-          reference "[MEF15]. [MEF7.3] Section 10.1.1.";\r
-        }\r
-        leaf uni-resiliency {\r
-          type mef-types:uni-resiliency-type;\r
-          must "(. != 'none') or ((. = 'none') and " +\r
-                    "(../physical-layers/number-of-links = 1))" {\r
-            error-message "If uni-resiliency is 'none', " +\r
-                        "number-of-links must be 1.";\r
-            description\r
-                        "If uni-resiliency is 'none', number-of-links " +\r
-                        "must be 1.";\r
-          }\r
-          must "(. != 'dual-link-aggregation') or " +\r
-                    "((. = 'dual-link-aggregation') and " +\r
-                    "(../physical-layers/number-of-links = 2))" {\r
-            error-message "If uni-resiliency is " +\r
-                        "'dual-link-aggregation', " +\r
-                        "number-of-links must be 2.";\r
-            description\r
-                        "If uni-resiliency is 'dual-link-aggregation', " +\r
-                        "number-of-links must be 2.";\r
-          }\r
-          must "(. != 'other') or " +\r
-                    "((. = 'other') and " +\r
-                    "(../physical-layers/number-of-links > 2))" {\r
-            error-message "If uni-resiliency is 'other', " +\r
-                        "number-of-links must be 3 or greater.";\r
-            description\r
-                        "If uni-resiliency is 'other', number-of-links " +\r
-                        "must be 3 or greater.";\r
-          }\r
-          default "none";\r
-          description\r
-                    "UNI Resiliency.";\r
-          reference "[MEF10.3] Section 9.5 [R64], [R65], [R66], " +\r
-                    "[R67]. [MEF6.2] Section 8.2.2.";\r
-        }\r
-        leaf max-svc-frame-size {\r
-          type mef-types:max-svc-frame-size-type;\r
-          default "1600";\r
-          description\r
-                    "This attribute describes the maximum service frame " +\r
-                    "size for the UNI.";\r
-          reference "[MEF10.3] Section 9.7, [R71], MEF 6.2 " +\r
-                    "Section 8.2.2 and MEF 22.1: [D2]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf svc-mux-enabled {\r
-          type boolean;\r
-          default "false";\r
-          description\r
-                    "Service Multiplexing Enable - Enable if to support " +\r
-                    "multiple EVCs per UNI.";\r
-          reference "[MEF10.3] Section 9.8. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf bundling-enabled {\r
-          type boolean;\r
-          default "false";\r
-          description\r
-                    "When a UNI has Bundling Enabled, it MUST be able to " +\r
-                    "support more than one CE-VLAN ID mapping to a " +\r
-                    "particular EVC at the UNI.  When more than one " +\r
-                    "CE-VLAN-ID is mapped to an EVC at a UNI, the " +\r
-                    "EVC have CE-VLAN ID Preservation enabled";\r
-          reference "[MEF10.3] Section 9.12, [R25], [R77], " +\r
-                    "[R78], [R80]. [MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf all-to-one-bundling-enabled {\r
-          type boolean;\r
-          default "false";\r
-          description\r
-                    "When all-to-one-bundling-enabled = true, all " +\r
-                    "CE-VLAN IDs MUST map to a single EVC at the " +\r
-                    "UNI. This also means that the UNI cannot " +\r
-                    "have svc-mux-enabled = true. When " +\r
-                    "all-to-one-bundling-enabled = true, " +\r
-                    "all other UNIs in the EVC associating this UNI " +\r
-                    "must have all-to-one-bundling-enabled = true. " +\r
-                    "If this values is true, the value of " +\r
-                    "ce-vlan-id-for-untagged-and-priority is not " +\r
-                    "applicable.";\r
-          reference "[MEF10.3] Section 9.13, Table 12 " +\r
-                    "(5 valid combinations), [R82], [R83]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf ce-vlan-id-for-untagged-and-priority {\r
-          type mef-types:vlan-id-type;\r
-          default "1";\r
-          description\r
-                    "The ce-vlan-id-for-untagged-and-priority is " +\r
-                    "equivalent to the Layer 2 PVID (Port VLAN ID) " +\r
-                    "with the Q-BRIDGE-MIB option for frame admitance set " +\r
-                    "to admitAll. With AdmitAll set, all Untagged and " +\r
-                    "Priority Tagged Service Frames are treated with " +\r
-                    "the CE-VLAN-ID tag on ingress. It is not applicable " +\r
-                    "if All in One Bundling is enabled.";\r
-          reference "[MEF10.3] Section 9.9, [R73], [R74], " +\r
-                    "[R75]. [MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf max-evc-count {\r
-          type uint32 {\r
-            range "1..max";\r
-          }\r
-          default "1";\r
-          description\r
-                    "The Maximum Number of EVCs that can be supported " +\r
-                    "by this UNI (Default 1).";\r
-          reference "[MEF10.3] Section 9.11, [R79]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf token-share-enabled {\r
-          type boolean;\r
-          default "false";\r
-          description\r
-                    "Token Share Enabled/Disabled is used to indicate " +\r
-                    "whether a given UNI is capable of sharing tokens " +\r
-                    "across Bandwidth Profile Flows in an envelope.";\r
-          reference "[MEF6.2] Section 8.2.1, [R2], [D1], [R3]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf ingress-bw-profile-per-uni {\r
-          type leafref {\r
-            path "/mef-global:mef-global/mef-global:profiles/" +\r
-                        "mef-global:ingress-bwp-flows/mef-global:" +\r
-                        "bwp-flow/mef-global:bw-profile";\r
-          }\r
-          description\r
-                    "Ingress Bandwidth Profile for this UNI.";\r
-          reference "[MEF10.3] Section 9.15, Section 12.1. " +\r
-                    "[MEF6.2] Section 8.2.1: [R3]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf egress-bw-profile-per-uni {\r
-          type leafref {\r
-            path "/mef-global:mef-global/mef-global:profiles/" +\r
-                        "mef-global:egress-bwp-flows/mef-global:" +\r
-                        "bwp-flow/mef-global:bw-profile";\r
-          }\r
-          description\r
-                    "Egress Bandwidth Profile Flow for this UNI.";\r
-          reference "[MEF10.3] Section 9.15, Section 12.1. " +\r
-                    "[MEF6.2] Section 8.2.1: [R3]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf link-oam-enabled {\r
-          type boolean;\r
-          default "false";\r
-          description\r
-                    "Link OAM Enabled/Disabled.";\r
-          reference "[MEF10.3] Section 9.16, [R86]. " +\r
-                    "[MEF6.2] Section 8.2.2, [D3]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf uni-meg-enabled {\r
-          type boolean;\r
-          default "false";\r
-          description\r
-                    "Enables / Disables the Maintenance Entity Group (MEG).";\r
-          reference "[MEF10.3] Section 9.17, [R87]. " +\r
-                    "[MEF30.1] Section 7.9. [MEF6.2] Section 8.2.2, " +\r
-                    "[D4]. [MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf elmi-enabled {\r
-          type boolean;\r
-          must "(. = 'false') or " +\r
-                    "(. = 'true' and " +\r
-                    "(../elmi-profile))" {\r
-            error-message "ELMI Profile must be set if " +\r
-                        "ELMI is Enabled.";\r
-            description\r
-                        "Ethernet Local Management Interface(ELMI) " +\r
-                        "Profile ID must be set if ELMI is Enabled.";\r
-          }\r
-          default "false";\r
-          description\r
-                    "Ethernet Local Management Interface(ELMI) " +\r
-                    "Enabled / Disabled.";\r
-          reference "[MEF10.3] Section 9.18, [R88]. " +\r
-                    "[MEF16]. [MEF6.2] Section 8.2.2, [D5]. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf elmi-profile {\r
-          type leafref {\r
-            path "/mef-global:mef-global/mef-global:profiles/" +\r
-                        "mef-global:elmi/mef-global:elmi-profile/" +\r
-                        "mef-global:id";\r
-          }\r
-          description\r
-                    "The ELMI Profile is only applicable when ELMI " +\r
-                    "is enabled. The E-LMI protocol is based on " +\r
-                    "ITU-T Q.933, X.36 and other relevant " +\r
-                    "recommendations as well as Frame Relay " +\r
-                    "Local Management Interface (FR-LMI) " +\r
-                    "Implementation Agreement document defined " +\r
-                    "by the Frame Relay Forum and related " +\r
-                    "ITU-T recommendations.";\r
-          reference "[MEF10.3] Section 9.18. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf l2cp-address-set {\r
-          type mef-types:l2cp-address-set-type;\r
-          default "aware-cta";\r
-          description\r
-                    "The L2CP Address Set Service Attribute specifies " +\r
-                    "the subset of the Bridge Reserved Addresses " +\r
-                    "that are filtered (i.e. L2CP Frames with " +\r
-                    "this destination address are Peered or " +\r
-                    "Discarded but not Passed) at a L2CP Decision Point.";\r
-          reference "[MEF10.3] Section 9.19. " +\r
-                    "[MEF45] Section 8.1, [R2] through [R9]. " +\r
-                    "[MEF6.2] Section 8.2.2, [R1]. " +\r
-                    "[MEF45] Section 8.1.";\r
-        }\r
-        leaf l2cp-peering-profile {\r
-          type leafref {\r
-            path "/mef-global:mef-global/mef-global:profiles/" +\r
-                        "mef-global:l2cp-peering/mef-global:" +\r
-                        "l2cp-profile/mef-global:id";\r
-          }\r
-          description\r
-                    "L2CP Peering Profile for this UNI. This profile " +\r
-                    "may contain groups of L2CP Destination " +\r
-                    "MAC Addresses and protocols to be peered at " +\r
-                    "the UNI (as opposed to being passed or discarded).";\r
-          reference "[MEF10.3] Section 9.19. " +\r
-                    "[MEF45] Section 8.2. " +\r
-                    "[MEF7.3] Section 10.2.2.";\r
-        }\r
-        leaf tenant-id {\r
-          type leafref {\r
-            path "/mef-global:mef-global/mef-global:tenants-instances/mef-global:tenant-list/mef-global:name";\r
-          }\r
-        }\r
-      }\r
-    }\r
-  }\r
-}\r
+module mef-interfaces {
+  namespace "http://metroethernetforum.org/ns/yang/mef-interfaces";
+  prefix mef-interfaces;
+  import ietf-inet-types { prefix inet; }
+  import ietf-yang-types { prefix yang; }
+  import mef-types { prefix mef-types; }
+  import mef-global { prefix mef-global; }
+  import mef-topology { prefix mef-topology; }
+  import yang-ext {prefix ext; revision-date "2013-07-09";}
+
+  import opendaylight-l2-types { prefix ethertype; }
+  // revision-date "2013-08-27";
+
+  organization "Metro Ethernet Forum";
+  contact
+    "Web URL: http://metroethernetforum.org/ E-mail: mibs@metroethernetforum.org
+    Postal: Metro Ethernet Forum 6033 W. Century Boulevard, Suite
+    1107 Los Angeles, CA 90045 U.S.A. Phone: +1 310-642-2800 Fax:
+    +1 310-642-2808";
+  description
+    "This module implements the UNI functionality specified in MEF
+    10.3, MEF 6.2, and MEF 7.2. Reference Overview: A number of base
+    documents have been used to create the MEF Interfaces YANG Module.
+    The following are the abbreviations for the baseline documents:
+    [RFC 6991] refers to IETF RFC 6991 'Common YANG Data Types', 2013-07-15
+    [RFC 6643] refers to IETF RFC 6643 'Translation of Structure of
+    Management Information Version 2 (SMIv2) MIB Modules to YANG Modules',
+    2011-11-25 [802.1AB] refers to 'Station and Media Access Control
+    Connectivity Discovery', IEEE 802.1AB-2009, September 2009 [802.1q]
+    refers to IEEE 802.1Q-2011 'IEEE Standard for Local and metropolitan
+    area networks --Media Access Control (MAC) Bridges and Virtual
+    Bridged Local Area Networks, August 2011 [802-2001] refers to
+    'IEEE Standard for Local and Metropolitan Area Networks: Overview
+    and Architecture', IEEE 802-2001, February 2002 [MEF10.3] refers
+    to MEF 10.3 'Ethernet Services Attributes Phase 3', October 2013
+    [MEF6.2] refers to MEF 6.2 'EVC Ethernet Services Defintions Phase
+    3', August 2014 [MEF40] refers to MEF 40 'UNI and EVC Definition
+    of Managed Objects', April 2013 [MEF45] refers to MEF 45 'Multi-CEN
+    L2CP', August 2014 [MEF7.2] refers to MEF 7.2 'Carrier Ethernet
+    Management Information Model', April 2013 [MEF7.3] refers to MEF
+    7.3 'Carrier Ethernet Management Information Model', Working Draft
+    #1 2015 [RFC 2737] refers to IETF RFC 2737 'Entity MIB (Version
+    2)', December 1999 [RFC 2863] refers to IETF RFC 2863 'The Interfaces
+    Group MIB', June 2000 [RFC 3419] refers to IETF RFC 3419 'Textual
+    Conventions for Transport Addresses', December 2002 [Y.1731] refers
+    to ITU-T Y.1731 'OAM functions and mechanisms for Ethernet based
+    networks', July 2011 [Q.840.1] refers to ITU-T Q.840.1 'Requirements
+    and analysis for NMS-EMS management interface of Ethernet over
+    Transport and Metro Ethernet Network(EoT/MEN)' March 2007";
+  revision 2015-05-26 {
+    description
+        "Formal Project Review Draft 1.";
+    reference "EVC Ethernet Services Definitions YANG Modules " +
+        "(MEF XX), TBD";
+  }
+  container mef-interfaces {
+    description
+        "MEF Interfaces";
+    container unis {
+      description
+            "User Network Interface(UNI).";
+      list uni {
+        must "not(./ingress-bw-profile-per-uni) or " +
+                "((./ingress-bw-profile-per-uni) and " +
+                "not(./ingress-envelopes))" {
+          error-message "If there is a per UNI Ingress Bandwidth " +
+                    "Profile, then there cannot be any other Ingress " +
+                    "Bandwidth Profiles at that UNI.";
+          description
+                    "If there is a per UNI Ingress Bandwidth Profile, " +
+                    "then there cannot be any other Ingress Bandwidth " +
+                    "Profiles at that UNI.";
+        }
+        must "not(./egress-bw-profile-per-uni) or " +
+                "((./egress-bw-profile-per-uni) and " +
+                "not(./egress-envelopes))" {
+          error-message "If there is a per UNI Egress Bandwidth " +
+                    "Profile, then there cannot be any other Egress " +
+                    "Bandwidth Profiles at that UNI.";
+          description
+                    "If there is a per UNI Egress Bandwidth Profile, " +
+                    "then there cannot be any other Egress Bandwidth " +
+                    "Profiles at that UNI.";
+        }
+        must "(not(/mef-global:mef-global/mef-global:" +
+                "subscribers) and " +
+                "not(./subscriber)) or " +
+                "(/mef-global:mef-global/mef-global:" +
+                "subscribers and " +
+                "./subscriber)" {
+          error-message "If the Subscribers list has been " +
+                    "populated, a UNI must be configured for " +
+                    "a single Subscriber.";
+          description
+                    "[MEF103] [R1] A UNI must be dedicated to a single " +
+                    "Subscriber. This must statement is effectively " +
+                    "a 'mandatory true' when the Global Subscribers " +
+                    "list is being used.";
+        }
+        must "(not(/mef-global:mef-global/mef-global:cens) and " +
+                "not(./cen-id)) or " +
+                "(/mef-global:mef-global/mef-global:cens and " +
+                "./cen-id)" {
+          error-message "If the CENs list has been populated, " +
+                    "a UNI must be configured for a single CEN.";
+          description
+                    "[MEF103] [R57] A UNI must be dedicated to a " +
+                    "single CEN. This must statement is effectively " +
+                    "a 'mandatory true' when the Global CENs list " +
+                    "is being used.";
+        }
+        key "uni-id";
+        description
+                "MEF UNI List.";
+        reference "[MEF6.2] Section 8.2.2.";
+        container ip-unis {
+          list ip-uni {
+            key "ip-uni-id";
+            leaf ip-uni-id {
+              type mef-types:identifier45;
+            }
+            leaf ip-address {
+              type inet:ip-prefix;
+            }
+            leaf vlan {
+              type ethertype:vlan-id;
+            }
+          }
+        }
+        container physical-layers {
+          description
+                    "The Physical Layer MUST operate in a full duplex " +
+                    "mode. It is not configurable.";
+          reference "[MEF10.3] Section 9.2, [R61], [R62]";
+          container links {
+            presence "A UNI must have links.";
+            description
+                        "The Physical Layer for each physical link " +
+                        "implementing the UNI MUST be one of the " +
+                        "PHYs listed in IEEE Std 802.3–2012 but " +
+                        "excluding 1000BASE-PX-D and 1000BASE-PX-U.";
+            reference "[MEF10.3] Section 9.2 [R60]";
+            list link {
+              must "count(.) >= 1" {
+                error-message "A UNI must have at least one " +
+                                "physical link configured.";
+                description
+                                "A UNI must have at least one physical link " +
+                                "configured.";
+              }
+              key "device interface";
+              description
+                            "A list of all the physical ports associated " +
+                            "with this Link Layer.";
+              leaf device {
+                type leafref {
+                  path "/mef-topology:mef-topology/mef-topology:" +
+                                    "devices/mef-topology:device/" +
+                                    "mef-topology:dev-id";
+                }
+                description
+                                "The Physical Layer for each physical link " +
+                                "implementing the UNI MUST be one of the " +
+                                "PHYs listed in IEEE Std 802.3–2012 but " +
+                                "excluding 1000BASE-PX-D and 1000BASE-PX-U.";
+                reference "[MEF10.3] Section 9.2 [R60]";
+              }
+              leaf interface {
+                type leafref {
+                  path "/mef-topology:mef-topology/mef-topology:" +
+                                    "devices/mef-topology:device" +
+                                    "[mef-topology:dev-id = " +
+                                    "current()/../device]" +
+                                    "/mef-topology:interfaces/mef-topology:" +
+                                    "interface/mef-topology:phy";
+                }
+                description
+                                "The Physical Layer for each physical link " +
+                                "implementing the UNI MUST be one of the " +
+                                "PHYs listed in IEEE Std 802.3–2012 but " +
+                                "excluding 1000BASE-PX-D and 1000BASE-PX-U.";
+                reference "[MEF10.3] Section 9.2 [R60]";
+              }
+              leaf ieee8023-phy {
+                type identityref {
+                  base mef-types:ieee-8023-interface-type;
+                }
+                must "(. != 'mef-types:" +
+                                "ieee8023-1000BASE-PX-D') and " +
+                                "(. != 'mef-types:ieee8023-1000BASE-PX-U')" {
+                  error-message "The Physical Layer for each " +
+                                    "physical link implementing the UNI " +
+                                    "cannot be 1000BASE-PX-D and 1000BASE-PX-U.";
+                  description
+                                    "The Physical Layer for each physical " +
+                                    "link implementing the UNI cannot be " +
+                                    "1000BASE-PX-D and 1000BASE-PX-U.";
+                }
+                description
+                                "The Physical Layer for each physical link " +
+                                "implementing the UNI MUST be one of the " +
+                                "PHYs listed in IEEE Std 802.3–2012 but " +
+                                "excluding 1000BASE-PX-D and 1000BASE-PX-U.";
+                reference "[MEF10.3] Section 9.2 [R60]";
+              }
+              leaf connection-speed {
+                type mef-types:ext-if-physical-layer-type;
+                units "bits-per-second";
+                default "1G";
+                description
+                                "Physical Layer Connection Speed (Max Data Rate).";
+                reference "[MEF10.3] Section 9.2. [MEF6.2] " +
+                                "Section 8.2.2. [MEF20] [R80].";
+              }
+              leaf phy-auto-neg {
+                type mef-types:auto-negotiation-type;
+                default "on";
+                description
+                                "Auto-Negotiation ON/OFF/Auto.";
+                reference "[MEF6.2] Section 8.2.2. [MEF20] [R80]. " +
+                                "[MEF7.3] Section 10.2.2.";
+              }
+              leaf sync-mode-enabled {
+                type boolean;
+                must ".='false' or (.='true' and " +
+                                "../clock-accuracy)" {
+                  error-message "The quality of the clock " +
+                                    "reference must be set if Synchronous " +
+                                    "Mode is enabled.";
+                  description
+                                    "The quality of the clock reference must " +
+                                    "be set if Synchronous Mode is enabled.";
+                }
+                default "false";
+                description
+                                "Enabled or Disabled for each physical link " +
+                                "implementing the UNI.";
+                reference "[MEF10.3] Section 9.3. [MEF6.2] " +
+                                "Section 8.2.2. [MEF7.3] Section 10.2.2.";
+              }
+              leaf clock-accuracy {
+                type decimal64 {
+                  fraction-digits 3;
+                }
+                units "ppm";
+                description
+                                "ESMC:Ethernet Equipment Slave Clock Accuracy " +
+                                "in PPM. IEEE 802.3 standard specifies " +
+                                "that Ethernet clock accuracy is to be less " +
+                                "than or equal to +- 4.6 PPM.";
+                reference "[MEF10.3] Section 9.3, [R62]. " +
+                                "[MEF22.1], [IEEE802.3].";
+              }
+            }
+          }
+          leaf number-of-links {
+            type uint32 {
+              range "1..max";
+            }
+            must ". = count(../links/link)" {
+              error-message "The UNI Number of Links value " +
+                            "must match to the number of interfaces " +
+                            "in the link list.";
+              description
+                            "The UNI Number of Links value must match " +
+                            "to the number of interfaces in the link list.";
+            }
+            default "1";
+            description
+                        "The number of links configured in the links list.";
+            reference "[MEF10.3] [R63]. [MEF7.3] Section 10.2.2.";
+          }
+        }
+        container ce-vlans {
+          description
+                    "Each Device (and by extension UNIs) MUST have list " +
+                    "of the CE-VLAN ID including mappings to configured " +
+                    "EVCs if assigned. This list of ce-vlans is a " +
+                    "complete list of all VLANs associated with this " +
+                    "UNI. At the Service Module level, there are two " +
+                    "lists: This one and the list of CE-VLAN IDs " +
+                    "associated with the EVC's UNI List as part of " +
+                    "the MEF Service Definition. ";
+          reference "[MEF10.3] Section 9.10, [R77], [R78]. " +
+                    "[MEF7.3] Section 10.2.2.";
+          list ce-vlan {
+            key "vid";
+            description
+                        "A list of all EC-VLANs allowed ingres or egress " +
+                        "on the UNI. This is the UNI-specific CE-VLAN ID " +
+                        "listing as part of the Service Level " +
+                        "CE-VLAN ID / EVC Map.";
+            reference "[MEF10.3] Section 9.10.1.";
+            leaf vid {
+              type mef-types:vlan-id-type;
+              description
+                            "The Customer Edge VLAN ID is equivalent " +
+                            "to a Static VLAN allowed on that port " +
+                            "(ie. Port is not Forbidden). The " +
+                            "association with the EVC is part of " +
+                            "the EVC configuration.";
+              reference "[MEF10.3] Section 9.10.";
+            }
+          }
+        }
+        container ingress-envelopes {
+          presence "Ingress Bandwidth Profile Envelopes " +
+                    "configured.";
+          description
+                    "UNI Bandwidth Profile Flow Envelopes.";
+          reference "[MEF10.3] Section 9.15, Section 12.1. " +
+                    "[MEF6.2] Section 8.2.1: [R3]. " +
+                    "[MEF7.3] Section 10.2.2.";
+          list envelope {
+            key "env-id";
+            description
+                        "UNI Bandwidth Profile Flow Envelope List.";
+            reference "[MEF10.3] Section 9.15, Section 12.1. " +
+                        "[MEF6.2] Section 8.2.1, [R3], " +
+                        "Section 8.2.2, [R4]. [MEF7.3] " +
+                        "Section 10.2.2.";
+            container bwp-flows {
+              presence "Bandwidth Profile configured for " +
+                            "this envelope.";
+              description
+                            "UNI Bandwidth Profile Flows per Envelope.";
+              reference "[MEF10.3] Section 12.1. " +
+                            "[MEF6.2] Section 10.1.";
+              list bwp-flow {
+                key "bw-profile";
+                ordered-by user;
+                description
+                                "UNI Bandwidth Profile Flow List per Envelope. " +
+                                "The order of entries in the list is user " +
+                                "controlled. The first element of the list " +
+                                "has the lowest priority and the last " +
+                                "element will have the highest priority.";
+                reference "[MEF10.3] Section 12.1. " +
+                                "[MEF6.2] Section 10.1. " +
+                                "[MEF6.2] Section 8.2.1, [R3]. ";
+                leaf bw-profile {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:" +
+                                        "profiles/mef-global:" +
+                                        "ingress-bwp-flows/mef-global:" +
+                                        "bwp-flow/mef-global:bw-profile";
+                  }
+                  must "(../../../../../token-share-enabled = " +
+                                    "'true') or " +
+                                    "((../../../../../token-share-enabled = " +
+                                    "'false') and " +
+                                    "(count(../../bwp-flow) = 1))" {
+                    error-message "A UNI with Token Share " +
+                                        "Disabled MUST have exactly one " +
+                                        "Bandwidth Profile Flow per envelope.";
+                    description
+                                        "A UNI with Token Share Disabled MUST " +
+                                        "have exactly one Bandwidth Profile Flow " +
+                                        "per envelope.";
+                  }
+                  must "(../../../coupling-enabled = 'false') or " +
+                                    "(/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:" +
+                                    "ingress-bwp-flows/mef-global:bwp-flow" +
+                                    "[mef-global:bw-profile = current()]/" +
+                                    "mef-global:coupling-enabled = 'false')" {
+                    error-message "If an Ingress Envelope's " +
+                                        "Coupling Flag is Enabled, then " +
+                                        "the Coupling Flags must be disabled " +
+                                        "for all Bandwidth Profile Flows " +
+                                        "mapped to the Envelope.";
+                    description
+                                        "If an Ingress Envelope's Coupling Flag is " +
+                                        "Enabled, then the Coupling Flags must " +
+                                        "be disabled for all Bandwidth Profile " +
+                                        "Flows mapped to the Envelope.";
+                  }
+                  description
+                                    "If no Ingress Bandwidth Profile per UNI " +
+                                    "has been defined (ie. 'No'), then the " +
+                                    "behavior has been defined at the Service " +
+                                    "Level of the configuration.";
+                  reference "[MEF10.3] Section 9.14, " +
+                                    "Section 12.1, [R84], [R134]. " +
+                                    "[MEF6.2] Section 8.2.1,[R3],[R136]. " +
+                                    "Section 8.2.2, 10.1, [R6]. [MEF7.3] " +
+                                    "Section 10.2.2.";
+                }
+              }
+            }
+            leaf env-id {
+              type mef-types:identifier45;
+              description
+                            "This attribute identifies the Envelope of " +
+                            "Bandwidth Profile Parameters.";
+              reference "[MEF10.3] Section 12.1.";
+            }
+            leaf coupling-enabled {
+              type boolean;
+              must "not(../bwp-flows) or " +
+                            "(../bwp-flows/bwp-flow[2]) or " +
+                            "(. = 'false')" {
+                error-message "When only one Bandwidth Profile " +
+                                "Flow is mapped to an envelope, Envelope " +
+                                "Coupling must be Disabled.";
+                description
+                                "When only one Bandwidth Profile Flow is " +
+                                "mapped to an envelope, Envelope " +
+                                "Coupling must be Disabled.";
+              }
+              default "false";
+              description
+                            "The Envelope Coupling Flag (CF) attribute.";
+              reference "[MEF10.3] Section 12.1.";
+            }
+          }
+        }
+        container egress-envelopes {
+          presence "Egress Bandwidth Profile Envelopes configured.";
+          description
+                    "UNI Bandwidth Profile Flow Envelopes.";
+          reference "[MEF10.3] Section 9.15, Section 12.1. " +
+                    "[MEF6.2] Section 8.2.1: [R3]. " +
+                    "[MEF7.3] Section 10.2.2.";
+          list envelope {
+            key "env-id";
+            description
+                        "UNI Bandwidth Profile Flow Envelope List.";
+            reference "[MEF10.3] Section 9.15, Section 12.1. " +
+                        "[MEF6.2] Section 8.2.1, [R3], " +
+                        "Section 8.2.2, [R4]. [MEF7.3] " +
+                        "Section 10.2.2.";
+            container bwp-flows {
+              presence "Bandwidth Profile configured for " +
+                            "this envelope.";
+              description
+                            "UNI Bandwidth Profile Flows per Envelope.";
+              reference "[MEF10.3] Section 12.1. [MEF6.2] " +
+                            "Section 10.1.";
+              list bwp-flow {
+                key "bw-profile";
+                ordered-by user;
+                description
+                                "UNI Bandwidth Profile Flow List per Envelope. " +
+                                "The order of entries in the list is user " +
+                                "controlled. The first element of the list " +
+                                "has the lowest priority and the last element " +
+                                "will have the highest priority.";
+                reference "[MEF10.3] Section 12.1. " +
+                                "[MEF6.2] Section 10.1. " +
+                                "[MEF6.2] Section 8.2.1, [R3]. ";
+                leaf bw-profile {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:" +
+                                        "profiles/mef-global:egress-bwp-flows" +
+                                        "/mef-global:bwp-flow/" +
+                                        "mef-global:bw-profile";
+                  }
+                  must "(../../../../../token-share-enabled = " +
+                                    "'true') or " +
+                                    "((../../../../../token-share-enabled = " +
+                                    "'false') and " +
+                                    "(count(../../bwp-flow) = 1))" {
+                    error-message "A UNI with Token Share " +
+                                        "Disabled must have exactly one " +
+                                        "Bandwidth Profile Flow per envelope.";
+                    description
+                                        "A UNI with Token Share Disabled must have " +
+                                        "exactly one Bandwidth Profile Flow per " +
+                                        "envelope.";
+                  }
+                  must "(../../../coupling-enabled = 'false') or " +
+                                    "(/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:" +
+                                    "egress-bwp-flows/mef-global:bwp-flow" +
+                                    "[mef-global:bw-profile = current()]/" +
+                                    "mef-global:coupling-enabled = 'false')" {
+                    error-message "If an Egress Envelope's " +
+                                        "Coupling Flag is Enabled, then the " +
+                                        "Coupling Flags must be disabled " +
+                                        "for all Bandwidth Profile Flows " +
+                                        "mapped to the Envelope.";
+                    description
+                                        "If an Egress Envelope's Coupling Flag " +
+                                        "is Enabled, then the Coupling Flags must " +
+                                        "be disabled for all Bandwidth Profile " +
+                                        "Flows mapped to the Envelope.";
+                  }
+                  description
+                                    "UNI Bandwidth Profile Flow per Envelope.";
+                  reference "[MEF10.3] Section 12.1. " +
+                                    "[MEF6.2] Section 10.1. " +
+                                    "[MEF6.2] Section 8.2.1, [R3], [R136]. ";
+                }
+              }
+            }
+            leaf env-id {
+              type mef-types:identifier45;
+              description
+                            "This attribute identifies the Envelope of " +
+                            "Bandwidth Profile Parameters.";
+              reference "[MEF10.3] Section 12.1.";
+            }
+            leaf coupling-enabled {
+              type boolean;
+              must "not(../bwp-flows) or " +
+                            "(../bwp-flows/bwp-flow[2]) or " +
+                            "(. = 'false')" {
+                error-message "When only one Bandwidth Profile " +
+                                "Flow is mapped to an envelope, " +
+                                "Envelope Coupling must be Disabled.";
+                description
+                                "When only one Bandwidth Profile Flow is " +
+                                "mapped to an envelope, Envelope Coupling " +
+                                "must be Disabled.";
+              }
+              default "false";
+              description
+                            "The Envelope Coupling Flag (CF) attribute.";
+              reference "[MEF10.3] Section 12.1.";
+            }
+          }
+        }
+        container status {
+          description
+                    "This group is related to the MEF 7.3 External " +
+                    "Network Interface";
+          leaf oper-state-enabled {
+            type boolean;
+            default "false";
+            config false;
+            description
+                        "Operational Status of the Link as " +
+                        "Enabled/Disabled.";
+            reference "[MEF15]. [MEF7.3] Section 10.1.1.";
+          }
+          leaf available-status {
+            type mef-types:ext-if-availability-type;
+            default "not-installed";
+            config false;
+            description
+                        "Availability Status of the Link.";
+            reference "[MEF15]. [MEF7.3] Section 10.1.1.";
+          }
+          leaf physical-layer {
+            type mef-types:ext-if-physical-layer-type;
+            default "1G";
+            config false;
+            description
+                        "Physical Layer Connection Speed.";
+            reference "[MEF15]. [MEF7.3] Section 10.1.1.";
+          }
+          leaf number-of-links {
+            type uint32;
+            default "0";
+            config false;
+            description
+                        "A count of the number of physical links in this " +
+                        "physical layer.";
+            reference "[MEF15]. [MEF7.3] Section 10.1.1.";
+          }
+          leaf svc-frame-format {
+            type mef-types:svc-frame-format-type;
+            default "ctag";
+            config false;
+            description
+                        "The format must be that of a MAC Frame specified " +
+                        "in IEEE Std 802.3-2012 Clause 3.";
+            reference "[MEF10.3] Section 9.6. [MEF15]. " +
+                        "[MEF7.2]. [MEF7.3] Section 10.1.1.";
+          }
+        }
+        leaf cen-id {
+          when "/mef-global:mef-global/mef-global:cens" {
+            description
+                        "Only configure when the Global CENs list " +
+                        "has been populated.";
+          }
+          type leafref {
+            path "/mef-global:mef-global/mef-global:cens/" +
+                        "mef-global:cen/mef-global:cen-id";
+          }
+          description
+                    "A CEN is defined as a network from a Service " +
+                    "Provider (SP). The CEN ID must be unique for " +
+                    "a specific Service Provider.";
+          reference "[MEF10.3] Section 7.";
+        }
+        leaf uni-id {
+          type mef-types:identifier45;
+          description
+                    " The UNI IDs must be be unique within a specific CEN.";
+          reference "[MEF10.3] Section 9.1, [R1], [R57], [R58], " +
+                    "[R59]. [MEF7.3] Section 10.2.2.";
+        }
+        leaf uni-type {
+          type mef-types:uni-mode-type;
+          default "uni";
+          description
+                    " The UNI Type must be one of {UNI, VUNI}.";
+          reference "[MEF10.3] Section 9.1, [R1], [R57], [R58], " +
+                    "[R59]. [MEF7.3] Section 10.2.2.";
+        }
+        leaf subscriber {
+          when "/mef-global:mef-global/mef-global:subscribers" {
+            description
+                        "UNI Subscriber Attribute is only configurable " +
+                        "when multiple Global Subscribers have been " +
+                        "configured.";
+          }
+          type leafref {
+            path "/mef-global:mef-global/mef-global:subscribers/" +
+                        "mef-global:subscriber/mef-global:sub-id";
+          }
+          description
+                    "A UNI MUST be dedicated to a single Subscriber. " +
+                    "This value can only be configured if the " +
+                    "'/mef-global/subscribers/subscriber' list " +
+                    "has been populated.";
+          reference "[MEF10.3] Section 7.";
+        }
+        leaf admin-state-enabled {
+          type boolean;
+          default "true";
+          description
+                    "Locked/Unlocked is inconsistent with Oper Status " +
+                    "and will be confusing.";
+          reference "MEF 15. MEF 7.3 Section 10.1.1.";
+        }
+        leaf mac-address {
+          type yang:mac-address;
+          description
+                    "MAC Address.";
+          reference "[MEF15]. [MEF7.3] Section 10.1.1.";
+        }
+        leaf uni-resiliency {
+          type mef-types:uni-resiliency-type;
+          must "(. != 'none') or ((. = 'none') and " +
+                    "(../physical-layers/number-of-links = 1))" {
+            error-message "If uni-resiliency is 'none', " +
+                        "number-of-links must be 1.";
+            description
+                        "If uni-resiliency is 'none', number-of-links " +
+                        "must be 1.";
+          }
+          must "(. != 'dual-link-aggregation') or " +
+                    "((. = 'dual-link-aggregation') and " +
+                    "(../physical-layers/number-of-links = 2))" {
+            error-message "If uni-resiliency is " +
+                        "'dual-link-aggregation', " +
+                        "number-of-links must be 2.";
+            description
+                        "If uni-resiliency is 'dual-link-aggregation', " +
+                        "number-of-links must be 2.";
+          }
+          must "(. != 'other') or " +
+                    "((. = 'other') and " +
+                    "(../physical-layers/number-of-links > 2))" {
+            error-message "If uni-resiliency is 'other', " +
+                        "number-of-links must be 3 or greater.";
+            description
+                        "If uni-resiliency is 'other', number-of-links " +
+                        "must be 3 or greater.";
+          }
+          default "none";
+          description
+                    "UNI Resiliency.";
+          reference "[MEF10.3] Section 9.5 [R64], [R65], [R66], " +
+                    "[R67]. [MEF6.2] Section 8.2.2.";
+        }
+        leaf max-svc-frame-size {
+          type mef-types:max-svc-frame-size-type;
+          default "1600";
+          description
+                    "This attribute describes the maximum service frame " +
+                    "size for the UNI.";
+          reference "[MEF10.3] Section 9.7, [R71], MEF 6.2 " +
+                    "Section 8.2.2 and MEF 22.1: [D2]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf svc-mux-enabled {
+          type boolean;
+          default "false";
+          description
+                    "Service Multiplexing Enable - Enable if to support " +
+                    "multiple EVCs per UNI.";
+          reference "[MEF10.3] Section 9.8. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf bundling-enabled {
+          type boolean;
+          default "false";
+          description
+                    "When a UNI has Bundling Enabled, it MUST be able to " +
+                    "support more than one CE-VLAN ID mapping to a " +
+                    "particular EVC at the UNI.  When more than one " +
+                    "CE-VLAN-ID is mapped to an EVC at a UNI, the " +
+                    "EVC have CE-VLAN ID Preservation enabled";
+          reference "[MEF10.3] Section 9.12, [R25], [R77], " +
+                    "[R78], [R80]. [MEF7.3] Section 10.2.2.";
+        }
+        leaf all-to-one-bundling-enabled {
+          type boolean;
+          default "false";
+          description
+                    "When all-to-one-bundling-enabled = true, all " +
+                    "CE-VLAN IDs MUST map to a single EVC at the " +
+                    "UNI. This also means that the UNI cannot " +
+                    "have svc-mux-enabled = true. When " +
+                    "all-to-one-bundling-enabled = true, " +
+                    "all other UNIs in the EVC associating this UNI " +
+                    "must have all-to-one-bundling-enabled = true. " +
+                    "If this values is true, the value of " +
+                    "ce-vlan-id-for-untagged-and-priority is not " +
+                    "applicable.";
+          reference "[MEF10.3] Section 9.13, Table 12 " +
+                    "(5 valid combinations), [R82], [R83]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf ce-vlan-id-for-untagged-and-priority {
+          type mef-types:vlan-id-type;
+          default "1";
+          description
+                    "The ce-vlan-id-for-untagged-and-priority is " +
+                    "equivalent to the Layer 2 PVID (Port VLAN ID) " +
+                    "with the Q-BRIDGE-MIB option for frame admitance set " +
+                    "to admitAll. With AdmitAll set, all Untagged and " +
+                    "Priority Tagged Service Frames are treated with " +
+                    "the CE-VLAN-ID tag on ingress. It is not applicable " +
+                    "if All in One Bundling is enabled.";
+          reference "[MEF10.3] Section 9.9, [R73], [R74], " +
+                    "[R75]. [MEF7.3] Section 10.2.2.";
+        }
+        leaf max-evc-count {
+          type uint32 {
+            range "1..max";
+          }
+          default "1";
+          description
+                    "The Maximum Number of EVCs that can be supported " +
+                    "by this UNI (Default 1).";
+          reference "[MEF10.3] Section 9.11, [R79]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf token-share-enabled {
+          type boolean;
+          default "false";
+          description
+                    "Token Share Enabled/Disabled is used to indicate " +
+                    "whether a given UNI is capable of sharing tokens " +
+                    "across Bandwidth Profile Flows in an envelope.";
+          reference "[MEF6.2] Section 8.2.1, [R2], [D1], [R3]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf ingress-bw-profile-per-uni {
+          type leafref {
+            path "/mef-global:mef-global/mef-global:profiles/" +
+                        "mef-global:ingress-bwp-flows/mef-global:" +
+                        "bwp-flow/mef-global:bw-profile";
+          }
+          description
+                    "Ingress Bandwidth Profile for this UNI.";
+          reference "[MEF10.3] Section 9.15, Section 12.1. " +
+                    "[MEF6.2] Section 8.2.1: [R3]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf egress-bw-profile-per-uni {
+          type leafref {
+            path "/mef-global:mef-global/mef-global:profiles/" +
+                        "mef-global:egress-bwp-flows/mef-global:" +
+                        "bwp-flow/mef-global:bw-profile";
+          }
+          description
+                    "Egress Bandwidth Profile Flow for this UNI.";
+          reference "[MEF10.3] Section 9.15, Section 12.1. " +
+                    "[MEF6.2] Section 8.2.1: [R3]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf link-oam-enabled {
+          type boolean;
+          default "false";
+          description
+                    "Link OAM Enabled/Disabled.";
+          reference "[MEF10.3] Section 9.16, [R86]. " +
+                    "[MEF6.2] Section 8.2.2, [D3]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf uni-meg-enabled {
+          type boolean;
+          default "false";
+          description
+                    "Enables / Disables the Maintenance Entity Group (MEG).";
+          reference "[MEF10.3] Section 9.17, [R87]. " +
+                    "[MEF30.1] Section 7.9. [MEF6.2] Section 8.2.2, " +
+                    "[D4]. [MEF7.3] Section 10.2.2.";
+        }
+        leaf elmi-enabled {
+          type boolean;
+          must "(. = 'false') or " +
+                    "(. = 'true' and " +
+                    "(../elmi-profile))" {
+            error-message "ELMI Profile must be set if " +
+                        "ELMI is Enabled.";
+            description
+                        "Ethernet Local Management Interface(ELMI) " +
+                        "Profile ID must be set if ELMI is Enabled.";
+          }
+          default "false";
+          description
+                    "Ethernet Local Management Interface(ELMI) " +
+                    "Enabled / Disabled.";
+          reference "[MEF10.3] Section 9.18, [R88]. " +
+                    "[MEF16]. [MEF6.2] Section 8.2.2, [D5]. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf elmi-profile {
+          type leafref {
+            path "/mef-global:mef-global/mef-global:profiles/" +
+                        "mef-global:elmi/mef-global:elmi-profile/" +
+                        "mef-global:id";
+          }
+          description
+                    "The ELMI Profile is only applicable when ELMI " +
+                    "is enabled. The E-LMI protocol is based on " +
+                    "ITU-T Q.933, X.36 and other relevant " +
+                    "recommendations as well as Frame Relay " +
+                    "Local Management Interface (FR-LMI) " +
+                    "Implementation Agreement document defined " +
+                    "by the Frame Relay Forum and related " +
+                    "ITU-T recommendations.";
+          reference "[MEF10.3] Section 9.18. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf l2cp-address-set {
+          type mef-types:l2cp-address-set-type;
+          default "aware-cta";
+          description
+                    "The L2CP Address Set Service Attribute specifies " +
+                    "the subset of the Bridge Reserved Addresses " +
+                    "that are filtered (i.e. L2CP Frames with " +
+                    "this destination address are Peered or " +
+                    "Discarded but not Passed) at a L2CP Decision Point.";
+          reference "[MEF10.3] Section 9.19. " +
+                    "[MEF45] Section 8.1, [R2] through [R9]. " +
+                    "[MEF6.2] Section 8.2.2, [R1]. " +
+                    "[MEF45] Section 8.1.";
+        }
+        leaf l2cp-peering-profile {
+          type leafref {
+            path "/mef-global:mef-global/mef-global:profiles/" +
+                        "mef-global:l2cp-peering/mef-global:" +
+                        "l2cp-profile/mef-global:id";
+          }
+          description
+                    "L2CP Peering Profile for this UNI. This profile " +
+                    "may contain groups of L2CP Destination " +
+                    "MAC Addresses and protocols to be peered at " +
+                    "the UNI (as opposed to being passed or discarded).";
+          reference "[MEF10.3] Section 9.19. " +
+                    "[MEF45] Section 8.2. " +
+                    "[MEF7.3] Section 10.2.2.";
+        }
+        leaf tenant-id {
+          type leafref {
+            path "/mef-global:mef-global/mef-global:tenants-instances/mef-global:tenant-list/mef-global:name";
+          }
+        }
+      }
+    }
+
+    container subnets {
+      list subnet {
+        key "uni-id ip-uni-id subnet";
+        leaf uni-id {
+          type leafref {
+            path "/mef-interfaces:mef-interfaces/mef-interfaces:unis/mef-interfaces:uni/mef-interfaces:uni-id";
+          }
+        }
+        leaf ip-uni-id {
+          type leafref {
+            path "/mef-interfaces:mef-interfaces/mef-interfaces:unis/mef-interfaces:uni/" +
+                 "mef-interfaces:ip-unis/mef-interfaces:ip-uni/mef-interfaces:ip-uni-id";
+          }
+        }
+        leaf subnet {type inet:ip-prefix;}
+        leaf gateway {type inet:ip-address;}
+      }
+    }
+
+  }
+
+  augment "/mef-interfaces:mef-interfaces/mef-interfaces:unis/mef-interfaces:uni" {
+    ext:augment-identifier "port-vlan-mapping";
+    list vlan-to-port {
+      key "vlan";
+      leaf vlan {
+        type mef-types:vlan-id-or-none-type;
+      }
+      leaf vlan-port-id {
+        type string;
+      }
+    }
+  }
+
+}
index a0b81fdbda4da7dc79bcca4fb608a88dc39545af..13b27c50628a97220ddcaade1f17012c32b13cf3 100644 (file)
-module mef-services {\r
-  namespace "http://metroethernetforum.org/ns/yang/mef-services";\r
-  prefix mef-services;\r
-  import ietf-yang-types { prefix yang; }\r
-  import ietf-inet-types { prefix inet; }\r
-  import mef-types { prefix mef-types; }\r
-  import mef-global { prefix mef-global; }\r
-  import mef-interfaces { prefix mef-interfaces; }\r
-  organization "Metro Ethernet Forum";\r
-  contact\r
-    "Web URL: http://metroethernetforum.org/ E-mail: mibs@metroethernetforum.org\r
-    Postal: Metro Ethernet Forum 6033 W. Century Boulevard, Suite\r
-    1107 Los Angeles, CA 90045 U.S.A. Phone: +1 310-642-2800 Fax:\r
-    +1 310-642-2808";\r
-  description\r
-    "This module implements the Carrier Ethernet Services as defined\r
-    in MEF 10.3, MEF 6.2, and MEF 7.2. Reference Overview: A number\r
-    of base documents have been used to create the MEF Services YANG\r
-    Module. The following are the abbreviations for the baseline documents:\r
-    [RFC 6991] refers to IETF RFC 6991 'Common YANG Data Types', 2013-07-15\r
-    [RFC 6643] refers to IETF RFC 6643 'Translation of Structure of\r
-    Management Information Version 2 (SMIv2) MIB Modules to YANG Modules',\r
-    2011-11-25 [802.1AB] refers to 'Station and Media Access Control\r
-    Connectivity Discovery', IEEE 802.1AB-2009, September 2009 [802.1q]\r
-    refers to IEEE 802.1Q-2011 'IEEE Standard for Local and metropolitan\r
-    area networks --Media Access Control (MAC) Bridges and Virtual\r
-    Bridged Local Area Networks, August 2011 [802-2001] refers to\r
-    'IEEE Standard for Local and Metropolitan Area Networks: Overview\r
-    and Architecture', IEEE 802-2001, February 2002 [MEF10.3] refers\r
-    to MEF 10.3 'Ethernet Services Attributes Phase 3', October 2013\r
-    [MEF6.2] refers to MEF 6.2 'EVC Ethernet Services Defintions Phase\r
-    3', August 2014 [MEF40] refers to MEF 40 'UNI and EVC Definition\r
-    of Managed Objects', April 2013 [MEF45] refers to MEF 45 'Multi-CEN\r
-    L2CP', August 2014 [MEF7.2] refers to MEF 7.2 'Carrier Ethernet\r
-    Management Information Model', April 2013 [MEF7.3] refers to MEF\r
-    7.3 'Carrier Ethernet Management Information Model', Working Draft\r
-    #1 2015 [RFC 2737] refers to IETF RFC 2737 'Entity MIB (Version\r
-    2)', December 1999 [RFC 2863] refers to IETF RFC 2863 'The Interfaces\r
-    Group MIB', June 2000 [RFC 3419] refers to IETF RFC 3419 'Textual\r
-    Conventions for Transport Addresses', December 2002 [Y.1731] refers\r
-    to ITU-T Y.1731 'OAM functions and mechanisms for Ethernet based\r
-    networks', July 2011 [Q.840.1] refers to ITU-T Q.840.1 'Requirements\r
-    and analysis for NMS-EMS management interface of Ethernet over\r
-    Transport and Metro Ethernet Network(EoT/MEN)' March 2007";\r
-  revision 2015-05-26 {\r
-    description\r
-        "Formal Project Review Draft 1.";\r
-    reference "EVC Ethernet Services Definitions YANG Modules " +\r
-        "(MEF XX), TBD";\r
-  }\r
-\r
-  container mef-services {\r
-    description\r
-        "MEF Services";\r
-    list mef-service {\r
-      must "(not(/mef-global:mef-global/mef-global:svc-providers)" +\r
-            " and " +\r
-            "not(./sp-id)) or " +\r
-            "(/mef-global:mef-global/mef-global:svc-providers and " +\r
-            "./sp-id)" {\r
-        error-message "If the Service Providers list has been " +\r
-                "populated, a Service Provider ID must be " +\r
-                "configured for a Service.";\r
-        description\r
-                "A Service sees a single Service Provider. This must " +\r
-                "statement is effectively a 'mandatory true' when " +\r
-                "the Global Service Providers list is being used.";\r
-      }\r
-      key "svc-id";\r
-      unique "evc/evc-id";\r
-      unique "ipvc/ipvc-id";\r
-      description\r
-            "Metro Ethernet Forum's Ethernet Services.";\r
-      choice mef-service-choice {\r
-        case ipvc-choice {\r
-          container ipvc {\r
-            container unis {\r
-              list uni {\r
-                key "uni-id";\r
-                leaf uni-id {\r
-                  type leafref {\r
-                    path "/mef-interfaces:mef-interfaces/" +\r
-                                        "mef-interfaces:unis/mef-interfaces:uni/" +\r
-                                        "mef-interfaces:uni-id";\r
-                  }\r
-                }\r
-                leaf ip-uni-id {\r
-                  type mef-types:identifier45;\r
-                }\r
-\r
-                container evc-uni-ce-vlans {\r
-                  description\r
-                                    "EVC Per UNI CE-VLAN IDs.";\r
-                  list evc-uni-ce-vlan {\r
-                    key "vid";\r
-                    description\r
-                                        "A list of the CE-VLAN IDs mapped to this UNI " +\r
-                                        "for this EVC.";\r
-                    reference "[MEF10.3] Section 8.6.1, [R24] " +\r
-                                        "[R25], Section 9.10.2, Section 9.12, " +\r
-                                        "[R76], [R81].";\r
-                    leaf vid {\r
-                      type leafref {\r
-                        path "/mef-interfaces:mef-interfaces/" +\r
-                                                "mef-interfaces:unis/" +\r
-                                                "mef-interfaces:uni" +\r
-                                                "[mef-interfaces:uni-id = " +\r
-                                                "current()/../../../uni-id]" +\r
-                                                "/mef-interfaces:ce-vlans/" +\r
-                                                "mef-interfaces:ce-vlan/" +\r
-                                                "mef-interfaces:vid";\r
-                      }\r
-                      description\r
-                                            "VLAN Identifier.";\r
-                    }\r
-                  }\r
-                }\r
-              }\r
-            }\r
-\r
-            leaf ipvc-id {\r
-              type mef-types:evc-id-type;\r
-              mandatory true;\r
-            }\r
-            leaf ipvc-type {\r
-              type mef-types:ipvc-type;\r
-\r
-              mandatory true;\r
-              description\r
-                            "This IPVC attribute describes the IPVC as either " +\r
-                            "Cloud-access, Multipoint, or " +\r
-                            "Rooted-Multipoint.";\r
-            }\r
-          }\r
-        }\r
-        case evc-choice {\r
-          container evc {\r
-\r
-            must "not(sls-uni-inclusions) or " +\r
-                        "(sls-uni-inclusions and not(sls-uni-exclusions))" {\r
-              error-message "The EVC Performance SLS Exclusions and " +\r
-                            "Inclusions List cannot both be configured for " +\r
-                            "an EVC.";\r
-              description\r
-                            "The EVC Performance SLS Exclusions and Inclusions " +\r
-                            "List cannot both be configured for an EVC.";\r
-            }\r
-            must "(evc-type != 'rooted-multipoint') or " +\r
-                        "((evc-type = 'rooted-multipoint') and " +\r
-                        "not(sls-uni-exclusions) )" {\r
-              error-message "If EVC Type is Rooted-Multipoint, " +\r
-                            "sls-uni-inclusions must be used instead of " +\r
-                            "sls-uni-exclusions.";\r
-              description\r
-                            "If EVC Type is Rooted-Multipoint, " +\r
-                            "sls-uni-inclusions must be used instead of " +\r
-                            "sls-uni-exclusions.";\r
-            }\r
-            description\r
-                        "Ethernet Virtual Circuit(EVC) Configuration and Status.";\r
-            container unis {\r
-              description\r
-                            "EVC Per Universal Network Interface(UNI) " +\r
-                            "Configuration and Status.";\r
-              list uni {\r
-                must "not(evc-uni-ce-vlans/evc-uni-ce-vlan[2]) or " +\r
-                                "../../preserve-ce-vlan-id = 'true'" {\r
-                  error-message "When more than one CE-VLAN-ID is " +\r
-                                    "mapped to an EVC at a UNI, the EVC must have " +\r
-                                    "CE-VLAN ID Preservation Enabled.";\r
-                  description\r
-                                    "When more than one CE-VLAN-ID is mapped to " +\r
-                                    "an EVC at a UNI, the EVC must have CE-VLAN ID " +\r
-                                    "Preservation Enabled.";\r
-                }\r
-                must "/mef-interfaces:mef-interfaces/mef-interfaces:" +\r
-                                "unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                                "max-svc-frame-size >= current()/../../" +\r
-                                "mef-services:max-svc-frame-size]" {\r
-                  error-message "The value of the EVC Maximum " +\r
-                                    "Service Frame Size must be less than " +\r
-                                    "or equal to all the UNI Maximum Service " +\r
-                                    "Frame Sizes.";\r
-                  description\r
-                                    "The value of the EVC Maximum Service Frame " +\r
-                                    "Size must be less than or equal to all the " +\r
-                                    "UNI Maximum Service Frame Sizes.";\r
-                }\r
-                must "(/mef-interfaces:mef-interfaces/mef-interfaces:" +\r
-                                "unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                                "bundling-enabled = 'true']) or " +\r
-                                "(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                                "all-to-one-bundling-enabled = 'true']) or " +\r
-                                "not(evc-uni-ce-vlans/evc-uni-ce-vlan[2])" {\r
-                  error-message "If both Bundling and All-to-One " +\r
-                                    "Bundling are disabled for a UNI, only one " +\r
-                                    "CE VLAN ID can be configured for a specific " +\r
-                                    "EVC on that UNI.";\r
-                  description\r
-                                    "If both Bundling and All-to-One Bundling are " +\r
-                                    "disabled for a UNI, only one CE VLAN ID can be " +\r
-                                    "configured for a specific EVC on that UNI.";\r
-                }\r
-                must "(/mef-interfaces:mef-interfaces/mef-interfaces:" +\r
-                                "unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                                "all-to-one-bundling-enabled = 'false']) or " +\r
-                                "(count(/mef-services:mef-services/" +\r
-                                "mef-service/evc/unis/uni[uni-id = " +\r
-                                "current()/uni-id]) = 1)" {\r
-                  error-message "If All-to-One Bundling is enabled " +\r
-                                    "for any UNI in an EVC, all CE-VLAN IDs " +\r
-                                    "mapped to any EVC for that UNI must map " +\r
-                                    "to the same EVC ID.";\r
-                  description\r
-                                    "If All-to-One Bundling is enabled for any UNI " +\r
-                                    "in an EVC, all CE-VLAN IDs mapped to any EVC " +\r
-                                    "for that UNI must map to the same EVC ID.";\r
-                }\r
-                must "((/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                                "ingress-bw-profile-per-uni]) or " +\r
-                                "(/mef-services:mef-services/mef-service/" +\r
-                                "evc/unis/uni" +\r
-                                "[uni-id = current()/mef-services:uni-id]" +\r
-                                "/ingress-bwp-flows-per-cos) or " +\r
-                                "(/mef-services:mef-services/mef-service/" +\r
-                                "evc/unis/uni" +\r
-                                "[uni-id = current()/mef-services:uni-id]" +\r
-                                "/ingress-bw-profile-per-evc)) or " +\r
-                                "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-envelopes)" {\r
-                  error-message "If no Ingress Bandwidth Profiles " +\r
-                                    "are specied for this UNI (BW Profile " +\r
-                                    "Per UNI, BWP Flows Per CoS, nor BW Profile " +\r
-                                    "Per EVC), then the UNI Ingress Envelopes " +\r
-                                    "list must be empty.";\r
-                  description\r
-                                    "If no Ingress Bandwidth Profiles are specied " +\r
-                                    "for this UNI (BW Profile Per UNI, BWP Flows " +\r
-                                    "Per CoS, nor BW Profile Per EVC), then the " +\r
-                                    "UNI Ingress Envelopes list must be empty.";\r
-                }\r
-                must "((/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                                "egress-bw-profile-per-uni]) or " +\r
-                                "(/mef-services:mef-services/mef-service/" +\r
-                                "evc/unis/uni" +\r
-                                "[uni-id = current()/mef-services:uni-id]" +\r
-                                "/egress-bwp-flows-per-eec) or " +\r
-                                "(/mef-services:mef-services/mef-service/" +\r
-                                "evc/unis/uni" +\r
-                                "[uni-id = current()/mef-services:uni-id]" +\r
-                                "/egress-bw-profile-per-evc)) or " +\r
-                                "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-envelopes)" {\r
-                  error-message "If no Egress Bandwidth Profiles are " +\r
-                                    "specied for this UNI (BW Profile Per UNI, " +\r
-                                    "BWP Flows Per EEC, nor BW Profile Per EVC), " +\r
-                                    "then the UNI Egress Envelopes list must be " +\r
-                                    "empty.";\r
-                  description\r
-                                    "If no Egress Bandwidth Profiles are specied " +\r
-                                    "for this UNI (BW Profile Per UNI, BWP Flows " +\r
-                                    "Per EEC, nor BW Profile Per EVC), then the UNI " +\r
-                                    "Egress Envelopes list must be empty.";\r
-                }\r
-                must "not(./ingress-bw-profile-per-evc) or " +\r
-                                "((./ingress-bw-profile-per-evc) and " +\r
-                                "not(./ingress-bwp-flows-per-cos))" {\r
-                  error-message "If there is a per EVC Ingress " +\r
-                                    "Bandwidth Profile on an EVC, then there " +\r
-                                    "cannot be any per Class of Service Ingress " +\r
-                                    "Bandwidth Profiles on that EVC.";\r
-                  description\r
-                                    "If there is a per EVC Ingress Bandwidth Profile " +\r
-                                    "on an EVC, then there cannot be any per " +\r
-                                    "Class of Service Ingress Bandwidth Profiles " +\r
-                                    "on that EVC.";\r
-                }\r
-                must "not(./egress-bw-profile-per-evc) or " +\r
-                                "((./egress-bw-profile-per-evc) and " +\r
-                                "not(./egress-bwp-flows-per-eec))" {\r
-                  error-message "If there is a per EVC Egress " +\r
-                                    "Bandwidth Profile on an EVC, then there " +\r
-                                    "cannot be any per Egress Equivalence " +\r
-                                    "Class Identifier Bandwidth Profiles on " +\r
-                                    "that EVC.";\r
-                  description\r
-                                    "If there is a per EVC Egress Bandwidth " +\r
-                                    "Profile on an EVC, then there cannot be " +\r
-                                    "any per Egress Equivalence Class Identifier " +\r
-                                    "Bandwidth Profiles on that EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-bw-profile-" +\r
-                                "per-uni) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:ingress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-bw-profile-per-uni]" +\r
-                                "[mef-global:cir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:ingress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-bw-profile-per-uni]" +\r
-                                "[mef-global:cbs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Ingress Bandwidth Profile Per UNI: " +\r
-                                    "If CIR > 0, CBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                  description\r
-                                    "Ingress Bandwidth Profile Per UNI: If CIR > 0, " +\r
-                                    "CBS must be greater than or equal to the " +\r
-                                    "EVC Max Service Frame Size for the EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-bw-profile-per-uni) " +\r
-                                "or " +\r
-                                "(/mef-global:mef-global/mef-global:profiles/" +\r
-                                "mef-global:egress-bwp-flows/mef-global:" +\r
-                                "bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-bw-profile-per-uni]" +\r
-                                "[mef-global:cir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:profiles/" +\r
-                                "mef-global:ingress-bwp-flows/mef-global:" +\r
-                                "bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-bw-profile-per-uni]" +\r
-                                "[mef-global:cbs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Egress Bandwidth Profile Per UNI: " +\r
-                                    "If CIR > 0, CBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                  description\r
-                                    "Egress Bandwidth Profile Per UNI: If CIR > 0, " +\r
-                                    "CBS must be greater than or equal to the " +\r
-                                    "EVC Max Service Frame Size for the EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-envelopes) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:ingress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:cir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:ingress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:cbs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Ingress Bandwidth Profile Envelope: " +\r
-                                    "If CIR > 0, CBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                  description\r
-                                    "Ingress Bandwidth Profile Envelope: " +\r
-                                    "If CIR > 0, CBS must be greater than " +\r
-                                    "or equal to the EVC Max Service Frame " +\r
-                                    "Size for the EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-envelopes) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:egress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = " +\r
-                                "/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:cir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:egress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:cbs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Egress Bandwidth Profile " +\r
-                                    "Envelope: If CIR > 0, CBS must be greater " +\r
-                                    "than or equal to the EVC Max Service Frame " +\r
-                                    "Size for the EVC.";\r
-                  description\r
-                                    "Egress Bandwidth Profile Envelope: If CIR > 0, " +\r
-                                    "CBS must be greater than or equal to the " +\r
-                                    "EVC Max Service Frame Size for the EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-bw-profile-per-uni) " +\r
-                                "or " +\r
-                                "(/mef-global:mef-global/mef-global:profiles/" +\r
-                                "mef-global:ingress-bwp-flows/mef-global:" +\r
-                                "bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]/mef-interfaces:" +\r
-                                "ingress-bw-profile-per-uni]" +\r
-                                "[mef-global:eir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:profiles/" +\r
-                                "mef-global:ingress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-bw-profile-per-uni]" +\r
-                                "[mef-global:ebs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Ingress Bandwidth Profile Per UNI: " +\r
-                                    "If EIR > 0, EBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                  description\r
-                                    "Ingress Bandwidth Profile Per UNI: If EIR > 0, " +\r
-                                    "EBS must be greater than or equal to the " +\r
-                                    "EVC Max Service Frame Size for the EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-bw-profile-" +\r
-                                "per-uni) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:egress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]/mef-interfaces:" +\r
-                                "egress-bw-profile-per-uni]" +\r
-                                "[mef-global:eir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:ingress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]/mef-interfaces:" +\r
-                                "egress-bw-profile-per-uni]" +\r
-                                "[mef-global:ebs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Egress Bandwidth Profile Per UNI: " +\r
-                                    "If EIR > 0, EBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                  description\r
-                                    "Egress Bandwidth Profile Per UNI: If EIR > 0, " +\r
-                                    "EBS must be greater than or equal to the " +\r
-                                    "EVC Max Service Frame Size for the EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:" +\r
-                                "unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-envelopes) or " +\r
-                                "(/mef-global:mef-global/mef-global:profiles/" +\r
-                                "mef-global:ingress-bwp-flows/mef-global:" +\r
-                                "bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:eir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:profiles/" +\r
-                                "mef-global:ingress-bwp-flows/mef-global:" +\r
-                                "bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:ingress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:ebs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Ingress Bandwidth Profile Envelope: " +\r
-                                    "If EIR > 0, EBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                  description\r
-                                    "Ingress Bandwidth Profile Envelope: " +\r
-                                    "If EIR > 0, EBS must be greater than or equal " +\r
-                                    "to the EVC Max Service Frame Size for the EVC.";\r
-                }\r
-                must "not(/mef-interfaces:mef-interfaces/" +\r
-                                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-envelopes) or " +\r
-                                "(/mef-global:mef-global/mef-global:" +\r
-                                "profiles/mef-global:egress-bwp-flows/" +\r
-                                "mef-global:bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:eir = 0]) or " +\r
-                                "(/mef-global:mef-global/mef-global:profiles/" +\r
-                                "mef-global:egress-bwp-flows/mef-global:" +\r
-                                "bwp-flow" +\r
-                                "[mef-global:bw-profile = /mef-interfaces:" +\r
-                                "mef-interfaces/mef-interfaces:unis/" +\r
-                                "mef-interfaces:uni" +\r
-                                "[mef-interfaces:uni-id = current()/" +\r
-                                "mef-services:uni-id]" +\r
-                                "/mef-interfaces:egress-envelopes/" +\r
-                                "mef-interfaces:envelope/mef-interfaces:" +\r
-                                "bwp-flows/mef-interfaces:bwp-flow/" +\r
-                                "mef-interfaces:bw-profile]" +\r
-                                "[mef-global:ebs >= current()/../../" +\r
-                                "max-svc-frame-size])" {\r
-                  error-message "Egress Bandwidth Profile Envelope: " +\r
-                                    "If EIR > 0, EBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                  description\r
-                                    "Egress Bandwidth Profile Envelope: " +\r
-                                    "If EIR > 0, EBS must be greater than or " +\r
-                                    "equal to the EVC Max Service Frame Size " +\r
-                                    "for the EVC.";\r
-                }\r
-                key "uni-id";\r
-                description\r
-                                "EVC Flow Points and EVC-UNI List defines the " +\r
-                                "roles of each UNI in the Service. One UNI can " +\r
-                                "be used by 0 or more EVCs.";\r
-                reference "[MEF10.3] Section 8.3. " +\r
-                                "[MEF7.3] Section 12.2.2.";\r
-                container evc-uni-ce-vlans {\r
-                  description\r
-                                    "EVC Per UNI CE-VLAN IDs.";\r
-                  list evc-uni-ce-vlan {\r
-                    key "vid";\r
-                    description\r
-                                        "A list of the CE-VLAN IDs mapped to this UNI " +\r
-                                        "for this EVC.";\r
-                    reference "[MEF10.3] Section 8.6.1, [R24] " +\r
-                                        "[R25], Section 9.10.2, Section 9.12, " +\r
-                                        "[R76], [R81].";\r
-                    leaf vid {\r
-                      type leafref {\r
-                        path "/mef-interfaces:mef-interfaces/" +\r
-                                                "mef-interfaces:unis/" +\r
-                                                "mef-interfaces:uni" +\r
-                                                "[mef-interfaces:uni-id = " +\r
-                                                "current()/../../../uni-id]" +\r
-                                                "/mef-interfaces:ce-vlans/" +\r
-                                                "mef-interfaces:ce-vlan/" +\r
-                                                "mef-interfaces:vid";\r
-                      }\r
-                      must "not(current()/../../" +\r
-                                            "evc-uni-ce-vlan[2]) or " +\r
-                                            "(count(../../../../uni/evc-uni-ce-vlans/" +\r
-                                            "evc-uni-ce-vlan" +\r
-                                            "[vid = current()]) = " +\r
-                                            "count(../../../../uni))" {\r
-                        error-message "If more than one CE-VLAN ID " +\r
-                                                "is configured for a UNI as part of " +\r
-                                                "an EVC, every CE VLAN-ID mapped to " +\r
-                                                "that EVC must be configured for all " +\r
-                                                "UNIs within that EVC.";\r
-                        description\r
-                                                "If more than one CE-VLAN ID is configured " +\r
-                                                "for a UNI as part of an EVC, every " +\r
-                                                "CE VLAN-ID mapped to that EVC must be " +\r
-                                                "configured for all UNIs within that EVC.";\r
-                      }\r
-                      description\r
-                                            "VLAN Identifier.";\r
-                    }\r
-                  }\r
-                }\r
-                container ingress-bwp-flows-per-cos {\r
-                  presence "Use Ingress Bandwidth Profiles Per CoS";\r
-                  description\r
-                                    "EVC Per UNI Class of Service Identifiers " +\r
-                                    "corresponding to this EVC's Ingress Bandwidth " +\r
-                                    "Profile Flows.";\r
-                  leaf coupling-enabled {\r
-                    type boolean;\r
-                    default "false";\r
-                    description\r
-                                        "EVC Per UNI Envelope Coupling Flag (CF) " +\r
-                                        "attribute.";\r
-                    reference "[MEF10.3] Section 12.1.";\r
-                  }\r
-                  list bwp-flow-per-cos {\r
-                    key "cos-name";\r
-                    description\r
-                                        "EVC Per UNI: The list of Class of Service " +\r
-                                        "Identifiers corresponding to this UNI's " +\r
-                                        "Ingress Bandwidth Profile Flow.";\r
-                    leaf cos-name {\r
-                      type leafref {\r
-                        path "/mef-global:mef-global/mef-global:" +\r
-                                                "profiles/mef-global:cos-names/" +\r
-                                                "mef-global:cos-name/mef-global:name";\r
-                      }\r
-                      description\r
-                                            "EVC Per UNI: Class of Service Identifier " +\r
-                                            "for this Bandwidth Profile Flow.";\r
-                      reference "[MEF7.3] Section 12.1.2.";\r
-                    }\r
-                    leaf bw-profile {\r
-                      type leafref {\r
-                        path "/mef-interfaces:mef-interfaces/" +\r
-                                                "mef-interfaces:unis/" +\r
-                                                "mef-interfaces:uni" +\r
-                                                "[mef-interfaces:uni-id = " +\r
-                                                "current()/../../../uni-id]" +\r
-                                                "/mef-interfaces:ingress-envelopes/" +\r
-                                                "mef-interfaces:envelope/" +\r
-                                                "mef-interfaces:env-id";\r
-                      }\r
-                      mandatory true;\r
-                      description\r
-                                            "EVC Per UNI: Ingress Bandwidth Profile " +\r
-                                            "Envelope Per CoS ID. If this parameter " +\r
-                                            "is not configured (ie. 'No') this " +\r
-                                            "setting is configured else at the " +\r
-                                            "UNI Level.";\r
-                      reference "[MEF10.3] Section 10.6, Table 28. " +\r
-                                            "[MEF7.3] Section 12.1.2.";\r
-                    }\r
-                  }\r
-                }\r
-                container egress-bwp-flows-per-eec {\r
-                  presence "Using Egress Bandwidth Profiles Per " +\r
-                                    "Egress Equivalence Class";\r
-                  description\r
-                                    "EVC Per UNI: The Egress Equivalence Class " +\r
-                                    "Identifiers corresponding to this EVC's Egress " +\r
-                                    "Bandwidth Profile Flows.";\r
-                  leaf coupling-enabled {\r
-                    type boolean;\r
-                    default "false";\r
-                    description\r
-                                        "EVC Per UNI: The Envelope Coupling Flag (CF) " +\r
-                                        "attribute.";\r
-                    reference "[MEF10.3] Section 12.1.";\r
-                  }\r
-                  list bwp-flow-per-eec {\r
-                    key "eec-name";\r
-                    description\r
-                                        "EVC Per UNI: The list of Egress Equivalence " +\r
-                                        "Class Identifiers corresponding to this " +\r
-                                        "EVC's Egress Bandwidth Profile Flow.";\r
-                    leaf eec-name {\r
-                      type leafref {\r
-                        path "/mef-global:mef-global/mef-global:" +\r
-                                                "profiles/mef-global:eec-names/" +\r
-                                                "mef-global:eec-name/mef-global:name";\r
-                      }\r
-                      description\r
-                                            "EVC Per UNI: Egress Equivalence Class " +\r
-                                            "Identifier for this Bandwidth Profile Flow.";\r
-                      reference "[MEF7.3] Section 12.1.2.";\r
-                    }\r
-                    leaf bw-profile {\r
-                      type leafref {\r
-                        path "/mef-interfaces:mef-interfaces/" +\r
-                                                "mef-interfaces:unis/" +\r
-                                                "mef-interfaces:uni" +\r
-                                                "[mef-interfaces:uni-id = " +\r
-                                                "current()/../../../uni-id]" +\r
-                                                "/mef-interfaces:egress-envelopes/" +\r
-                                                "mef-interfaces:envelope/" +\r
-                                                "mef-interfaces:env-id";\r
-                      }\r
-                      mandatory true;\r
-                      description\r
-                                            "EVC Per UNI: Egress Bandwidth Profile " +\r
-                                            "Envelope Per Equivance Class. If this " +\r
-                                            "parameter is not configured (ie. 'No') " +\r
-                                            "this setting is configured else at the " +\r
-                                            "UNI Level.";\r
-                      reference "[MEF10.3] Section 10.6, Table 28. " +\r
-                                            "[MEF7.3] Section 12.1.2.";\r
-                    }\r
-                  }\r
-                }\r
-                container status {\r
-                  description\r
-                                    "EVC Per UNI: This status group is related to " +\r
-                                    "the MEF 7.3 Service Endpoint";\r
-                  leaf oper-state-enabled {\r
-                    type boolean;\r
-                    default "false";\r
-                    config false;\r
-                    description\r
-                                        "EVC Per UNI: Operational Status of the " +\r
-                                        "Virtual Connection as Enabled/Disabled.";\r
-                    reference "[MEF15]. [MEF7.3] Section 11.2.1.";\r
-                  }\r
-                  leaf available-status {\r
-                    type mef-types:svc-endpoint-availability-type;\r
-                    default "not-installed";\r
-                    config false;\r
-                    description\r
-                                        "EVC Per UNI: Availability Status of the " +\r
-                                        "Virtual Connection.";\r
-                    reference "[MEF15]. [MEF7.3] Section 11.2.1.";\r
-                  }\r
-                }\r
-                leaf uni-id {\r
-                  type leafref {\r
-                    path "/mef-interfaces:mef-interfaces/" +\r
-                                        "mef-interfaces:unis/mef-interfaces:uni/" +\r
-                                        "mef-interfaces:uni-id";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: The UNI ID paired with the EVC ID " +\r
-                                    "in the containing list.";\r
-                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf role {\r
-                  type mef-types:evc-uni-role-type;\r
-                  mandatory true;\r
-                  description\r
-                                    "EVC Per UNI: The UNI Role MUST have the value " +\r
-                                    "of either 'root' or 'leaf'.";\r
-                  reference "[MEF10.3] [R4], [R5], [R10], [R11], " +\r
-                                    "[R12]. [MEF7.3] Section 12.2.2.";\r
-                }\r
-                leaf admin-state-enabled {\r
-                  type boolean;\r
-                  default "true";\r
-                  description\r
-                                    "EVC Per UNI: Locked/Unlocked is inconsistent " +\r
-                                    "with Oper Status and will be confusing.";\r
-                  reference "[MEF15]. [MEF7.3] Section 11.2.1.";\r
-                }\r
-                leaf color-id {\r
-                  type mef-types:cos-color-identifier-type;\r
-                  description\r
-                                    "EVC Per UNI: The Color Identifier for " +\r
-                                    "Service Frames.";\r
-                  reference "[MEF10.3] Section 10.3. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf data-svc-frm-cos {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:profiles/" +\r
-                                        "mef-global:cos/mef-global:cos-profile/" +\r
-                                        "mef-global:id";\r
-                  }\r
-                  must "not(/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:cos/" +\r
-                                    "mef-global:cos-profile" +\r
-                                    "[mef-global:id = current()]" +\r
-                                    "/mef-global:cos-pcp) or " +\r
-                                    "((/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:cos/" +\r
-                                    "mef-global:cos-profile" +\r
-                                    "[mef-global:id = current()]" +\r
-                                    "/mef-global:cos-pcp) and " +\r
-                                    "((../color-id = 'pcp') or " +\r
-                                    "(../color-id = 'dei')) )" {\r
-                    error-message "When the Class of Service " +\r
-                                        "Identifier is based on PCP for a " +\r
-                                        "given EVC at a given UNI, the Color " +\r
-                                        "Identifier must be based on either " +\r
-                                        "DEI or PCP.";\r
-                    description\r
-                                        "When the Class of Service Identifier is " +\r
-                                        "based on PCP for a given EVC at a given UNI, " +\r
-                                        "the Color Identifier must be based on either " +\r
-                                        "DEI or PCP.";\r
-                  }\r
-                  must "not(/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:cos/mef-global:" +\r
-                                    "cos-profile" +\r
-                                    "[mef-global:id = current()]/mef-global:" +\r
-                                    "cos-dscp) or " +\r
-                                    "((/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:cos/mef-global:" +\r
-                                    "cos-profile" +\r
-                                    "[mef-global:id = current()]/mef-global:" +\r
-                                    "cos-dscp) and " +\r
-                                    "(../color-id = 'dscp'))" {\r
-                    error-message "When the Class of Service " +\r
-                                        "Identifier is based on DSCP for a " +\r
-                                        "given EVC at a given UNI, the Color " +\r
-                                        "Identifier must be based DSCP.";\r
-                    description\r
-                                        "When the Class of Service Identifier is based " +\r
-                                        "on DSCP for a given EVC at a given UNI, the " +\r
-                                        "Color Identifier must be based DSCP.";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Ingress Data Service Frame " +\r
-                                    "CoS Profile.";\r
-                  reference "[MEF10.3] Section 8.8, Section 10.2. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf l2cp-svc-frm-cos {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:" +\r
-                                        "profiles/mef-global:l2cp-cos/mef-global:" +\r
-                                        "l2cp-profile/mef-global:id";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Ingress Layer 2 Control Protocol " +\r
-                                    "Processing.";\r
-                  reference "[MEF10.3] Section 8.8, Section 10.2. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf soam-svc-frm-cos {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:profiles/" +\r
-                                        "mef-global:cos/mef-global:cos-profile/" +\r
-                                        "mef-global:id";\r
-                  }\r
-                  must "(not(.) and not(../data-svc-frm-cos)) or " +\r
-                                    "(. = ../data-svc-frm-cos)" {\r
-                    error-message "For a given EVC at a given UNI, " +\r
-                                        "the basis for the Class of Service " +\r
-                                        "Identifier for ingress SOAM Service " +\r
-                                        "Frames must be the same as that for " +\r
-                                        "ingress Data Service Frames.";\r
-                    description\r
-                                        "For a given EVC at a given UNI, the basis " +\r
-                                        "for the Class of Service Identifier for " +\r
-                                        "ingress SOAM Service Frames must be the " +\r
-                                        "same as that for ingress Data Service Frames.";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Ingress SOAM Service Frames.";\r
-                  reference "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf data-svc-frm-eec {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:profiles/" +\r
-                                        "mef-global:eec/mef-global:eec-profile/" +\r
-                                        "mef-global:id";\r
-                  }\r
-                  must "not(/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:eec/mef-global:" +\r
-                                    "eec-profile" +\r
-                                    "[mef-global:id = current()]" +\r
-                                    "/mef-global:eec-pcp) or " +\r
-                                    "((/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:eec/mef-global:" +\r
-                                    "eec-profile" +\r
-                                    "[mef-global:id = current()]" +\r
-                                    "/mef-global:eec-pcp) and " +\r
-                                    "((../color-id = 'pcp') or " +\r
-                                    "(../color-id = 'dei')) )" {\r
-                    error-message "When the Egress Equivalence " +\r
-                                        "Class Identifier is based on PCP " +\r
-                                        "for a given EVC at a given UNI, " +\r
-                                        "the Color Identifier must be based " +\r
-                                        "on either DEI or PCP.";\r
-                    description\r
-                                        "When the Egress Equivalence Class Identifier " +\r
-                                        "is based on PCP for a given EVC at a " +\r
-                                        "given UNI, the Color Identifier must " +\r
-                                        "be based on either DEI or PCP.";\r
-                  }\r
-                  must "not(/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:eec/mef-global:" +\r
-                                    "eec-profile" +\r
-                                    "[mef-global:id = current()]" +\r
-                                    "/mef-global:eec-dscp) or " +\r
-                                    "((/mef-global:mef-global/mef-global:" +\r
-                                    "profiles/mef-global:eec/mef-global:" +\r
-                                    "eec-profile" +\r
-                                    "[mef-global:id = current()]" +\r
-                                    "/mef-global:eec-dscp) and " +\r
-                                    "(../color-id = 'dscp'))" {\r
-                    error-message "When the Egress Equivalence " +\r
-                                        "Class Identifier is based on DSCP for " +\r
-                                        "a given EVC at a given UNI, the Color " +\r
-                                        "Identifier must be based DSCP.";\r
-                    description\r
-                                        "When the Egress Equivalence Class Identifier " +\r
-                                        "is based on DSCP for a given EVC at a given " +\r
-                                        "UNI, the Color Identifier must be based DSCP.";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Egress Data Service Frame Processing.";\r
-                  reference "[MEF10.3] Section 10.4. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf l2cp-svc-frm-eec {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:profiles/" +\r
-                                        "mef-global:l2cp-eec/mef-global:" +\r
-                                        "l2cp-profile/mef-global:id";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Egress Layer 2 Control Protocol " +\r
-                                    "Processing.";\r
-                  reference "[MEF10.3] Section 10.4. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf soam-svc-frm-eec {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:" +\r
-                                        "profiles/mef-global:eec/mef-global:" +\r
-                                        "eec-profile/mef-global:id";\r
-                  }\r
-                  must "(not(.) and not(../data-svc-frm-eec)) or " +\r
-                                    "(. = ../data-svc-frm-eec)" {\r
-                    error-message "For a given EVC at a given UNI, " +\r
-                                        "the basis for the Egress Equivalence " +\r
-                                        "Class Identifier for egress SOAM " +\r
-                                        "Service Frames must be the same as " +\r
-                                        "that for egress Data Service Frames.";\r
-                    description\r
-                                        "For a given EVC at a given UNI, the basis " +\r
-                                        "for the Egress Equivalence Class Identifier " +\r
-                                        "for egress SOAM Service Frames must be " +\r
-                                        "the same as that for egress Data " +\r
-                                        "Service Frames.";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Egress SOAM Service Frames.";\r
-                  reference "[MEF10.3] Section 10.4. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf ingress-bw-profile-per-evc {\r
-                  type leafref {\r
-                    path "/mef-interfaces:mef-interfaces/" +\r
-                                        "mef-interfaces:unis/" +\r
-                                        "mef-interfaces:uni" +\r
-                                        "[mef-interfaces:uni-id = " +\r
-                                        "current()/../uni-id]" +\r
-                                        "/mef-interfaces:ingress-envelopes/" +\r
-                                        "mef-interfaces:envelope/" +\r
-                                        "mef-interfaces:env-id";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Ingress Bandwidth Profile " +\r
-                                    "Envelope Per EVC. If this parameter is " +\r
-                                    "not configured (ie. 'No') this setting " +\r
-                                    "is configured else at the UNI Level.";\r
-                  reference "[MEF10.3] Section 10.5. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf egress-bw-profile-per-evc {\r
-                  type leafref {\r
-                    path "/mef-interfaces:mef-interfaces/" +\r
-                                        "mef-interfaces:unis/" +\r
-                                        "mef-interfaces:uni" +\r
-                                        "[mef-interfaces:uni-id = " +\r
-                                        "current()/../uni-id]" +\r
-                                        "/mef-interfaces:egress-envelopes/" +\r
-                                        "mef-interfaces:envelope/mef-interfaces:" +\r
-                                        "env-id";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Egress Bandwidth Profile Envelope " +\r
-                                    "Per EVC. If this parameter is not configured " +\r
-                                    "(ie. 'No') this setting is configured else at " +\r
-                                    "the UNI Level.";\r
-                  reference "[MEF10.3] Section 10.7. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf src-mac-addr-limit-enabled {\r
-                  type boolean;\r
-                  default "false";\r
-                  description\r
-                                    "EVC Per UNI: Source MAC Address Limit " +\r
-                                    "Enable / Disable. If Enabled, the values " +\r
-                                    "for the Source MAC Address Limit and Source " +\r
-                                    "MAC Address Interval must be set.";\r
-                  reference "[MEF10.3] Section 10.9. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf src-mac-addr-limit {\r
-                  type uint32 {\r
-                    range "1..max";\r
-                  }\r
-                  description\r
-                                    "EVC Per UNI: Source MAC Address Limit. " +\r
-                                    "This value is used when the Source MAC Address " +\r
-                                    "Limit Enabled is true.";\r
-                  reference "[MEF10.3] Section 10.9.";\r
-                }\r
-                leaf src-mac-addr-limit-interval {\r
-                  type yang:timeticks;\r
-                  default "0";\r
-                  description\r
-                                    "EVC Per UNI: Source MAC Address Limit " +\r
-                                    "Interval. This value is used when the " +\r
-                                    "Source MAC Address Limit Enabled is true.";\r
-                  reference "[MEF10.3] Section 10.9.";\r
-                }\r
-                leaf test-meg-enabled {\r
-                  type boolean;\r
-                  default "false";\r
-                  description\r
-                                    "EVC Per UNI: Test MEG Enabled / Disabled.";\r
-                  reference "[MEF10.3] Section 10.10. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf test-meg {\r
-                  type mef-types:identifier45;\r
-                  description\r
-                                    "EVC Per UNI: Test MEG Identifier.";\r
-                  reference "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf subscriber-meg-mip-enabled {\r
-                  type boolean;\r
-                  default "false";\r
-                  description\r
-                                    "EVC Per UNI: Subscriber MEG MIP " +\r
-                                    "Enabled / Disabled.";\r
-                  reference "[MEF10.3] Section 10.11. " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf subscriber-meg-mip {\r
-                  type mef-types:identifier45;\r
-                  description\r
-                                    "EVC Per UNI: Subscriber MEG MIP Identifier.";\r
-                  reference "[MEF7.3] Section 12.1.2.";\r
-                }\r
-              }\r
-            }\r
-            container status {\r
-              description\r
-                            "This status group is related to the MEF 7.3 Virtual " +\r
-                            "Connection";\r
-              leaf oper-state-enabled {\r
-                type boolean;\r
-                default "false";\r
-                config false;\r
-                description\r
-                                "EVC Operational Status of the Virtual Connection " +\r
-                                "as Enabled/Disabled.";\r
-                reference "[MEF7.3] Section 11.1.1.";\r
-              }\r
-              leaf available-status {\r
-                type mef-types:virt-cx-availability-type;\r
-                default "not-installed";\r
-                config false;\r
-                description\r
-                                "EVC Availability Status of the Virtual Connection.";\r
-                reference "[MEF7.3] Section 11.1.1.";\r
-              }\r
-            }\r
-            container sls-inclusions-by-cos {\r
-              description\r
-                            "SLS Inclusions by CoS: For this EVC, the following " +\r
-                            "CoS Names/Labels are applicable.";\r
-              list sls-inclusion-by-cos {\r
-                key "cos-name";\r
-                description\r
-                                "CoS Name.";\r
-                leaf cos-name {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:profiles/" +\r
-                                        "mef-global:cos-names/mef-global:" +\r
-                                        "cos-name/mef-global:name";\r
-                  }\r
-                  description\r
-                                    "EVC: This attribute identifies the name of " +\r
-                                    "a class of service (CoS) instance to be used " +\r
-                                    "for EVC Performance.";\r
-                }\r
-              }\r
-            }\r
-            container sls-uni-inclusions {\r
-              presence "EVC: Defines the EVC Flow Points (UNI) Pairs " +\r
-                            "that must conform to the EVC's SLS Performance " +\r
-                            "Metrics.";\r
-              description\r
-                            "SLS UNI Inclusions List. The following pairs of UNI " +\r
-                            "Interconnections are to required to meet the " +\r
-                            "SLS Performance Objectives. Configing both SLS " +\r
-                            "UNI Inclusions and SLS UNI Exclusions is not " +\r
-                            "permitted.";\r
-              list sls-uni-inclusion-set {\r
-                must "uni-id1 != uni-id2" {\r
-                  error-message "The two UNI IDs for a given " +\r
-                                    "inclusion cannot be the same.";\r
-                  description\r
-                                    "The two UNI IDs for a given inclusion " +\r
-                                    "cannot be the same.";\r
-                }\r
-                must "(../../evc-type != 'rooted-multipoint') or " +\r
-                                "((../../evc-type = 'rooted-multipoint') " +\r
-                                "and " +\r
-                                "not((../../unis/uni[uni-id = " +\r
-                                "current()/uni-id1]/role = 'leaf') and " +\r
-                                "(../../unis/uni[uni-id = current()/uni-id2]" +\r
-                                "/role = 'leaf')))" {\r
-                  error-message "If EVC Type is Rooted-Multipoint, " +\r
-                                    "sls-uni-inclusion UNI Pairs cannot both " +\r
-                                    "be role 'leaf'.";\r
-                  description\r
-                                    "If EVC Type is Rooted-Multipoint, " +\r
-                                    "sls-uni-inclusion UNI Pairs cannot " +\r
-                                    "both be role 'leaf'.";\r
-                }\r
-                key "pm-type pm-id uni-id1 uni-id2";\r
-                description\r
-                                "EVC: Defines the EVC Flow Points (UNI) Pairs that " +\r
-                                "must conform to the EVC's SLS Performance " +\r
-                                "Metrics. Use of this list indicates that a " +\r
-                                "complete set of UNI Pairs has been specified " +\r
-                                "for the Performance Metrics defined in the " +\r
-                                "selected SLS.";\r
-                leaf pm-type {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:slss/" +\r
-                                        "mef-global:sls" +\r
-                                        "[mef-global:sls-id = current()/../../../" +\r
-                                        "evc-performance-sls]" +\r
-                                        "/mef-global:perf-objs/mef-global:" +\r
-                                        "perf-obj/mef-global:pm-type";\r
-                  }\r
-                  description\r
-                                    "EVC: Performance Metric.";\r
-                  reference "[MEF10.3] Section 8.8.";\r
-                }\r
-                leaf pm-id {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:slss/" +\r
-                                        "mef-global:sls" +\r
-                                        "[mef-global:sls-id = current()/../../../" +\r
-                                        "evc-performance-sls]" +\r
-                                        "/mef-global:perf-objs/mef-global:perf-obj" +\r
-                                        "[mef-global:pm-type = current()/../" +\r
-                                        "pm-type]" +\r
-                                        "/mef-global:pm-id";\r
-                  }\r
-                  description\r
-                                    "EVC: This is a friendly name for specific " +\r
-                                    "performance profile.";\r
-                }\r
-                leaf uni-id1 {\r
-                  type leafref {\r
-                    path "../../../unis/uni/uni-id";\r
-                  }\r
-                  description\r
-                                    "EVC: The UNI ID paired with the EVC ID in the " +\r
-                                    "containing list.";\r
-                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf uni-id2 {\r
-                  type leafref {\r
-                    path "../../../unis/uni/uni-id";\r
-                  }\r
-                  description\r
-                                    "EVC: The UNI ID paired with the EVC ID in the " +\r
-                                    "containing list.";\r
-                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-              }\r
-            }\r
-            container sls-uni-exclusions {\r
-              presence "Not all EVC Flow Points (UNI) must conform " +\r
-                            "to the EVC SLS Performance Metrics.";\r
-              description\r
-                            "EVC: Not all EVC Flow Points (UNI) must conform to " +\r
-                            "the EVC SLS Performance Metrics. Use of this " +\r
-                            "list indicates that all UNI Pairs EXCEPT for " +\r
-                            "the ones indicated (per Performance Metric) must " +\r
-                            "conform to the SLS.";\r
-              list sls-uni-exclusion-set {\r
-                must "uni-id1 != uni-id2" {\r
-                  error-message "The two UNI IDs for a given " +\r
-                                    "exclusion cannot be the same.";\r
-                  description\r
-                                    "The two UNI IDs for a given exclusion cannot " +\r
-                                    "be the same as these pairs are invalid as " +\r
-                                    "defined in MEF 10.3.";\r
-                }\r
-                key "pm-type pm-id uni-id1 uni-id2";\r
-                description\r
-                                "SLS UNI Exclusions List. The following pairs " +\r
-                                "of UNI Interconnections are not required " +\r
-                                "meet the SLS Performance Objectives. " +\r
-                                "Configing both SLS UNI Inclusions and SLS " +\r
-                                "UNI Exclusions is not permitted.";\r
-                leaf pm-type {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:" +\r
-                                        "slss/mef-global:sls" +\r
-                                        "[mef-global:sls-id = current()/../../../" +\r
-                                        "evc-performance-sls]" +\r
-                                        "/mef-global:perf-objs/mef-global:" +\r
-                                        "perf-obj/mef-global:pm-type";\r
-                  }\r
-                  description\r
-                                    "EVC: Performance Metric.";\r
-                  reference "[MEF10.3] Section 8.8.";\r
-                }\r
-                leaf pm-id {\r
-                  type leafref {\r
-                    path "/mef-global:mef-global/mef-global:slss/" +\r
-                                        "mef-global:sls" +\r
-                                        "[mef-global:sls-id = current()/../../../" +\r
-                                        "evc-performance-sls]" +\r
-                                        "/mef-global:perf-objs/mef-global:perf-obj" +\r
-                                        "[mef-global:pm-type = current()/../" +\r
-                                        "pm-type]" +\r
-                                        "/mef-global:pm-id";\r
-                  }\r
-                  description\r
-                                    "EVC: This is a friendly name for specific " +\r
-                                    "performance profile.";\r
-                }\r
-                leaf uni-id1 {\r
-                  type leafref {\r
-                    path "../../../unis/uni/uni-id";\r
-                  }\r
-                  description\r
-                                    "EVC: The UNI ID paired with the EVC ID in the " +\r
-                                    "containing list.";\r
-                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-                leaf uni-id2 {\r
-                  type leafref {\r
-                    path "../../../unis/uni/uni-id";\r
-                  }\r
-                  description\r
-                                    "EVC: The UNI ID paired with the EVC ID in the " +\r
-                                    "containing list.";\r
-                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +\r
-                                    "[MEF7.3] Section 12.1.2.";\r
-                }\r
-              }\r
-            }\r
-            leaf evc-id {\r
-              type mef-types:evc-id-type;\r
-              mandatory true;\r
-              description\r
-                            "The EVC ID must be unique across all EVCs in the CEN." +\r
-                            " The EVC ID must be non-NULL.";\r
-              reference "[MEF10.3] Section 8.2 [R7]. " +\r
-                            "[MEF7.3] Section 11.1.1, Section 12.2.2.";\r
-            }\r
-            leaf evc-status {\r
-              type mef-types:evc-status-type;\r
-              config false;\r
-              description\r
-                            "EVC Operational Status.";\r
-              reference "[MEF16] Section 5.3.";\r
-            }\r
-            leaf evc-type {\r
-              type mef-types:evc-type;\r
-              must "(. != 'point-to-point') or " +\r
-                            "((. = 'point-to-point') and " +\r
-                            "(count(../unis/uni[role = 'leaf']) = 0))" {\r
-                error-message "If EVC Type is Point-to-Point, all " +\r
-                                "UNI Roles must be root.";\r
-                description\r
-                                "If EVC Type is Point-to-Point, all UNI Roles must " +\r
-                                "be root.";\r
-              }\r
-              must "(. != 'multipoint-to-multipoint') or " +\r
-                            "((. = 'multipoint-to-multipoint') and " +\r
-                            "(count(../unis/uni[role = 'leaf']) = 0))" {\r
-                error-message "If EVC Type is " +\r
-                                "Multipoint-to-Multipoint, all UNI Roles " +\r
-                                "must be root.";\r
-                description\r
-                                "If EVC Type is Multipoint-to-Multipoint, all UNI " +\r
-                                "Roles must be root.";\r
-              }\r
-              must "(. != 'rooted-multipoint') or " +\r
-                            "((. = 'rooted-multipoint') and " +\r
-                            "(count(../unis/uni[role = 'root']) > 0) )" {\r
-                error-message "If EVC Type is Rooted-Multipoint, one " +\r
-                                "or more UNI Roles must be root.";\r
-                description\r
-                                "If EVC Type is Rooted-Multipoint, one or more " +\r
-                                "UNI Roles must be root.";\r
-              }\r
-              must "(. != 'point-to-point') or " +\r
-                            "((. = 'point-to-point') and " +\r
-                            "(count(../unis/uni) = 2))" {\r
-                error-message "If EVC Type is Point-to-Point, there " +\r
-                                "must be exactly 2 UNI configured for the EVC.";\r
-                description\r
-                                "If EVC Type is Point-to-Point, there must be " +\r
-                                "exactly 2 UNI configured for the EVC.";\r
-              }\r
-              must "(. != 'multipoint-to-multipoint') or " +\r
-                            "((. = 'multipoint-to-multipoint') and " +\r
-                            "(count(../unis/uni) > 1) and " +\r
-                            "(count(../unis/uni) <= ../max-uni-count))" {\r
-                error-message "If EVC Type is " +\r
-                                "Multipoint-to-Multipoint, " +\r
-                                "there must be 2 or more UNI configured " +\r
-                                "for the EVC.";\r
-                description\r
-                                "If EVC Type is Multipoint-to-Multipoint, " +\r
-                                "there must be 2 or more UNI configured for " +\r
-                                "the EVC.";\r
-              }\r
-              must "(. != 'rooted-multipoint') or " +\r
-                            "((. = 'rooted-multipoint') and " +\r
-                            "(count(../unis/uni) > 1) and " +\r
-                            "(count(../unis/uni) <= ../max-uni-count))" {\r
-                error-message "If EVC Type is Rooted-Multipoint, " +\r
-                                "there must be 2 or more UNI configured for the EVC.";\r
-                description\r
-                                "If EVC Type is Rooted-Multipoint, there must " +\r
-                                "be 2 or more UNI configured for the EVC.";\r
-              }\r
-              must "(. != 'point-to-point') or " +\r
-                            "((. = 'point-to-point') and " +\r
-                            "(../max-uni-count = 2))" {\r
-                error-message "If EVC Type is Point-to-Point, " +\r
-                                "the value of max-uni-count must be 2.";\r
-                description\r
-                                "If EVC Type is Point-to-Point, the value of " +\r
-                                "max-uni-count must be 2.";\r
-              }\r
-              must "(. != 'multipoint-to-multipoint') or " +\r
-                            "((. = 'multipoint-to-multipoint') and " +\r
-                            "(../max-uni-count > 2))" {\r
-                error-message "If EVC Type is " +\r
-                                "Multipoint-to-Multipoint, the value of " +\r
-                                "max-uni-count must be at least 3.";\r
-                description\r
-                                "If EVC Type is Multipoint-to-Multipoint, the " +\r
-                                "value of max-uni-count must be at least 3.";\r
-              }\r
-              must "(. != 'rooted-multipoint') or " +\r
-                            "((. = 'rooted-multipoint') and " +\r
-                            "(../max-uni-count > 2))" {\r
-                error-message "If EVC Type is Rooted-Multipoint, " +\r
-                                "the value of max-uni-count must be at " +\r
-                                "least 3.";\r
-                description\r
-                                "If EVC Type is Rooted-Multipoint, the value " +\r
-                                "of max-uni-count must be at least 3.";\r
-              }\r
-              // mandatory true;\r
-              description\r
-                            "This EVC attribute describes the EVC as either " +\r
-                            "Multipoint-To-Multipoint, Point-To-Point, or " +\r
-                            "Rooted-Multipoint.";\r
-              reference "[MEF10.3] Section 8.1, [R4], [R5], " +\r
-                            "[R10], [R11], [R12], [R13] and [R14]. " +\r
-                            "[MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf admin-state-enabled {\r
-              type boolean;\r
-              default "true";\r
-              description\r
-                            "EVC: Locked/Unlocked is inconsistent with " +\r
-                            "Oper Status and will be confusing.";\r
-              reference "[MEF15]. [MEF7.3] Section 11.1.1.";\r
-            }\r
-            leaf elastic-enabled {\r
-              type boolean;\r
-              default "true";\r
-              description\r
-                            "EVC: Elastic Enabled/Disabled.";\r
-              reference "[MEF7.3] Section 11.1.1.";\r
-            }\r
-            leaf elastic-service {\r
-              type mef-types:identifier45;\r
-              description\r
-                            "EVC: Related to CE4Cloud Information Model.";\r
-              reference "[MEF7.3] Section 11.1.1.";\r
-            }\r
-            leaf max-uni-count {\r
-              type uint32 {\r
-                range "2..max";\r
-              }\r
-              must "(. > 2) or ((. = 2) and " +\r
-                            "(../evc-type = 'point-to-point'))" {\r
-                error-message "If EVC Type is Point-to-Point, the " +\r
-                                "max-uni-count value must be 2.";\r
-                description\r
-                                "If EVC Type is Point-to-Point, the max-uni-count " +\r
-                                "value must be 2.";\r
-              }\r
-              must "(. = 2) or ((. > 2) and " +\r
-                            "((../evc-type = 'multipoint-to-multipoint') or " +\r
-                            "(../evc-type = 'rooted-multipoint')))" {\r
-                error-message "If EVC Type is " +\r
-                                "Multipoint-to-Multipoint or " +\r
-                                "Rooted-Multipoint, the max-uni-count value " +\r
-                                "must be at least 3.";\r
-                description\r
-                                "If EVC Type is Multipoint-to-Multipoint or " +\r
-                                "Rooted-Multipoint, the max-uni-count value " +\r
-                                "must be at least 3.";\r
-              }\r
-              default "2";\r
-              description\r
-                            "EVC:The Maximum Number of UNIs this EVC can be " +\r
-                            "configured for (Default 2).If EVC Type is " +\r
-                            "Multipoint-to-Multipoint or Rooted-Multipoint, " +\r
-                            "the max-uni-count value must be at least 3. " +\r
-                            "This value must be 2 for point-to-point mode.";\r
-              reference "[MEF10.3] [R14]. [MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf preserved-vlan {\r
-              type uint32;\r
-            }\r
-            leaf preserve-ce-vlan-id {\r
-              type boolean;\r
-              default "false";\r
-              description\r
-                            "EVC:An EVC with more than one CE-VLAN ID mapping " +\r
-                            "to it must have the same list of CE-VLAN IDs " +\r
-                            "mapping to the EVC at each UNI in the EVC.";\r
-              reference "[MEF10.3] Section 8.6.1, [R24] [R25], " +\r
-                            "Section 9.10.2, Section 9.12, [R81], Figure 20. " +\r
-                            "[MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf cos-preserve-ce-vlan-id {\r
-              type boolean;\r
-              default "false";\r
-              description\r
-                            "EVC: Preserve CE-VLAN ID for CoS.";\r
-              reference "[MEF10.3] Section 8.6.2, [R26]. " +\r
-                            "[MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf evc-performance-sls {\r
-              type leafref {\r
-                path "/mef-global:mef-global/mef-global:slss/" +\r
-                                "mef-global:sls/mef-global:sls-id";\r
-              }\r
-              description\r
-                            "EVC: EVC-specific performance objectives and " +\r
-                            "parameters. Note that an SLS can also specify " +\r
-                            "performance objectives spanning more than one EVC. " +\r
-                            "By default, all the UNI associated with the EVC " +\r
-                            "have this SLS applied for them.";\r
-              reference "[MEF10.3] Section 8.8, Section 10. " +\r
-                            "[MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf unicast-svc-frm-delivery {\r
-              type mef-types:data-svc-frame-delivery-type;\r
-              default "unconditional";\r
-              description\r
-                            "EVC: Unicast Data Service Frame Delivery Mode " +\r
-                            "(unconditional[default], conditional, or discard).";\r
-              reference "[MEF10.3] Section 8.5.2,[R16], [R17], " +\r
-                            "Section 8.8, Section 11. [MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf multicast-svc-frm-delivery {\r
-              type mef-types:data-svc-frame-delivery-type;\r
-              default "unconditional";\r
-              description\r
-                            "EVC: Multicast Data Service Frame Delivery Mode " +\r
-                            "(unconditional[default], conditional, or discard).";\r
-              reference "[MEF10.3] Section 8.5.2, [R16], [R18], " +\r
-                            "Section 8.8, Section 11. [MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf broadcast-svc-frm-delivery {\r
-              type mef-types:data-svc-frame-delivery-type;\r
-              default "unconditional";\r
-              description\r
-                            "EVC: Broadcast Data Service Frame Delivery Mode " +\r
-                            "(unconditional[default], conditional, or discard).";\r
-              reference "[MEF10.3] Section 8.5.2, [R16], [R19], " +\r
-                            "Section 8.8, Section 11. [MEF7.3] Section 12.2.2.";\r
-            }\r
-            leaf evc-meg-id {\r
-              type mef-types:identifier45;\r
-              description\r
-                            "EVC: Identifies the Maintenance Entity Group (MEG) " +\r
-                            "for this EVC.";\r
-              reference "[MEF7.3] Section 12.2.2. MEF 35.1.";\r
-            }\r
-            leaf max-svc-frame-size {\r
-              type mef-types:max-svc-frame-size-type;\r
-              default "1600";\r
-              description\r
-                            "EVC: This attribute describes the maximum service " +\r
-                            "frame size for the EVC.";\r
-              reference "[MEF10.3] Section 8.9, Section 9.7, [R71], " +\r
-                            "[MEF6.2] Section 8.2.2 and MEF 22.1: [D2]. " +\r
-                            "[MEF7.3] Section 12.2.2.";\r
-            }\r
-          }\r
-        }\r
-      }\r
-      leaf svc-id {\r
-        type mef-types:retail-svc-id-type;\r
-        description\r
-                "The MEF Service ID is a simple key used to " +\r
-                "distinguish MEF Service Configuration Groups.";\r
-        reference "[MEF10.3] Section 7.";\r
-      }\r
-      leaf sp-id {\r
-        when "/mef-global:mef-global/mef-global:svc-providers" {\r
-          description\r
-                    "Only configure when the Global Service Providers " +\r
-                    "list has been populated.";\r
-        }\r
-        type leafref {\r
-          path "/mef-global:mef-global/mef-global:svc-providers/" +\r
-                    "mef-global:svc-provider/mef-global:sp-id";\r
-        }\r
-        description\r
-                "The MEF Service Provider ID must be globally unique " +\r
-                "as all CENs and Subscribers must be supported by a " +\r
-                "specific Service Provider(SP). A SP can support " +\r
-                "multiple CENs.";\r
-        reference "[MEF10.3] Section 7.";\r
-      }\r
-      leaf svc-type {\r
-        type mef-types:mef-service-type;\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "svc-mux-enabled = 'true']) = 0))" {\r
-          error-message "For EPL, Service Multiplexing must be " +\r
-                    "disabled for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EPL, Service Multiplexing must be disabled for " +\r
-                    "all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "bundling-enabled = 'true']) = 0))" {\r
-          error-message "For EPL, Bundling must be disabled for " +\r
-                    "all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EPL, Bundling must be disabled for all UNIs in " +\r
-                    "the EVC UNI List.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/" +\r
-                "mef-services:uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "all-to-one-bundling-enabled = 'false']) = 0))" {\r
-          error-message "For EPL, All-to-One Bundling must be " +\r
-                    "enabled for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EPL, All-to-One Bundling must be enabled for " +\r
-                    "all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "max-evc-count != 1]) = 0))" {\r
-          error-message "For EPL, Max EVC Count must be 1 for " +\r
-                    "all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EPL, Max EVC Count must be 1 for all UNIs " +\r
-                    "in the EVC UNI List.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(count(../evc/unis/uni/egress-bwp-flows-per-eec/" +\r
-                "bwp-flow-per-eec) = 0))" {\r
-          error-message "For EPL, Egress Bandwidth Profile per " +\r
-                    "Egress Equivalence Class cannot be set for " +\r
-                    "all UNIs in the EVC per UNI List.";\r
-          description\r
-                    "For EPL, Egress Bandwidth Profile per Egress " +\r
-                    "Equivalence Class cannot be set for all UNIs in the " +\r
-                    "EVC per UNI List.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(count(../evc/unis/uni" +\r
-                "[src-mac-addr-limit-enabled = 'true']) = 0) )" {\r
-          error-message "For EPL, Source MAC Address Limit must " +\r
-                    "be disabled.";\r
-          description\r
-                    "For EPL, Source MAC Address Limit must be disabled.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(../evc/evc-type = 'point-to-point'))" {\r
-          error-message "For EPL, EVC Type must be Point-to-Point.";\r
-          description\r
-                    "For EPL, EVC Type must be Point-to-Point.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(../evc/unicast-svc-frm-delivery = " +\r
-                "'unconditional'))" {\r
-          error-message "For EPL, unicast-svc-frm-delivery " +\r
-                    "must be unconditional.";\r
-          description\r
-                    "For EPL, unicast-svc-frm-delivery must be " +\r
-                    "unconditional.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(../evc/multicast-svc-frm-delivery = " +\r
-                "'unconditional'))" {\r
-          error-message "For EPL, multicast-svc-frm-delivery " +\r
-                    "must be unconditional.";\r
-          description\r
-                    "For EPL, multicast-svc-frm-delivery must be " +\r
-                    "unconditional.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(../evc/broadcast-svc-frm-delivery = " +\r
-                "'unconditional'))" {\r
-          error-message "For EPL, broadcast-svc-frm-delivery " +\r
-                    "must be unconditional.";\r
-          description\r
-                    "For EPL, broadcast-svc-frm-delivery must be " +\r
-                    "unconditional.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(../evc/preserve-ce-vlan-id = 'true'))" {\r
-          error-message "For EPL, CE-VLAN ID Preservation " +\r
-                    "must be enabled.";\r
-          description\r
-                    "For EPL, CE-VLAN ID Preservation must be enabled.";\r
-        }\r
-        must "(. != 'epl') or ((. = 'epl') and " +\r
-                "(../evc/cos-preserve-ce-vlan-id = 'true'))" {\r
-          error-message "For EPL, CE-VLAN ID CoS Preservation " +\r
-                    "must be enabled.";\r
-          description\r
-                    "For EPL, CE-VLAN ID CoS Preservation must be enabled.";\r
-        }\r
-        must "(. != 'evpl') or ((. = 'evpl') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "all-to-one-bundling-enabled = 'true']) = 0))" {\r
-          error-message "For EVPL, All-to-One Bundling must be " +\r
-                    "disabled for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EVPL, All-to-One Bundling must be disabled for " +\r
-                    "all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'evpl') or ((. = 'evpl') and " +\r
-                "((../evc/unicast-svc-frm-delivery != " +\r
-                "'unconditional') or " +\r
-                "(../evc/multicast-svc-frm-delivery != " +\r
-                "'unconditional') or " +\r
-                "(../evc/broadcast-svc-frm-delivery != " +\r
-                "'unconditional') or " +\r
-                "count(../evc/unis/uni" +\r
-                "[src-mac-addr-limit-enabled = 'true']) = 0))" {\r
-          error-message "For EVPL, Source MAC Address Limit must " +\r
-                    "be disabled for all UNIs in the EVC per " +\r
-                    "UNI List if all 3 -svc-frm-delivery values " +\r
-                    "are unconditional.";\r
-          description\r
-                    "For EVPL, Source MAC Address Limit must be disabled " +\r
-                    "for all UNIs in the EVC per UNI List if all " +\r
-                    "3 -svc-frm-delivery values are unconditional.";\r
-        }\r
-        must "(. != 'evpl') or ((. = 'evpl') and " +\r
-                "(../evc/evc-type = 'point-to-point'))" {\r
-          error-message "For EVPL, EVC Type must be Point-to-Point.";\r
-          description\r
-                    "For EVPL, EVC Type must be Point-to-Point.";\r
-        }\r
-        must "(. != 'eplan') or ((. = 'eplan') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "svc-mux-enabled = 'true']) = 0))" {\r
-          error-message "For EP-LAN, Service Multiplexing must " +\r
-                    "be disabled for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EP-LAN, Service Multiplexing must be disabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eplan') or ((. = 'eplan') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "bundling-enabled = 'true']) = 0))" {\r
-          error-message "For EP-LAN, Bundling must be disabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EP-LAN, Bundling must be disabled for all UNIs " +\r
-                    "in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eplan') or ((. = 'eplan') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/" +\r
-                "mef-services:uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "all-to-one-bundling-enabled = 'false']) = 0))" {\r
-          error-message "For EP-LAN, All-to-One Bundling " +\r
-                    "must be enabled for all UNIs in the " +\r
-                    "EVC UNI List.";\r
-          description\r
-                    "For EP-LAN, All-to-One Bundling must be enabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eplan') or ((. = 'eplan') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/" +\r
-                "mef-services:uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "max-evc-count != 1]) = 0))" {\r
-          error-message "For EP-LAN, Max EVC Count must be 1 " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EP-LAN, Max EVC Count must be 1 for all UNIs in " +\r
-                    "the EVC UNI List.";\r
-        }\r
-        must "(. != 'eplan') or ((. = 'eplan') and " +\r
-                "(../evc/evc-type = 'multipoint-to-multipoint'))" {\r
-          error-message "For EP-LAN, EVC Type must be " +\r
-                    "Multipoint-to-Multipoint.";\r
-          description\r
-                    "For EP-LAN, EVC Type must be " +\r
-                    "Multipoint-to-Multipoint.";\r
-        }\r
-        must "(. != 'eplan') or ((. = 'eplan') and " +\r
-                "(../evc/preserve-ce-vlan-id = 'true'))" {\r
-          error-message "For EP-LAN, CE-VLAN ID Preservation " +\r
-                    "must be enabled.";\r
-          description\r
-                    "For EP-LAN, CE-VLAN ID Preservation must be enabled.";\r
-        }\r
-        must "(. != 'eplan') or ((. = 'eplan') and " +\r
-                "(../evc/cos-preserve-ce-vlan-id = 'true'))" {\r
-          error-message "For EP-LAN, CE-VLAN ID CoS Preservation " +\r
-                    "must be enabled.";\r
-          description\r
-                    "For EP-LAN, CE-VLAN ID CoS Preservation must be " +\r
-                    "enabled.";\r
-        }\r
-        must "(. != 'evplan') or ((. = 'evplan') and " +\r
-                "(../evc/evc-type = 'multipoint-to-multipoint'))" {\r
-          error-message "For EVP-LAN, EVC Type must be " +\r
-                    "Multipoint-to-Multipoint.";\r
-          description\r
-                    "For EVP-LAN, EVC Type must be " +\r
-                    "Multipoint-to-Multipoint.";\r
-        }\r
-        must "(. != 'evplan') or ((. = 'evplan') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "all-to-one-bundling-enabled = 'true']) = 0))" {\r
-          error-message "For EVP-LAN, All-to-One Bundling must " +\r
-                    "be disabled for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EVP-LAN, All-to-One Bundling must be disabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eptree') or ((. = 'eptree') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "svc-mux-enabled = 'true']) = 0))" {\r
-          error-message "For EP-TREE, Service Multiplexing " +\r
-                    "must be disabled for all UNIs in the " +\r
-                    "EVC UNI List.";\r
-          description\r
-                    "For EP-TREE, Service Multiplexing must be disabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eptree') or ((. = 'eptree') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "bundling-enabled = 'true']) = 0))" {\r
-          error-message "For EP-TREE, Bundling must be disabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EP-TREE, Bundling must be disabled for all UNIs " +\r
-                    "in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eptree') or ((. = 'eptree') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/" +\r
-                "mef-services:uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "all-to-one-bundling-enabled = 'false']) = 0))" {\r
-          error-message "For EP-TREE, All-to-One Bundling must " +\r
-                    "be enabled for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EP-TREE, All-to-One Bundling must be enabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eptree') or ((. = 'eptree') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/" +\r
-                "mef-services:uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "max-evc-count != 1]) = 0))" {\r
-          error-message "For EP-TREE, Max EVC Count must be 1 " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EP-TREE, Max EVC Count must be 1 for all UNIs " +\r
-                    "in the EVC UNI List.";\r
-        }\r
-        must "(. != 'eptree') or ((. = 'eptree') and " +\r
-                "(../evc/evc-type = 'rooted-multipoint'))" {\r
-          error-message "For EP-TREE, EVC Type must be " +\r
-                    "Rooted-Multipoint.";\r
-          description\r
-                    "For EP-TREE, EVC Type must be Rooted-Multipoint.";\r
-        }\r
-        must "(. != 'eptree') or ((. = 'eptree') and " +\r
-                "(../evc/preserve-ce-vlan-id = 'true'))" {\r
-          error-message "For EP-TREE, CE-VLAN ID Preservation " +\r
-                    "must be enabled.";\r
-          description\r
-                    "For EP-TREE, CE-VLAN ID Preservation must be enabled.";\r
-        }\r
-        must "(. != 'eptree') or ((. = 'eptree') and " +\r
-                "(../evc/cos-preserve-ce-vlan-id = 'true'))" {\r
-          error-message "For EP-TREE, CE-VLAN ID " +\r
-                    "CoS Preservation must be enabled.";\r
-          description\r
-                    "For EP-TREE, CE-VLAN ID CoS Preservation must be " +\r
-                    "enabled.";\r
-        }\r
-        must "(. != 'evptree') or ((. = 'evptree') and " +\r
-                "(count(/mef-interfaces:mef-interfaces/" +\r
-                "mef-interfaces:unis/mef-interfaces:uni" +\r
-                "[mef-interfaces:uni-id = current()/../" +\r
-                "mef-services:evc/mef-services:unis/mef-services:" +\r
-                "uni/mef-services:uni-id]" +\r
-                "[mef-interfaces:uni-id/../mef-interfaces:" +\r
-                "all-to-one-bundling-enabled = 'true']) = 0))" {\r
-          error-message "For EVP-TREE, All-to-One Bundling " +\r
-                    "must be disabled for all UNIs in the EVC UNI List.";\r
-          description\r
-                    "For EVP-TREE, All-to-One Bundling must be disabled " +\r
-                    "for all UNIs in the EVC UNI List.";\r
-        }\r
-        must "(. != 'evptree') or ((. = 'evptree') and " +\r
-                "(../evc/evc-type = 'rooted-multipoint'))" {\r
-          error-message "For EVP-TREE, EVC Type must be " +\r
-                    "Rooted-Multipoint.";\r
-          description\r
-                    "For EVP-TREE, EVC Type must be Rooted-Multipoint.";\r
-        }\r
-        description\r
-                "The MEF Service Type.";\r
-      }\r
-      leaf user-label {\r
-        type mef-types:identifier45;\r
-        description\r
-                "This MEF user label is set by the user to a value " +\r
-                "that is easier to identify than the Service ID.";\r
-      }\r
-      leaf svc-entity {\r
-        type mef-types:service-entity-type;\r
-        default "evc";\r
-        description\r
-                "MEF Service Entity.";\r
-        reference "[MEF12.2] Table 3.";\r
-      }\r
-      leaf tenant-id {\r
-        type leafref {\r
-          path "/mef-global:mef-global/mef-global:tenants-instances/mef-global:tenant-list/mef-global:name";\r
-        }\r
-      }\r
-    }\r
-  }\r
-}\r
+module mef-services {
+  namespace "http://metroethernetforum.org/ns/yang/mef-services";
+  prefix mef-services;
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+  import mef-types { prefix mef-types; }
+  import mef-global { prefix mef-global; }
+  import mef-interfaces { prefix mef-interfaces; }
+  import yang-ext {prefix ext; revision-date "2013-07-09";}
+
+  organization "Metro Ethernet Forum";
+  contact
+    "Web URL: http://metroethernetforum.org/ E-mail: mibs@metroethernetforum.org
+    Postal: Metro Ethernet Forum 6033 W. Century Boulevard, Suite
+    1107 Los Angeles, CA 90045 U.S.A. Phone: +1 310-642-2800 Fax:
+    +1 310-642-2808";
+  description
+    "This module implements the Carrier Ethernet Services as defined
+    in MEF 10.3, MEF 6.2, and MEF 7.2. Reference Overview: A number
+    of base documents have been used to create the MEF Services YANG
+    Module. The following are the abbreviations for the baseline documents:
+    [RFC 6991] refers to IETF RFC 6991 'Common YANG Data Types', 2013-07-15
+    [RFC 6643] refers to IETF RFC 6643 'Translation of Structure of
+    Management Information Version 2 (SMIv2) MIB Modules to YANG Modules',
+    2011-11-25 [802.1AB] refers to 'Station and Media Access Control
+    Connectivity Discovery', IEEE 802.1AB-2009, September 2009 [802.1q]
+    refers to IEEE 802.1Q-2011 'IEEE Standard for Local and metropolitan
+    area networks --Media Access Control (MAC) Bridges and Virtual
+    Bridged Local Area Networks, August 2011 [802-2001] refers to
+    'IEEE Standard for Local and Metropolitan Area Networks: Overview
+    and Architecture', IEEE 802-2001, February 2002 [MEF10.3] refers
+    to MEF 10.3 'Ethernet Services Attributes Phase 3', October 2013
+    [MEF6.2] refers to MEF 6.2 'EVC Ethernet Services Defintions Phase
+    3', August 2014 [MEF40] refers to MEF 40 'UNI and EVC Definition
+    of Managed Objects', April 2013 [MEF45] refers to MEF 45 'Multi-CEN
+    L2CP', August 2014 [MEF7.2] refers to MEF 7.2 'Carrier Ethernet
+    Management Information Model', April 2013 [MEF7.3] refers to MEF
+    7.3 'Carrier Ethernet Management Information Model', Working Draft
+    #1 2015 [RFC 2737] refers to IETF RFC 2737 'Entity MIB (Version
+    2)', December 1999 [RFC 2863] refers to IETF RFC 2863 'The Interfaces
+    Group MIB', June 2000 [RFC 3419] refers to IETF RFC 3419 'Textual
+    Conventions for Transport Addresses', December 2002 [Y.1731] refers
+    to ITU-T Y.1731 'OAM functions and mechanisms for Ethernet based
+    networks', July 2011 [Q.840.1] refers to ITU-T Q.840.1 'Requirements
+    and analysis for NMS-EMS management interface of Ethernet over
+    Transport and Metro Ethernet Network(EoT/MEN)' March 2007";
+  revision 2015-05-26 {
+    description
+        "Formal Project Review Draft 1.";
+    reference "EVC Ethernet Services Definitions YANG Modules " +
+        "(MEF XX), TBD";
+  }
+
+  container mef-services {
+    description
+        "MEF Services";
+    list mef-service {
+      must "(not(/mef-global:mef-global/mef-global:svc-providers)" +
+            " and " +
+            "not(./sp-id)) or " +
+            "(/mef-global:mef-global/mef-global:svc-providers and " +
+            "./sp-id)" {
+        error-message "If the Service Providers list has been " +
+                "populated, a Service Provider ID must be " +
+                "configured for a Service.";
+        description
+                "A Service sees a single Service Provider. This must " +
+                "statement is effectively a 'mandatory true' when " +
+                "the Global Service Providers list is being used.";
+      }
+      key "svc-id";
+      unique "evc/evc-id";
+      unique "ipvc/ipvc-id";
+      description
+            "Metro Ethernet Forum's Ethernet Services.";
+      choice mef-service-choice {
+        case ipvc-choice {
+          container ipvc {
+            container unis {
+              list uni {
+                key "uni-id ip-uni-id";
+                leaf uni-id {
+                  type leafref {
+                    path "/mef-interfaces:mef-interfaces/" +
+                                        "mef-interfaces:unis/mef-interfaces:uni/" +
+                                        "mef-interfaces:uni-id";
+                  }
+                }
+                leaf ip-uni-id {
+                  type mef-types:identifier45;
+                }
+
+                container evc-uni-ce-vlans {
+                  description
+                                    "EVC Per UNI CE-VLAN IDs.";
+                  list evc-uni-ce-vlan {
+                    key "vid";
+                    description
+                                        "A list of the CE-VLAN IDs mapped to this UNI " +
+                                        "for this EVC.";
+                    reference "[MEF10.3] Section 8.6.1, [R24] " +
+                                        "[R25], Section 9.10.2, Section 9.12, " +
+                                        "[R76], [R81].";
+                    leaf vid {
+                      type leafref {
+                        path "/mef-interfaces:mef-interfaces/" +
+                                                "mef-interfaces:unis/" +
+                                                "mef-interfaces:uni" +
+                                                "[mef-interfaces:uni-id = " +
+                                                "current()/../../../uni-id]" +
+                                                "/mef-interfaces:ce-vlans/" +
+                                                "mef-interfaces:ce-vlan/" +
+                                                "mef-interfaces:vid";
+                      }
+                      description
+                                            "VLAN Identifier.";
+                    }
+                  }
+                }
+              }
+            }
+
+            leaf ipvc-id {
+              type mef-types:evc-id-type;
+              mandatory true;
+            }
+            leaf ipvc-type {
+              type mef-types:ipvc-type;
+
+              mandatory true;
+              description
+                            "This IPVC attribute describes the IPVC as either " +
+                            "Cloud-access, Multipoint, or " +
+                            "Rooted-Multipoint.";
+            }
+          }
+        }
+        case evc-choice {
+          container evc {
+
+            must "not(sls-uni-inclusions) or " +
+                        "(sls-uni-inclusions and not(sls-uni-exclusions))" {
+              error-message "The EVC Performance SLS Exclusions and " +
+                            "Inclusions List cannot both be configured for " +
+                            "an EVC.";
+              description
+                            "The EVC Performance SLS Exclusions and Inclusions " +
+                            "List cannot both be configured for an EVC.";
+            }
+            must "(evc-type != 'rooted-multipoint') or " +
+                        "((evc-type = 'rooted-multipoint') and " +
+                        "not(sls-uni-exclusions) )" {
+              error-message "If EVC Type is Rooted-Multipoint, " +
+                            "sls-uni-inclusions must be used instead of " +
+                            "sls-uni-exclusions.";
+              description
+                            "If EVC Type is Rooted-Multipoint, " +
+                            "sls-uni-inclusions must be used instead of " +
+                            "sls-uni-exclusions.";
+            }
+            description
+                        "Ethernet Virtual Circuit(EVC) Configuration and Status.";
+            container unis {
+              description
+                            "EVC Per Universal Network Interface(UNI) " +
+                            "Configuration and Status.";
+              list uni {
+                must "not(evc-uni-ce-vlans/evc-uni-ce-vlan[2]) or " +
+                                "../../preserve-ce-vlan-id = 'true'" {
+                  error-message "When more than one CE-VLAN-ID is " +
+                                    "mapped to an EVC at a UNI, the EVC must have " +
+                                    "CE-VLAN ID Preservation Enabled.";
+                  description
+                                    "When more than one CE-VLAN-ID is mapped to " +
+                                    "an EVC at a UNI, the EVC must have CE-VLAN ID " +
+                                    "Preservation Enabled.";
+                }
+                must "/mef-interfaces:mef-interfaces/mef-interfaces:" +
+                                "unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                                "max-svc-frame-size >= current()/../../" +
+                                "mef-services:max-svc-frame-size]" {
+                  error-message "The value of the EVC Maximum " +
+                                    "Service Frame Size must be less than " +
+                                    "or equal to all the UNI Maximum Service " +
+                                    "Frame Sizes.";
+                  description
+                                    "The value of the EVC Maximum Service Frame " +
+                                    "Size must be less than or equal to all the " +
+                                    "UNI Maximum Service Frame Sizes.";
+                }
+                must "(/mef-interfaces:mef-interfaces/mef-interfaces:" +
+                                "unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                                "bundling-enabled = 'true']) or " +
+                                "(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                                "all-to-one-bundling-enabled = 'true']) or " +
+                                "not(evc-uni-ce-vlans/evc-uni-ce-vlan[2])" {
+                  error-message "If both Bundling and All-to-One " +
+                                    "Bundling are disabled for a UNI, only one " +
+                                    "CE VLAN ID can be configured for a specific " +
+                                    "EVC on that UNI.";
+                  description
+                                    "If both Bundling and All-to-One Bundling are " +
+                                    "disabled for a UNI, only one CE VLAN ID can be " +
+                                    "configured for a specific EVC on that UNI.";
+                }
+                must "(/mef-interfaces:mef-interfaces/mef-interfaces:" +
+                                "unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                                "all-to-one-bundling-enabled = 'false']) or " +
+                                "(count(/mef-services:mef-services/" +
+                                "mef-service/evc/unis/uni[uni-id = " +
+                                "current()/uni-id]) = 1)" {
+                  error-message "If All-to-One Bundling is enabled " +
+                                    "for any UNI in an EVC, all CE-VLAN IDs " +
+                                    "mapped to any EVC for that UNI must map " +
+                                    "to the same EVC ID.";
+                  description
+                                    "If All-to-One Bundling is enabled for any UNI " +
+                                    "in an EVC, all CE-VLAN IDs mapped to any EVC " +
+                                    "for that UNI must map to the same EVC ID.";
+                }
+                must "((/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                                "ingress-bw-profile-per-uni]) or " +
+                                "(/mef-services:mef-services/mef-service/" +
+                                "evc/unis/uni" +
+                                "[uni-id = current()/mef-services:uni-id]" +
+                                "/ingress-bwp-flows-per-cos) or " +
+                                "(/mef-services:mef-services/mef-service/" +
+                                "evc/unis/uni" +
+                                "[uni-id = current()/mef-services:uni-id]" +
+                                "/ingress-bw-profile-per-evc)) or " +
+                                "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-envelopes)" {
+                  error-message "If no Ingress Bandwidth Profiles " +
+                                    "are specied for this UNI (BW Profile " +
+                                    "Per UNI, BWP Flows Per CoS, nor BW Profile " +
+                                    "Per EVC), then the UNI Ingress Envelopes " +
+                                    "list must be empty.";
+                  description
+                                    "If no Ingress Bandwidth Profiles are specied " +
+                                    "for this UNI (BW Profile Per UNI, BWP Flows " +
+                                    "Per CoS, nor BW Profile Per EVC), then the " +
+                                    "UNI Ingress Envelopes list must be empty.";
+                }
+                must "((/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                                "egress-bw-profile-per-uni]) or " +
+                                "(/mef-services:mef-services/mef-service/" +
+                                "evc/unis/uni" +
+                                "[uni-id = current()/mef-services:uni-id]" +
+                                "/egress-bwp-flows-per-eec) or " +
+                                "(/mef-services:mef-services/mef-service/" +
+                                "evc/unis/uni" +
+                                "[uni-id = current()/mef-services:uni-id]" +
+                                "/egress-bw-profile-per-evc)) or " +
+                                "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-envelopes)" {
+                  error-message "If no Egress Bandwidth Profiles are " +
+                                    "specied for this UNI (BW Profile Per UNI, " +
+                                    "BWP Flows Per EEC, nor BW Profile Per EVC), " +
+                                    "then the UNI Egress Envelopes list must be " +
+                                    "empty.";
+                  description
+                                    "If no Egress Bandwidth Profiles are specied " +
+                                    "for this UNI (BW Profile Per UNI, BWP Flows " +
+                                    "Per EEC, nor BW Profile Per EVC), then the UNI " +
+                                    "Egress Envelopes list must be empty.";
+                }
+                must "not(./ingress-bw-profile-per-evc) or " +
+                                "((./ingress-bw-profile-per-evc) and " +
+                                "not(./ingress-bwp-flows-per-cos))" {
+                  error-message "If there is a per EVC Ingress " +
+                                    "Bandwidth Profile on an EVC, then there " +
+                                    "cannot be any per Class of Service Ingress " +
+                                    "Bandwidth Profiles on that EVC.";
+                  description
+                                    "If there is a per EVC Ingress Bandwidth Profile " +
+                                    "on an EVC, then there cannot be any per " +
+                                    "Class of Service Ingress Bandwidth Profiles " +
+                                    "on that EVC.";
+                }
+                must "not(./egress-bw-profile-per-evc) or " +
+                                "((./egress-bw-profile-per-evc) and " +
+                                "not(./egress-bwp-flows-per-eec))" {
+                  error-message "If there is a per EVC Egress " +
+                                    "Bandwidth Profile on an EVC, then there " +
+                                    "cannot be any per Egress Equivalence " +
+                                    "Class Identifier Bandwidth Profiles on " +
+                                    "that EVC.";
+                  description
+                                    "If there is a per EVC Egress Bandwidth " +
+                                    "Profile on an EVC, then there cannot be " +
+                                    "any per Egress Equivalence Class Identifier " +
+                                    "Bandwidth Profiles on that EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-bw-profile-" +
+                                "per-uni) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:ingress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-bw-profile-per-uni]" +
+                                "[mef-global:cir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:ingress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-bw-profile-per-uni]" +
+                                "[mef-global:cbs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Ingress Bandwidth Profile Per UNI: " +
+                                    "If CIR > 0, CBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                  description
+                                    "Ingress Bandwidth Profile Per UNI: If CIR > 0, " +
+                                    "CBS must be greater than or equal to the " +
+                                    "EVC Max Service Frame Size for the EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-bw-profile-per-uni) " +
+                                "or " +
+                                "(/mef-global:mef-global/mef-global:profiles/" +
+                                "mef-global:egress-bwp-flows/mef-global:" +
+                                "bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-bw-profile-per-uni]" +
+                                "[mef-global:cir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:profiles/" +
+                                "mef-global:ingress-bwp-flows/mef-global:" +
+                                "bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-bw-profile-per-uni]" +
+                                "[mef-global:cbs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Egress Bandwidth Profile Per UNI: " +
+                                    "If CIR > 0, CBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                  description
+                                    "Egress Bandwidth Profile Per UNI: If CIR > 0, " +
+                                    "CBS must be greater than or equal to the " +
+                                    "EVC Max Service Frame Size for the EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-envelopes) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:ingress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:cir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:ingress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:cbs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Ingress Bandwidth Profile Envelope: " +
+                                    "If CIR > 0, CBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                  description
+                                    "Ingress Bandwidth Profile Envelope: " +
+                                    "If CIR > 0, CBS must be greater than " +
+                                    "or equal to the EVC Max Service Frame " +
+                                    "Size for the EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-envelopes) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:egress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = " +
+                                "/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:cir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:egress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:cbs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Egress Bandwidth Profile " +
+                                    "Envelope: If CIR > 0, CBS must be greater " +
+                                    "than or equal to the EVC Max Service Frame " +
+                                    "Size for the EVC.";
+                  description
+                                    "Egress Bandwidth Profile Envelope: If CIR > 0, " +
+                                    "CBS must be greater than or equal to the " +
+                                    "EVC Max Service Frame Size for the EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-bw-profile-per-uni) " +
+                                "or " +
+                                "(/mef-global:mef-global/mef-global:profiles/" +
+                                "mef-global:ingress-bwp-flows/mef-global:" +
+                                "bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]/mef-interfaces:" +
+                                "ingress-bw-profile-per-uni]" +
+                                "[mef-global:eir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:profiles/" +
+                                "mef-global:ingress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-bw-profile-per-uni]" +
+                                "[mef-global:ebs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Ingress Bandwidth Profile Per UNI: " +
+                                    "If EIR > 0, EBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                  description
+                                    "Ingress Bandwidth Profile Per UNI: If EIR > 0, " +
+                                    "EBS must be greater than or equal to the " +
+                                    "EVC Max Service Frame Size for the EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-bw-profile-" +
+                                "per-uni) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:egress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]/mef-interfaces:" +
+                                "egress-bw-profile-per-uni]" +
+                                "[mef-global:eir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:ingress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]/mef-interfaces:" +
+                                "egress-bw-profile-per-uni]" +
+                                "[mef-global:ebs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Egress Bandwidth Profile Per UNI: " +
+                                    "If EIR > 0, EBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                  description
+                                    "Egress Bandwidth Profile Per UNI: If EIR > 0, " +
+                                    "EBS must be greater than or equal to the " +
+                                    "EVC Max Service Frame Size for the EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:" +
+                                "unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-envelopes) or " +
+                                "(/mef-global:mef-global/mef-global:profiles/" +
+                                "mef-global:ingress-bwp-flows/mef-global:" +
+                                "bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:eir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:profiles/" +
+                                "mef-global:ingress-bwp-flows/mef-global:" +
+                                "bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:ingress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:ebs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Ingress Bandwidth Profile Envelope: " +
+                                    "If EIR > 0, EBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                  description
+                                    "Ingress Bandwidth Profile Envelope: " +
+                                    "If EIR > 0, EBS must be greater than or equal " +
+                                    "to the EVC Max Service Frame Size for the EVC.";
+                }
+                must "not(/mef-interfaces:mef-interfaces/" +
+                                "mef-interfaces:unis/mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-envelopes) or " +
+                                "(/mef-global:mef-global/mef-global:" +
+                                "profiles/mef-global:egress-bwp-flows/" +
+                                "mef-global:bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:eir = 0]) or " +
+                                "(/mef-global:mef-global/mef-global:profiles/" +
+                                "mef-global:egress-bwp-flows/mef-global:" +
+                                "bwp-flow" +
+                                "[mef-global:bw-profile = /mef-interfaces:" +
+                                "mef-interfaces/mef-interfaces:unis/" +
+                                "mef-interfaces:uni" +
+                                "[mef-interfaces:uni-id = current()/" +
+                                "mef-services:uni-id]" +
+                                "/mef-interfaces:egress-envelopes/" +
+                                "mef-interfaces:envelope/mef-interfaces:" +
+                                "bwp-flows/mef-interfaces:bwp-flow/" +
+                                "mef-interfaces:bw-profile]" +
+                                "[mef-global:ebs >= current()/../../" +
+                                "max-svc-frame-size])" {
+                  error-message "Egress Bandwidth Profile Envelope: " +
+                                    "If EIR > 0, EBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                  description
+                                    "Egress Bandwidth Profile Envelope: " +
+                                    "If EIR > 0, EBS must be greater than or " +
+                                    "equal to the EVC Max Service Frame Size " +
+                                    "for the EVC.";
+                }
+                key "uni-id";
+                description
+                                "EVC Flow Points and EVC-UNI List defines the " +
+                                "roles of each UNI in the Service. One UNI can " +
+                                "be used by 0 or more EVCs.";
+                reference "[MEF10.3] Section 8.3. " +
+                                "[MEF7.3] Section 12.2.2.";
+                container evc-uni-ce-vlans {
+                  description
+                                    "EVC Per UNI CE-VLAN IDs.";
+                  list evc-uni-ce-vlan {
+                    key "vid";
+                    description
+                                        "A list of the CE-VLAN IDs mapped to this UNI " +
+                                        "for this EVC.";
+                    reference "[MEF10.3] Section 8.6.1, [R24] " +
+                                        "[R25], Section 9.10.2, Section 9.12, " +
+                                        "[R76], [R81].";
+                    leaf vid {
+                      type leafref {
+                        path "/mef-interfaces:mef-interfaces/" +
+                                                "mef-interfaces:unis/" +
+                                                "mef-interfaces:uni" +
+                                                "[mef-interfaces:uni-id = " +
+                                                "current()/../../../uni-id]" +
+                                                "/mef-interfaces:ce-vlans/" +
+                                                "mef-interfaces:ce-vlan/" +
+                                                "mef-interfaces:vid";
+                      }
+                      must "not(current()/../../" +
+                                            "evc-uni-ce-vlan[2]) or " +
+                                            "(count(../../../../uni/evc-uni-ce-vlans/" +
+                                            "evc-uni-ce-vlan" +
+                                            "[vid = current()]) = " +
+                                            "count(../../../../uni))" {
+                        error-message "If more than one CE-VLAN ID " +
+                                                "is configured for a UNI as part of " +
+                                                "an EVC, every CE VLAN-ID mapped to " +
+                                                "that EVC must be configured for all " +
+                                                "UNIs within that EVC.";
+                        description
+                                                "If more than one CE-VLAN ID is configured " +
+                                                "for a UNI as part of an EVC, every " +
+                                                "CE VLAN-ID mapped to that EVC must be " +
+                                                "configured for all UNIs within that EVC.";
+                      }
+                      description
+                                            "VLAN Identifier.";
+                    }
+                  }
+                }
+                container ingress-bwp-flows-per-cos {
+                  presence "Use Ingress Bandwidth Profiles Per CoS";
+                  description
+                                    "EVC Per UNI Class of Service Identifiers " +
+                                    "corresponding to this EVC's Ingress Bandwidth " +
+                                    "Profile Flows.";
+                  leaf coupling-enabled {
+                    type boolean;
+                    default "false";
+                    description
+                                        "EVC Per UNI Envelope Coupling Flag (CF) " +
+                                        "attribute.";
+                    reference "[MEF10.3] Section 12.1.";
+                  }
+                  list bwp-flow-per-cos {
+                    key "cos-name";
+                    description
+                                        "EVC Per UNI: The list of Class of Service " +
+                                        "Identifiers corresponding to this UNI's " +
+                                        "Ingress Bandwidth Profile Flow.";
+                    leaf cos-name {
+                      type leafref {
+                        path "/mef-global:mef-global/mef-global:" +
+                                                "profiles/mef-global:cos-names/" +
+                                                "mef-global:cos-name/mef-global:name";
+                      }
+                      description
+                                            "EVC Per UNI: Class of Service Identifier " +
+                                            "for this Bandwidth Profile Flow.";
+                      reference "[MEF7.3] Section 12.1.2.";
+                    }
+                    leaf bw-profile {
+                      type leafref {
+                        path "/mef-interfaces:mef-interfaces/" +
+                                                "mef-interfaces:unis/" +
+                                                "mef-interfaces:uni" +
+                                                "[mef-interfaces:uni-id = " +
+                                                "current()/../../../uni-id]" +
+                                                "/mef-interfaces:ingress-envelopes/" +
+                                                "mef-interfaces:envelope/" +
+                                                "mef-interfaces:env-id";
+                      }
+                      mandatory true;
+                      description
+                                            "EVC Per UNI: Ingress Bandwidth Profile " +
+                                            "Envelope Per CoS ID. If this parameter " +
+                                            "is not configured (ie. 'No') this " +
+                                            "setting is configured else at the " +
+                                            "UNI Level.";
+                      reference "[MEF10.3] Section 10.6, Table 28. " +
+                                            "[MEF7.3] Section 12.1.2.";
+                    }
+                  }
+                }
+                container egress-bwp-flows-per-eec {
+                  presence "Using Egress Bandwidth Profiles Per " +
+                                    "Egress Equivalence Class";
+                  description
+                                    "EVC Per UNI: The Egress Equivalence Class " +
+                                    "Identifiers corresponding to this EVC's Egress " +
+                                    "Bandwidth Profile Flows.";
+                  leaf coupling-enabled {
+                    type boolean;
+                    default "false";
+                    description
+                                        "EVC Per UNI: The Envelope Coupling Flag (CF) " +
+                                        "attribute.";
+                    reference "[MEF10.3] Section 12.1.";
+                  }
+                  list bwp-flow-per-eec {
+                    key "eec-name";
+                    description
+                                        "EVC Per UNI: The list of Egress Equivalence " +
+                                        "Class Identifiers corresponding to this " +
+                                        "EVC's Egress Bandwidth Profile Flow.";
+                    leaf eec-name {
+                      type leafref {
+                        path "/mef-global:mef-global/mef-global:" +
+                                                "profiles/mef-global:eec-names/" +
+                                                "mef-global:eec-name/mef-global:name";
+                      }
+                      description
+                                            "EVC Per UNI: Egress Equivalence Class " +
+                                            "Identifier for this Bandwidth Profile Flow.";
+                      reference "[MEF7.3] Section 12.1.2.";
+                    }
+                    leaf bw-profile {
+                      type leafref {
+                        path "/mef-interfaces:mef-interfaces/" +
+                                                "mef-interfaces:unis/" +
+                                                "mef-interfaces:uni" +
+                                                "[mef-interfaces:uni-id = " +
+                                                "current()/../../../uni-id]" +
+                                                "/mef-interfaces:egress-envelopes/" +
+                                                "mef-interfaces:envelope/" +
+                                                "mef-interfaces:env-id";
+                      }
+                      mandatory true;
+                      description
+                                            "EVC Per UNI: Egress Bandwidth Profile " +
+                                            "Envelope Per Equivance Class. If this " +
+                                            "parameter is not configured (ie. 'No') " +
+                                            "this setting is configured else at the " +
+                                            "UNI Level.";
+                      reference "[MEF10.3] Section 10.6, Table 28. " +
+                                            "[MEF7.3] Section 12.1.2.";
+                    }
+                  }
+                }
+                container status {
+                  description
+                                    "EVC Per UNI: This status group is related to " +
+                                    "the MEF 7.3 Service Endpoint";
+                  leaf oper-state-enabled {
+                    type boolean;
+                    default "false";
+                    config false;
+                    description
+                                        "EVC Per UNI: Operational Status of the " +
+                                        "Virtual Connection as Enabled/Disabled.";
+                    reference "[MEF15]. [MEF7.3] Section 11.2.1.";
+                  }
+                  leaf available-status {
+                    type mef-types:svc-endpoint-availability-type;
+                    default "not-installed";
+                    config false;
+                    description
+                                        "EVC Per UNI: Availability Status of the " +
+                                        "Virtual Connection.";
+                    reference "[MEF15]. [MEF7.3] Section 11.2.1.";
+                  }
+                }
+                leaf uni-id {
+                  type leafref {
+                    path "/mef-interfaces:mef-interfaces/" +
+                                        "mef-interfaces:unis/mef-interfaces:uni/" +
+                                        "mef-interfaces:uni-id";
+                  }
+                  description
+                                    "EVC Per UNI: The UNI ID paired with the EVC ID " +
+                                    "in the containing list.";
+                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf role {
+                  type mef-types:evc-uni-role-type;
+                  mandatory true;
+                  description
+                                    "EVC Per UNI: The UNI Role MUST have the value " +
+                                    "of either 'root' or 'leaf'.";
+                  reference "[MEF10.3] [R4], [R5], [R10], [R11], " +
+                                    "[R12]. [MEF7.3] Section 12.2.2.";
+                }
+                leaf admin-state-enabled {
+                  type boolean;
+                  default "true";
+                  description
+                                    "EVC Per UNI: Locked/Unlocked is inconsistent " +
+                                    "with Oper Status and will be confusing.";
+                  reference "[MEF15]. [MEF7.3] Section 11.2.1.";
+                }
+                leaf color-id {
+                  type mef-types:cos-color-identifier-type;
+                  description
+                                    "EVC Per UNI: The Color Identifier for " +
+                                    "Service Frames.";
+                  reference "[MEF10.3] Section 10.3. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf data-svc-frm-cos {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:profiles/" +
+                                        "mef-global:cos/mef-global:cos-profile/" +
+                                        "mef-global:id";
+                  }
+                  must "not(/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:cos/" +
+                                    "mef-global:cos-profile" +
+                                    "[mef-global:id = current()]" +
+                                    "/mef-global:cos-pcp) or " +
+                                    "((/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:cos/" +
+                                    "mef-global:cos-profile" +
+                                    "[mef-global:id = current()]" +
+                                    "/mef-global:cos-pcp) and " +
+                                    "((../color-id = 'pcp') or " +
+                                    "(../color-id = 'dei')) )" {
+                    error-message "When the Class of Service " +
+                                        "Identifier is based on PCP for a " +
+                                        "given EVC at a given UNI, the Color " +
+                                        "Identifier must be based on either " +
+                                        "DEI or PCP.";
+                    description
+                                        "When the Class of Service Identifier is " +
+                                        "based on PCP for a given EVC at a given UNI, " +
+                                        "the Color Identifier must be based on either " +
+                                        "DEI or PCP.";
+                  }
+                  must "not(/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:cos/mef-global:" +
+                                    "cos-profile" +
+                                    "[mef-global:id = current()]/mef-global:" +
+                                    "cos-dscp) or " +
+                                    "((/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:cos/mef-global:" +
+                                    "cos-profile" +
+                                    "[mef-global:id = current()]/mef-global:" +
+                                    "cos-dscp) and " +
+                                    "(../color-id = 'dscp'))" {
+                    error-message "When the Class of Service " +
+                                        "Identifier is based on DSCP for a " +
+                                        "given EVC at a given UNI, the Color " +
+                                        "Identifier must be based DSCP.";
+                    description
+                                        "When the Class of Service Identifier is based " +
+                                        "on DSCP for a given EVC at a given UNI, the " +
+                                        "Color Identifier must be based DSCP.";
+                  }
+                  description
+                                    "EVC Per UNI: Ingress Data Service Frame " +
+                                    "CoS Profile.";
+                  reference "[MEF10.3] Section 8.8, Section 10.2. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf l2cp-svc-frm-cos {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:" +
+                                        "profiles/mef-global:l2cp-cos/mef-global:" +
+                                        "l2cp-profile/mef-global:id";
+                  }
+                  description
+                                    "EVC Per UNI: Ingress Layer 2 Control Protocol " +
+                                    "Processing.";
+                  reference "[MEF10.3] Section 8.8, Section 10.2. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf soam-svc-frm-cos {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:profiles/" +
+                                        "mef-global:cos/mef-global:cos-profile/" +
+                                        "mef-global:id";
+                  }
+                  must "(not(.) and not(../data-svc-frm-cos)) or " +
+                                    "(. = ../data-svc-frm-cos)" {
+                    error-message "For a given EVC at a given UNI, " +
+                                        "the basis for the Class of Service " +
+                                        "Identifier for ingress SOAM Service " +
+                                        "Frames must be the same as that for " +
+                                        "ingress Data Service Frames.";
+                    description
+                                        "For a given EVC at a given UNI, the basis " +
+                                        "for the Class of Service Identifier for " +
+                                        "ingress SOAM Service Frames must be the " +
+                                        "same as that for ingress Data Service Frames.";
+                  }
+                  description
+                                    "EVC Per UNI: Ingress SOAM Service Frames.";
+                  reference "[MEF7.3] Section 12.1.2.";
+                }
+                leaf data-svc-frm-eec {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:profiles/" +
+                                        "mef-global:eec/mef-global:eec-profile/" +
+                                        "mef-global:id";
+                  }
+                  must "not(/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:eec/mef-global:" +
+                                    "eec-profile" +
+                                    "[mef-global:id = current()]" +
+                                    "/mef-global:eec-pcp) or " +
+                                    "((/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:eec/mef-global:" +
+                                    "eec-profile" +
+                                    "[mef-global:id = current()]" +
+                                    "/mef-global:eec-pcp) and " +
+                                    "((../color-id = 'pcp') or " +
+                                    "(../color-id = 'dei')) )" {
+                    error-message "When the Egress Equivalence " +
+                                        "Class Identifier is based on PCP " +
+                                        "for a given EVC at a given UNI, " +
+                                        "the Color Identifier must be based " +
+                                        "on either DEI or PCP.";
+                    description
+                                        "When the Egress Equivalence Class Identifier " +
+                                        "is based on PCP for a given EVC at a " +
+                                        "given UNI, the Color Identifier must " +
+                                        "be based on either DEI or PCP.";
+                  }
+                  must "not(/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:eec/mef-global:" +
+                                    "eec-profile" +
+                                    "[mef-global:id = current()]" +
+                                    "/mef-global:eec-dscp) or " +
+                                    "((/mef-global:mef-global/mef-global:" +
+                                    "profiles/mef-global:eec/mef-global:" +
+                                    "eec-profile" +
+                                    "[mef-global:id = current()]" +
+                                    "/mef-global:eec-dscp) and " +
+                                    "(../color-id = 'dscp'))" {
+                    error-message "When the Egress Equivalence " +
+                                        "Class Identifier is based on DSCP for " +
+                                        "a given EVC at a given UNI, the Color " +
+                                        "Identifier must be based DSCP.";
+                    description
+                                        "When the Egress Equivalence Class Identifier " +
+                                        "is based on DSCP for a given EVC at a given " +
+                                        "UNI, the Color Identifier must be based DSCP.";
+                  }
+                  description
+                                    "EVC Per UNI: Egress Data Service Frame Processing.";
+                  reference "[MEF10.3] Section 10.4. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf l2cp-svc-frm-eec {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:profiles/" +
+                                        "mef-global:l2cp-eec/mef-global:" +
+                                        "l2cp-profile/mef-global:id";
+                  }
+                  description
+                                    "EVC Per UNI: Egress Layer 2 Control Protocol " +
+                                    "Processing.";
+                  reference "[MEF10.3] Section 10.4. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf soam-svc-frm-eec {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:" +
+                                        "profiles/mef-global:eec/mef-global:" +
+                                        "eec-profile/mef-global:id";
+                  }
+                  must "(not(.) and not(../data-svc-frm-eec)) or " +
+                                    "(. = ../data-svc-frm-eec)" {
+                    error-message "For a given EVC at a given UNI, " +
+                                        "the basis for the Egress Equivalence " +
+                                        "Class Identifier for egress SOAM " +
+                                        "Service Frames must be the same as " +
+                                        "that for egress Data Service Frames.";
+                    description
+                                        "For a given EVC at a given UNI, the basis " +
+                                        "for the Egress Equivalence Class Identifier " +
+                                        "for egress SOAM Service Frames must be " +
+                                        "the same as that for egress Data " +
+                                        "Service Frames.";
+                  }
+                  description
+                                    "EVC Per UNI: Egress SOAM Service Frames.";
+                  reference "[MEF10.3] Section 10.4. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf ingress-bw-profile-per-evc {
+                  type leafref {
+                    path "/mef-interfaces:mef-interfaces/" +
+                                        "mef-interfaces:unis/" +
+                                        "mef-interfaces:uni" +
+                                        "[mef-interfaces:uni-id = " +
+                                        "current()/../uni-id]" +
+                                        "/mef-interfaces:ingress-envelopes/" +
+                                        "mef-interfaces:envelope/" +
+                                        "mef-interfaces:env-id";
+                  }
+                  description
+                                    "EVC Per UNI: Ingress Bandwidth Profile " +
+                                    "Envelope Per EVC. If this parameter is " +
+                                    "not configured (ie. 'No') this setting " +
+                                    "is configured else at the UNI Level.";
+                  reference "[MEF10.3] Section 10.5. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf egress-bw-profile-per-evc {
+                  type leafref {
+                    path "/mef-interfaces:mef-interfaces/" +
+                                        "mef-interfaces:unis/" +
+                                        "mef-interfaces:uni" +
+                                        "[mef-interfaces:uni-id = " +
+                                        "current()/../uni-id]" +
+                                        "/mef-interfaces:egress-envelopes/" +
+                                        "mef-interfaces:envelope/mef-interfaces:" +
+                                        "env-id";
+                  }
+                  description
+                                    "EVC Per UNI: Egress Bandwidth Profile Envelope " +
+                                    "Per EVC. If this parameter is not configured " +
+                                    "(ie. 'No') this setting is configured else at " +
+                                    "the UNI Level.";
+                  reference "[MEF10.3] Section 10.7. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf src-mac-addr-limit-enabled {
+                  type boolean;
+                  default "false";
+                  description
+                                    "EVC Per UNI: Source MAC Address Limit " +
+                                    "Enable / Disable. If Enabled, the values " +
+                                    "for the Source MAC Address Limit and Source " +
+                                    "MAC Address Interval must be set.";
+                  reference "[MEF10.3] Section 10.9. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf src-mac-addr-limit {
+                  type uint32 {
+                    range "1..max";
+                  }
+                  description
+                                    "EVC Per UNI: Source MAC Address Limit. " +
+                                    "This value is used when the Source MAC Address " +
+                                    "Limit Enabled is true.";
+                  reference "[MEF10.3] Section 10.9.";
+                }
+                leaf src-mac-addr-limit-interval {
+                  type yang:timeticks;
+                  default "0";
+                  description
+                                    "EVC Per UNI: Source MAC Address Limit " +
+                                    "Interval. This value is used when the " +
+                                    "Source MAC Address Limit Enabled is true.";
+                  reference "[MEF10.3] Section 10.9.";
+                }
+                leaf test-meg-enabled {
+                  type boolean;
+                  default "false";
+                  description
+                                    "EVC Per UNI: Test MEG Enabled / Disabled.";
+                  reference "[MEF10.3] Section 10.10. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf test-meg {
+                  type mef-types:identifier45;
+                  description
+                                    "EVC Per UNI: Test MEG Identifier.";
+                  reference "[MEF7.3] Section 12.1.2.";
+                }
+                leaf subscriber-meg-mip-enabled {
+                  type boolean;
+                  default "false";
+                  description
+                                    "EVC Per UNI: Subscriber MEG MIP " +
+                                    "Enabled / Disabled.";
+                  reference "[MEF10.3] Section 10.11. " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf subscriber-meg-mip {
+                  type mef-types:identifier45;
+                  description
+                                    "EVC Per UNI: Subscriber MEG MIP Identifier.";
+                  reference "[MEF7.3] Section 12.1.2.";
+                }
+              }
+            }
+            container status {
+              description
+                            "This status group is related to the MEF 7.3 Virtual " +
+                            "Connection";
+              leaf oper-state-enabled {
+                type boolean;
+                default "false";
+                config false;
+                description
+                                "EVC Operational Status of the Virtual Connection " +
+                                "as Enabled/Disabled.";
+                reference "[MEF7.3] Section 11.1.1.";
+              }
+              leaf available-status {
+                type mef-types:virt-cx-availability-type;
+                default "not-installed";
+                config false;
+                description
+                                "EVC Availability Status of the Virtual Connection.";
+                reference "[MEF7.3] Section 11.1.1.";
+              }
+            }
+            container sls-inclusions-by-cos {
+              description
+                            "SLS Inclusions by CoS: For this EVC, the following " +
+                            "CoS Names/Labels are applicable.";
+              list sls-inclusion-by-cos {
+                key "cos-name";
+                description
+                                "CoS Name.";
+                leaf cos-name {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:profiles/" +
+                                        "mef-global:cos-names/mef-global:" +
+                                        "cos-name/mef-global:name";
+                  }
+                  description
+                                    "EVC: This attribute identifies the name of " +
+                                    "a class of service (CoS) instance to be used " +
+                                    "for EVC Performance.";
+                }
+              }
+            }
+            container sls-uni-inclusions {
+              presence "EVC: Defines the EVC Flow Points (UNI) Pairs " +
+                            "that must conform to the EVC's SLS Performance " +
+                            "Metrics.";
+              description
+                            "SLS UNI Inclusions List. The following pairs of UNI " +
+                            "Interconnections are to required to meet the " +
+                            "SLS Performance Objectives. Configing both SLS " +
+                            "UNI Inclusions and SLS UNI Exclusions is not " +
+                            "permitted.";
+              list sls-uni-inclusion-set {
+                must "uni-id1 != uni-id2" {
+                  error-message "The two UNI IDs for a given " +
+                                    "inclusion cannot be the same.";
+                  description
+                                    "The two UNI IDs for a given inclusion " +
+                                    "cannot be the same.";
+                }
+                must "(../../evc-type != 'rooted-multipoint') or " +
+                                "((../../evc-type = 'rooted-multipoint') " +
+                                "and " +
+                                "not((../../unis/uni[uni-id = " +
+                                "current()/uni-id1]/role = 'leaf') and " +
+                                "(../../unis/uni[uni-id = current()/uni-id2]" +
+                                "/role = 'leaf')))" {
+                  error-message "If EVC Type is Rooted-Multipoint, " +
+                                    "sls-uni-inclusion UNI Pairs cannot both " +
+                                    "be role 'leaf'.";
+                  description
+                                    "If EVC Type is Rooted-Multipoint, " +
+                                    "sls-uni-inclusion UNI Pairs cannot " +
+                                    "both be role 'leaf'.";
+                }
+                key "pm-type pm-id uni-id1 uni-id2";
+                description
+                                "EVC: Defines the EVC Flow Points (UNI) Pairs that " +
+                                "must conform to the EVC's SLS Performance " +
+                                "Metrics. Use of this list indicates that a " +
+                                "complete set of UNI Pairs has been specified " +
+                                "for the Performance Metrics defined in the " +
+                                "selected SLS.";
+                leaf pm-type {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:slss/" +
+                                        "mef-global:sls" +
+                                        "[mef-global:sls-id = current()/../../../" +
+                                        "evc-performance-sls]" +
+                                        "/mef-global:perf-objs/mef-global:" +
+                                        "perf-obj/mef-global:pm-type";
+                  }
+                  description
+                                    "EVC: Performance Metric.";
+                  reference "[MEF10.3] Section 8.8.";
+                }
+                leaf pm-id {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:slss/" +
+                                        "mef-global:sls" +
+                                        "[mef-global:sls-id = current()/../../../" +
+                                        "evc-performance-sls]" +
+                                        "/mef-global:perf-objs/mef-global:perf-obj" +
+                                        "[mef-global:pm-type = current()/../" +
+                                        "pm-type]" +
+                                        "/mef-global:pm-id";
+                  }
+                  description
+                                    "EVC: This is a friendly name for specific " +
+                                    "performance profile.";
+                }
+                leaf uni-id1 {
+                  type leafref {
+                    path "../../../unis/uni/uni-id";
+                  }
+                  description
+                                    "EVC: The UNI ID paired with the EVC ID in the " +
+                                    "containing list.";
+                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf uni-id2 {
+                  type leafref {
+                    path "../../../unis/uni/uni-id";
+                  }
+                  description
+                                    "EVC: The UNI ID paired with the EVC ID in the " +
+                                    "containing list.";
+                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+              }
+            }
+            container sls-uni-exclusions {
+              presence "Not all EVC Flow Points (UNI) must conform " +
+                            "to the EVC SLS Performance Metrics.";
+              description
+                            "EVC: Not all EVC Flow Points (UNI) must conform to " +
+                            "the EVC SLS Performance Metrics. Use of this " +
+                            "list indicates that all UNI Pairs EXCEPT for " +
+                            "the ones indicated (per Performance Metric) must " +
+                            "conform to the SLS.";
+              list sls-uni-exclusion-set {
+                must "uni-id1 != uni-id2" {
+                  error-message "The two UNI IDs for a given " +
+                                    "exclusion cannot be the same.";
+                  description
+                                    "The two UNI IDs for a given exclusion cannot " +
+                                    "be the same as these pairs are invalid as " +
+                                    "defined in MEF 10.3.";
+                }
+                key "pm-type pm-id uni-id1 uni-id2";
+                description
+                                "SLS UNI Exclusions List. The following pairs " +
+                                "of UNI Interconnections are not required " +
+                                "meet the SLS Performance Objectives. " +
+                                "Configing both SLS UNI Inclusions and SLS " +
+                                "UNI Exclusions is not permitted.";
+                leaf pm-type {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:" +
+                                        "slss/mef-global:sls" +
+                                        "[mef-global:sls-id = current()/../../../" +
+                                        "evc-performance-sls]" +
+                                        "/mef-global:perf-objs/mef-global:" +
+                                        "perf-obj/mef-global:pm-type";
+                  }
+                  description
+                                    "EVC: Performance Metric.";
+                  reference "[MEF10.3] Section 8.8.";
+                }
+                leaf pm-id {
+                  type leafref {
+                    path "/mef-global:mef-global/mef-global:slss/" +
+                                        "mef-global:sls" +
+                                        "[mef-global:sls-id = current()/../../../" +
+                                        "evc-performance-sls]" +
+                                        "/mef-global:perf-objs/mef-global:perf-obj" +
+                                        "[mef-global:pm-type = current()/../" +
+                                        "pm-type]" +
+                                        "/mef-global:pm-id";
+                  }
+                  description
+                                    "EVC: This is a friendly name for specific " +
+                                    "performance profile.";
+                }
+                leaf uni-id1 {
+                  type leafref {
+                    path "../../../unis/uni/uni-id";
+                  }
+                  description
+                                    "EVC: The UNI ID paired with the EVC ID in the " +
+                                    "containing list.";
+                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+                leaf uni-id2 {
+                  type leafref {
+                    path "../../../unis/uni/uni-id";
+                  }
+                  description
+                                    "EVC: The UNI ID paired with the EVC ID in the " +
+                                    "containing list.";
+                  reference "[MEF10.3] Section 8.3, Section 10.1.  " +
+                                    "[MEF7.3] Section 12.1.2.";
+                }
+              }
+            }
+            leaf evc-id {
+              type mef-types:evc-id-type;
+              mandatory true;
+              description
+                            "The EVC ID must be unique across all EVCs in the CEN." +
+                            " The EVC ID must be non-NULL.";
+              reference "[MEF10.3] Section 8.2 [R7]. " +
+                            "[MEF7.3] Section 11.1.1, Section 12.2.2.";
+            }
+            leaf evc-status {
+              type mef-types:evc-status-type;
+              config false;
+              description
+                            "EVC Operational Status.";
+              reference "[MEF16] Section 5.3.";
+            }
+            leaf evc-type {
+              type mef-types:evc-type;
+              must "(. != 'point-to-point') or " +
+                            "((. = 'point-to-point') and " +
+                            "(count(../unis/uni[role = 'leaf']) = 0))" {
+                error-message "If EVC Type is Point-to-Point, all " +
+                                "UNI Roles must be root.";
+                description
+                                "If EVC Type is Point-to-Point, all UNI Roles must " +
+                                "be root.";
+              }
+              must "(. != 'multipoint-to-multipoint') or " +
+                            "((. = 'multipoint-to-multipoint') and " +
+                            "(count(../unis/uni[role = 'leaf']) = 0))" {
+                error-message "If EVC Type is " +
+                                "Multipoint-to-Multipoint, all UNI Roles " +
+                                "must be root.";
+                description
+                                "If EVC Type is Multipoint-to-Multipoint, all UNI " +
+                                "Roles must be root.";
+              }
+              must "(. != 'rooted-multipoint') or " +
+                            "((. = 'rooted-multipoint') and " +
+                            "(count(../unis/uni[role = 'root']) > 0) )" {
+                error-message "If EVC Type is Rooted-Multipoint, one " +
+                                "or more UNI Roles must be root.";
+                description
+                                "If EVC Type is Rooted-Multipoint, one or more " +
+                                "UNI Roles must be root.";
+              }
+              must "(. != 'point-to-point') or " +
+                            "((. = 'point-to-point') and " +
+                            "(count(../unis/uni) = 2))" {
+                error-message "If EVC Type is Point-to-Point, there " +
+                                "must be exactly 2 UNI configured for the EVC.";
+                description
+                                "If EVC Type is Point-to-Point, there must be " +
+                                "exactly 2 UNI configured for the EVC.";
+              }
+              must "(. != 'multipoint-to-multipoint') or " +
+                            "((. = 'multipoint-to-multipoint') and " +
+                            "(count(../unis/uni) > 1) and " +
+                            "(count(../unis/uni) <= ../max-uni-count))" {
+                error-message "If EVC Type is " +
+                                "Multipoint-to-Multipoint, " +
+                                "there must be 2 or more UNI configured " +
+                                "for the EVC.";
+                description
+                                "If EVC Type is Multipoint-to-Multipoint, " +
+                                "there must be 2 or more UNI configured for " +
+                                "the EVC.";
+              }
+              must "(. != 'rooted-multipoint') or " +
+                            "((. = 'rooted-multipoint') and " +
+                            "(count(../unis/uni) > 1) and " +
+                            "(count(../unis/uni) <= ../max-uni-count))" {
+                error-message "If EVC Type is Rooted-Multipoint, " +
+                                "there must be 2 or more UNI configured for the EVC.";
+                description
+                                "If EVC Type is Rooted-Multipoint, there must " +
+                                "be 2 or more UNI configured for the EVC.";
+              }
+              must "(. != 'point-to-point') or " +
+                            "((. = 'point-to-point') and " +
+                            "(../max-uni-count = 2))" {
+                error-message "If EVC Type is Point-to-Point, " +
+                                "the value of max-uni-count must be 2.";
+                description
+                                "If EVC Type is Point-to-Point, the value of " +
+                                "max-uni-count must be 2.";
+              }
+              must "(. != 'multipoint-to-multipoint') or " +
+                            "((. = 'multipoint-to-multipoint') and " +
+                            "(../max-uni-count > 2))" {
+                error-message "If EVC Type is " +
+                                "Multipoint-to-Multipoint, the value of " +
+                                "max-uni-count must be at least 3.";
+                description
+                                "If EVC Type is Multipoint-to-Multipoint, the " +
+                                "value of max-uni-count must be at least 3.";
+              }
+              must "(. != 'rooted-multipoint') or " +
+                            "((. = 'rooted-multipoint') and " +
+                            "(../max-uni-count > 2))" {
+                error-message "If EVC Type is Rooted-Multipoint, " +
+                                "the value of max-uni-count must be at " +
+                                "least 3.";
+                description
+                                "If EVC Type is Rooted-Multipoint, the value " +
+                                "of max-uni-count must be at least 3.";
+              }
+              // mandatory true;
+              description
+                            "This EVC attribute describes the EVC as either " +
+                            "Multipoint-To-Multipoint, Point-To-Point, or " +
+                            "Rooted-Multipoint.";
+              reference "[MEF10.3] Section 8.1, [R4], [R5], " +
+                            "[R10], [R11], [R12], [R13] and [R14]. " +
+                            "[MEF7.3] Section 12.2.2.";
+            }
+            leaf admin-state-enabled {
+              type boolean;
+              default "true";
+              description
+                            "EVC: Locked/Unlocked is inconsistent with " +
+                            "Oper Status and will be confusing.";
+              reference "[MEF15]. [MEF7.3] Section 11.1.1.";
+            }
+            leaf elastic-enabled {
+              type boolean;
+              default "true";
+              description
+                            "EVC: Elastic Enabled/Disabled.";
+              reference "[MEF7.3] Section 11.1.1.";
+            }
+            leaf elastic-service {
+              type mef-types:identifier45;
+              description
+                            "EVC: Related to CE4Cloud Information Model.";
+              reference "[MEF7.3] Section 11.1.1.";
+            }
+            leaf max-uni-count {
+              type uint32 {
+                range "2..max";
+              }
+              must "(. > 2) or ((. = 2) and " +
+                            "(../evc-type = 'point-to-point'))" {
+                error-message "If EVC Type is Point-to-Point, the " +
+                                "max-uni-count value must be 2.";
+                description
+                                "If EVC Type is Point-to-Point, the max-uni-count " +
+                                "value must be 2.";
+              }
+              must "(. = 2) or ((. > 2) and " +
+                            "((../evc-type = 'multipoint-to-multipoint') or " +
+                            "(../evc-type = 'rooted-multipoint')))" {
+                error-message "If EVC Type is " +
+                                "Multipoint-to-Multipoint or " +
+                                "Rooted-Multipoint, the max-uni-count value " +
+                                "must be at least 3.";
+                description
+                                "If EVC Type is Multipoint-to-Multipoint or " +
+                                "Rooted-Multipoint, the max-uni-count value " +
+                                "must be at least 3.";
+              }
+              default "2";
+              description
+                            "EVC:The Maximum Number of UNIs this EVC can be " +
+                            "configured for (Default 2).If EVC Type is " +
+                            "Multipoint-to-Multipoint or Rooted-Multipoint, " +
+                            "the max-uni-count value must be at least 3. " +
+                            "This value must be 2 for point-to-point mode.";
+              reference "[MEF10.3] [R14]. [MEF7.3] Section 12.2.2.";
+            }
+            leaf preserved-vlan {
+              type uint32;
+            }
+            leaf preserve-ce-vlan-id {
+              type boolean;
+              default "false";
+              description
+                            "EVC:An EVC with more than one CE-VLAN ID mapping " +
+                            "to it must have the same list of CE-VLAN IDs " +
+                            "mapping to the EVC at each UNI in the EVC.";
+              reference "[MEF10.3] Section 8.6.1, [R24] [R25], " +
+                            "Section 9.10.2, Section 9.12, [R81], Figure 20. " +
+                            "[MEF7.3] Section 12.2.2.";
+            }
+            leaf cos-preserve-ce-vlan-id {
+              type boolean;
+              default "false";
+              description
+                            "EVC: Preserve CE-VLAN ID for CoS.";
+              reference "[MEF10.3] Section 8.6.2, [R26]. " +
+                            "[MEF7.3] Section 12.2.2.";
+            }
+            leaf evc-performance-sls {
+              type leafref {
+                path "/mef-global:mef-global/mef-global:slss/" +
+                                "mef-global:sls/mef-global:sls-id";
+              }
+              description
+                            "EVC: EVC-specific performance objectives and " +
+                            "parameters. Note that an SLS can also specify " +
+                            "performance objectives spanning more than one EVC. " +
+                            "By default, all the UNI associated with the EVC " +
+                            "have this SLS applied for them.";
+              reference "[MEF10.3] Section 8.8, Section 10. " +
+                            "[MEF7.3] Section 12.2.2.";
+            }
+            leaf unicast-svc-frm-delivery {
+              type mef-types:data-svc-frame-delivery-type;
+              default "unconditional";
+              description
+                            "EVC: Unicast Data Service Frame Delivery Mode " +
+                            "(unconditional[default], conditional, or discard).";
+              reference "[MEF10.3] Section 8.5.2,[R16], [R17], " +
+                            "Section 8.8, Section 11. [MEF7.3] Section 12.2.2.";
+            }
+            leaf multicast-svc-frm-delivery {
+              type mef-types:data-svc-frame-delivery-type;
+              default "unconditional";
+              description
+                            "EVC: Multicast Data Service Frame Delivery Mode " +
+                            "(unconditional[default], conditional, or discard).";
+              reference "[MEF10.3] Section 8.5.2, [R16], [R18], " +
+                            "Section 8.8, Section 11. [MEF7.3] Section 12.2.2.";
+            }
+            leaf broadcast-svc-frm-delivery {
+              type mef-types:data-svc-frame-delivery-type;
+              default "unconditional";
+              description
+                            "EVC: Broadcast Data Service Frame Delivery Mode " +
+                            "(unconditional[default], conditional, or discard).";
+              reference "[MEF10.3] Section 8.5.2, [R16], [R19], " +
+                            "Section 8.8, Section 11. [MEF7.3] Section 12.2.2.";
+            }
+            leaf evc-meg-id {
+              type mef-types:identifier45;
+              description
+                            "EVC: Identifies the Maintenance Entity Group (MEG) " +
+                            "for this EVC.";
+              reference "[MEF7.3] Section 12.2.2. MEF 35.1.";
+            }
+            leaf max-svc-frame-size {
+              type mef-types:max-svc-frame-size-type;
+              default "1600";
+              description
+                            "EVC: This attribute describes the maximum service " +
+                            "frame size for the EVC.";
+              reference "[MEF10.3] Section 8.9, Section 9.7, [R71], " +
+                            "[MEF6.2] Section 8.2.2 and MEF 22.1: [D2]. " +
+                            "[MEF7.3] Section 12.2.2.";
+            }
+          }
+        }
+      }
+      leaf svc-id {
+        type mef-types:retail-svc-id-type;
+        description
+                "The MEF Service ID is a simple key used to " +
+                "distinguish MEF Service Configuration Groups.";
+        reference "[MEF10.3] Section 7.";
+      }
+      leaf sp-id {
+        when "/mef-global:mef-global/mef-global:svc-providers" {
+          description
+                    "Only configure when the Global Service Providers " +
+                    "list has been populated.";
+        }
+        type leafref {
+          path "/mef-global:mef-global/mef-global:svc-providers/" +
+                    "mef-global:svc-provider/mef-global:sp-id";
+        }
+        description
+                "The MEF Service Provider ID must be globally unique " +
+                "as all CENs and Subscribers must be supported by a " +
+                "specific Service Provider(SP). A SP can support " +
+                "multiple CENs.";
+        reference "[MEF10.3] Section 7.";
+      }
+      leaf svc-type {
+        type mef-types:mef-service-type;
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "svc-mux-enabled = 'true']) = 0))" {
+          error-message "For EPL, Service Multiplexing must be " +
+                    "disabled for all UNIs in the EVC UNI List.";
+          description
+                    "For EPL, Service Multiplexing must be disabled for " +
+                    "all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "bundling-enabled = 'true']) = 0))" {
+          error-message "For EPL, Bundling must be disabled for " +
+                    "all UNIs in the EVC UNI List.";
+          description
+                    "For EPL, Bundling must be disabled for all UNIs in " +
+                    "the EVC UNI List.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/" +
+                "mef-services:uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "all-to-one-bundling-enabled = 'false']) = 0))" {
+          error-message "For EPL, All-to-One Bundling must be " +
+                    "enabled for all UNIs in the EVC UNI List.";
+          description
+                    "For EPL, All-to-One Bundling must be enabled for " +
+                    "all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "max-evc-count != 1]) = 0))" {
+          error-message "For EPL, Max EVC Count must be 1 for " +
+                    "all UNIs in the EVC UNI List.";
+          description
+                    "For EPL, Max EVC Count must be 1 for all UNIs " +
+                    "in the EVC UNI List.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(count(../evc/unis/uni/egress-bwp-flows-per-eec/" +
+                "bwp-flow-per-eec) = 0))" {
+          error-message "For EPL, Egress Bandwidth Profile per " +
+                    "Egress Equivalence Class cannot be set for " +
+                    "all UNIs in the EVC per UNI List.";
+          description
+                    "For EPL, Egress Bandwidth Profile per Egress " +
+                    "Equivalence Class cannot be set for all UNIs in the " +
+                    "EVC per UNI List.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(count(../evc/unis/uni" +
+                "[src-mac-addr-limit-enabled = 'true']) = 0) )" {
+          error-message "For EPL, Source MAC Address Limit must " +
+                    "be disabled.";
+          description
+                    "For EPL, Source MAC Address Limit must be disabled.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(../evc/evc-type = 'point-to-point'))" {
+          error-message "For EPL, EVC Type must be Point-to-Point.";
+          description
+                    "For EPL, EVC Type must be Point-to-Point.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(../evc/unicast-svc-frm-delivery = " +
+                "'unconditional'))" {
+          error-message "For EPL, unicast-svc-frm-delivery " +
+                    "must be unconditional.";
+          description
+                    "For EPL, unicast-svc-frm-delivery must be " +
+                    "unconditional.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(../evc/multicast-svc-frm-delivery = " +
+                "'unconditional'))" {
+          error-message "For EPL, multicast-svc-frm-delivery " +
+                    "must be unconditional.";
+          description
+                    "For EPL, multicast-svc-frm-delivery must be " +
+                    "unconditional.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(../evc/broadcast-svc-frm-delivery = " +
+                "'unconditional'))" {
+          error-message "For EPL, broadcast-svc-frm-delivery " +
+                    "must be unconditional.";
+          description
+                    "For EPL, broadcast-svc-frm-delivery must be " +
+                    "unconditional.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(../evc/preserve-ce-vlan-id = 'true'))" {
+          error-message "For EPL, CE-VLAN ID Preservation " +
+                    "must be enabled.";
+          description
+                    "For EPL, CE-VLAN ID Preservation must be enabled.";
+        }
+        must "(. != 'epl') or ((. = 'epl') and " +
+                "(../evc/cos-preserve-ce-vlan-id = 'true'))" {
+          error-message "For EPL, CE-VLAN ID CoS Preservation " +
+                    "must be enabled.";
+          description
+                    "For EPL, CE-VLAN ID CoS Preservation must be enabled.";
+        }
+        must "(. != 'evpl') or ((. = 'evpl') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "all-to-one-bundling-enabled = 'true']) = 0))" {
+          error-message "For EVPL, All-to-One Bundling must be " +
+                    "disabled for all UNIs in the EVC UNI List.";
+          description
+                    "For EVPL, All-to-One Bundling must be disabled for " +
+                    "all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'evpl') or ((. = 'evpl') and " +
+                "((../evc/unicast-svc-frm-delivery != " +
+                "'unconditional') or " +
+                "(../evc/multicast-svc-frm-delivery != " +
+                "'unconditional') or " +
+                "(../evc/broadcast-svc-frm-delivery != " +
+                "'unconditional') or " +
+                "count(../evc/unis/uni" +
+                "[src-mac-addr-limit-enabled = 'true']) = 0))" {
+          error-message "For EVPL, Source MAC Address Limit must " +
+                    "be disabled for all UNIs in the EVC per " +
+                    "UNI List if all 3 -svc-frm-delivery values " +
+                    "are unconditional.";
+          description
+                    "For EVPL, Source MAC Address Limit must be disabled " +
+                    "for all UNIs in the EVC per UNI List if all " +
+                    "3 -svc-frm-delivery values are unconditional.";
+        }
+        must "(. != 'evpl') or ((. = 'evpl') and " +
+                "(../evc/evc-type = 'point-to-point'))" {
+          error-message "For EVPL, EVC Type must be Point-to-Point.";
+          description
+                    "For EVPL, EVC Type must be Point-to-Point.";
+        }
+        must "(. != 'eplan') or ((. = 'eplan') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "svc-mux-enabled = 'true']) = 0))" {
+          error-message "For EP-LAN, Service Multiplexing must " +
+                    "be disabled for all UNIs in the EVC UNI List.";
+          description
+                    "For EP-LAN, Service Multiplexing must be disabled " +
+                    "for all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'eplan') or ((. = 'eplan') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "bundling-enabled = 'true']) = 0))" {
+          error-message "For EP-LAN, Bundling must be disabled " +
+                    "for all UNIs in the EVC UNI List.";
+          description
+                    "For EP-LAN, Bundling must be disabled for all UNIs " +
+                    "in the EVC UNI List.";
+        }
+        must "(. != 'eplan') or ((. = 'eplan') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/" +
+                "mef-services:uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "all-to-one-bundling-enabled = 'false']) = 0))" {
+          error-message "For EP-LAN, All-to-One Bundling " +
+                    "must be enabled for all UNIs in the " +
+                    "EVC UNI List.";
+          description
+                    "For EP-LAN, All-to-One Bundling must be enabled " +
+                    "for all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'eplan') or ((. = 'eplan') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/" +
+                "mef-services:uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "max-evc-count != 1]) = 0))" {
+          error-message "For EP-LAN, Max EVC Count must be 1 " +
+                    "for all UNIs in the EVC UNI List.";
+          description
+                    "For EP-LAN, Max EVC Count must be 1 for all UNIs in " +
+                    "the EVC UNI List.";
+        }
+        must "(. != 'eplan') or ((. = 'eplan') and " +
+                "(../evc/evc-type = 'multipoint-to-multipoint'))" {
+          error-message "For EP-LAN, EVC Type must be " +
+                    "Multipoint-to-Multipoint.";
+          description
+                    "For EP-LAN, EVC Type must be " +
+                    "Multipoint-to-Multipoint.";
+        }
+        must "(. != 'eplan') or ((. = 'eplan') and " +
+                "(../evc/preserve-ce-vlan-id = 'true'))" {
+          error-message "For EP-LAN, CE-VLAN ID Preservation " +
+                    "must be enabled.";
+          description
+                    "For EP-LAN, CE-VLAN ID Preservation must be enabled.";
+        }
+        must "(. != 'eplan') or ((. = 'eplan') and " +
+                "(../evc/cos-preserve-ce-vlan-id = 'true'))" {
+          error-message "For EP-LAN, CE-VLAN ID CoS Preservation " +
+                    "must be enabled.";
+          description
+                    "For EP-LAN, CE-VLAN ID CoS Preservation must be " +
+                    "enabled.";
+        }
+        must "(. != 'evplan') or ((. = 'evplan') and " +
+                "(../evc/evc-type = 'multipoint-to-multipoint'))" {
+          error-message "For EVP-LAN, EVC Type must be " +
+                    "Multipoint-to-Multipoint.";
+          description
+                    "For EVP-LAN, EVC Type must be " +
+                    "Multipoint-to-Multipoint.";
+        }
+        must "(. != 'evplan') or ((. = 'evplan') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "all-to-one-bundling-enabled = 'true']) = 0))" {
+          error-message "For EVP-LAN, All-to-One Bundling must " +
+                    "be disabled for all UNIs in the EVC UNI List.";
+          description
+                    "For EVP-LAN, All-to-One Bundling must be disabled " +
+                    "for all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'eptree') or ((. = 'eptree') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "svc-mux-enabled = 'true']) = 0))" {
+          error-message "For EP-TREE, Service Multiplexing " +
+                    "must be disabled for all UNIs in the " +
+                    "EVC UNI List.";
+          description
+                    "For EP-TREE, Service Multiplexing must be disabled " +
+                    "for all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'eptree') or ((. = 'eptree') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "bundling-enabled = 'true']) = 0))" {
+          error-message "For EP-TREE, Bundling must be disabled " +
+                    "for all UNIs in the EVC UNI List.";
+          description
+                    "For EP-TREE, Bundling must be disabled for all UNIs " +
+                    "in the EVC UNI List.";
+        }
+        must "(. != 'eptree') or ((. = 'eptree') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/" +
+                "mef-services:uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "all-to-one-bundling-enabled = 'false']) = 0))" {
+          error-message "For EP-TREE, All-to-One Bundling must " +
+                    "be enabled for all UNIs in the EVC UNI List.";
+          description
+                    "For EP-TREE, All-to-One Bundling must be enabled " +
+                    "for all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'eptree') or ((. = 'eptree') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/" +
+                "mef-services:uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "max-evc-count != 1]) = 0))" {
+          error-message "For EP-TREE, Max EVC Count must be 1 " +
+                    "for all UNIs in the EVC UNI List.";
+          description
+                    "For EP-TREE, Max EVC Count must be 1 for all UNIs " +
+                    "in the EVC UNI List.";
+        }
+        must "(. != 'eptree') or ((. = 'eptree') and " +
+                "(../evc/evc-type = 'rooted-multipoint'))" {
+          error-message "For EP-TREE, EVC Type must be " +
+                    "Rooted-Multipoint.";
+          description
+                    "For EP-TREE, EVC Type must be Rooted-Multipoint.";
+        }
+        must "(. != 'eptree') or ((. = 'eptree') and " +
+                "(../evc/preserve-ce-vlan-id = 'true'))" {
+          error-message "For EP-TREE, CE-VLAN ID Preservation " +
+                    "must be enabled.";
+          description
+                    "For EP-TREE, CE-VLAN ID Preservation must be enabled.";
+        }
+        must "(. != 'eptree') or ((. = 'eptree') and " +
+                "(../evc/cos-preserve-ce-vlan-id = 'true'))" {
+          error-message "For EP-TREE, CE-VLAN ID " +
+                    "CoS Preservation must be enabled.";
+          description
+                    "For EP-TREE, CE-VLAN ID CoS Preservation must be " +
+                    "enabled.";
+        }
+        must "(. != 'evptree') or ((. = 'evptree') and " +
+                "(count(/mef-interfaces:mef-interfaces/" +
+                "mef-interfaces:unis/mef-interfaces:uni" +
+                "[mef-interfaces:uni-id = current()/../" +
+                "mef-services:evc/mef-services:unis/mef-services:" +
+                "uni/mef-services:uni-id]" +
+                "[mef-interfaces:uni-id/../mef-interfaces:" +
+                "all-to-one-bundling-enabled = 'true']) = 0))" {
+          error-message "For EVP-TREE, All-to-One Bundling " +
+                    "must be disabled for all UNIs in the EVC UNI List.";
+          description
+                    "For EVP-TREE, All-to-One Bundling must be disabled " +
+                    "for all UNIs in the EVC UNI List.";
+        }
+        must "(. != 'evptree') or ((. = 'evptree') and " +
+                "(../evc/evc-type = 'rooted-multipoint'))" {
+          error-message "For EVP-TREE, EVC Type must be " +
+                    "Rooted-Multipoint.";
+          description
+                    "For EVP-TREE, EVC Type must be Rooted-Multipoint.";
+        }
+        description
+                "The MEF Service Type.";
+      }
+      leaf user-label {
+        type mef-types:identifier45;
+        description
+                "This MEF user label is set by the user to a value " +
+                "that is easier to identify than the Service ID.";
+      }
+      leaf svc-entity {
+        type mef-types:service-entity-type;
+        default "evc";
+        description
+                "MEF Service Entity.";
+        reference "[MEF12.2] Table 3.";
+      }
+      leaf tenant-id {
+        type leafref {
+          path "/mef-global:mef-global/mef-global:tenants-instances/mef-global:tenant-list/mef-global:name";
+        }
+      }
+    }
+  }
+
+  augment "/mef-services:mef-services/mef-services:mef-service/mef-services:mef-service-choice/mef-services:evc-choice/mef-services:evc" {
+    ext:augment-identifier "evc-elan";
+    leaf elan-id {type string;}
+    list elan-ports {
+      key "port-id";
+      leaf port-id {type string;}
+    }
+  }
+
+  augment "/mef-services:mef-services/mef-services:mef-service/mef-services:mef-service-choice/mef-services:ipvc-choice/mef-services:ipvc" {
+    ext:augment-identifier "ipvc-vpn";
+    leaf vpn-id {type string;}
+    list vpn-elans {
+      key "uni-id ip-uni-id";
+      leaf uni-id {type  mef-types:identifier45;}
+      leaf ip-uni-id {type  mef-types:identifier45;}
+      leaf elan-id {type string;}
+      leaf elan-port {type string;}
+      list subnets {
+        key "subnet";
+        leaf subnet {type string;}
+      }
+    }
+  }
+}
index d6e524559effa3946d91a57229109992ad335c95..7916fa8db0608da87862f394e8a26abddb537ad9 100644 (file)
@@ -83,7 +83,7 @@
       <version>${vpnservices.version}</version>
     </dependency>
     <dependency>
-      <groupId>${project.groupId}</groupId>
+      <groupId>org.opendaylight.unimgr</groupId>
       <artifactId>unimgr-legato-api</artifactId>
       <version>${project.version}</version>
     </dependency>
index 8be48f5e8baa8521d15d1d972f5a0df3c154122f..68ea369d431e5974ac3f4da18f752910ec54d958 100644 (file)
@@ -11,42 +11,51 @@ package org.opendaylight.unimgr.mef.netvirt;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
+
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.Evc;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.uni.EvcUniCeVlans;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.uni.evc.uni.ce.vlans.EvcUniCeVlan;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.EvcElan;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.EvcElanBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.ElanPorts;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.ElanPortsBuilder;
+
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.EvcType;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.EvcUniRoleType;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 
+import jline.internal.Log;
+
 public class EvcListener extends UnimgrDataTreeChangeListener<Evc> {
 
     private static final Logger log = LoggerFactory.getLogger(EvcListener.class);
     private ListenerRegistration<EvcListener> evcListenerRegistration;
+    private final IUniPortManager uniPortManager;
 
-    public EvcListener(final DataBroker dataBroker) {
+    public EvcListener(final DataBroker dataBroker, final UniPortManager uniPortManager) {
         super(dataBroker);
-
+        this.uniPortManager = uniPortManager;
         registerListener();
     }
 
     public void registerListener() {
         try {
             final DataTreeIdentifier<Evc> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
-                    MefUtils.getEvcInstanceIdentifier());
+                    MefServicesUtils.getEvcsInstanceIdentifier());
             evcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
             log.info("EvcDataTreeChangeListener created and registered");
         } catch (final Exception e) {
@@ -89,22 +98,18 @@ public class EvcListener extends UnimgrDataTreeChangeListener<Evc> {
             Evc data = newDataObject.getRootNode().getDataAfter();
             String instanceName = data.getEvcId().getValue();
             boolean isEtree = data.getEvcType() == EvcType.RootedMultipoint;
-            if (!data.isAdminStateEnabled()) {
-                log.info("add - evc {} AdminStateEnabled false", data.getEvcId().getValue());
-            } else {
-                log.info("Adding {} instance: {}", isEtree ? "etree" : "elan", instanceName);
+            InstanceIdentifier<Evc> evcId = newDataObject.getRootPath().getRootIdentifier();
+
+            synchronized (instanceName.intern()) {
                 NetvirtUtils.createElanInstance(dataBroker, instanceName, isEtree);
-            }
-            // Create interfaces
-            if (data.getUnis() == null) {
-                log.info("No UNI's in service {}, exiting", instanceName);
-                return;
-            }
-            for (Uni uni : data.getUnis().getUni()) {
-                if (!uni.isAdminStateEnabled()) {
-                    log.info("uni {} AdminStateEnabled false", uni.getUniId().getValue());
-                } else {
-                    createInterface(instanceName, uni, isEtree);
+
+                // Create interfaces
+                if (data.getUnis() == null) {
+                    log.info("No UNI's in service {}, exiting", instanceName);
+                    return;
+                }
+                for (Uni uni : data.getUnis().getUni()) {
+                    createUniElanInterfaces(evcId, instanceName, uni, isEtree);
                 }
             }
         } catch (final Exception e) {
@@ -112,58 +117,64 @@ public class EvcListener extends UnimgrDataTreeChangeListener<Evc> {
         }
     }
 
+    private void removeEvc(DataTreeModification<Evc> removedDataObject) {
+        try {
+            Evc data = removedDataObject.getRootNode().getDataBefore();
+            InstanceIdentifier<Evc> evcId = removedDataObject.getRootPath().getRootIdentifier();
+            List<Uni> uniToRemove = data.getUnis() != null && data.getUnis().getUni() != null
+                    ? data.getUnis().getUni() : Collections.emptyList();
+
+
+            synchronized (data.getEvcId().getValue().intern()) {
+                EvcElan evcElan = getOperEvcElan(evcId);
+                if (evcElan == null) {
+                    log.error("Evc {} has not been created as required. Nothing to remove", data.getEvcId().getValue());
+                }
+
+                String instanceName = evcElan.getElanId();
+
+                for (Uni uni : uniToRemove) {
+                    removeUniElanInterfaces(evcId, instanceName, uni);
+                }
+
+                log.info("Removing elan instance: " + instanceName);
+                NetvirtUtils.deleteElanInstance(dataBroker, instanceName);
+                removeOperEvcElan(evcId);
+            }
+        } catch (final Exception e) {
+            log.error("Remove evc failed !", e);
+        }
+    }
+
     private void updateEvc(DataTreeModification<Evc> modifiedDataObject) {
+        InstanceIdentifier<Evc> evcId = modifiedDataObject.getRootPath().getRootIdentifier();
+
         try {
             Evc original = modifiedDataObject.getRootNode().getDataBefore();
             Evc update = modifiedDataObject.getRootNode().getDataAfter();
 
-            String instanceName = original.getEvcId().getValue();
-            boolean isEtree = update.getEvcType() == EvcType.RootedMultipoint;
+            List<Uni> originalUni = original.getUnis() != null && original.getUnis().getUni() != null
+                    ? original.getUnis().getUni() : Collections.emptyList();
+            List<Uni> updateUni = update.getUnis() != null && update.getUnis().getUni() != null
+                    ? update.getUnis().getUni() : Collections.emptyList();
 
-            if (!update.isAdminStateEnabled()) {
-                log.info("update - evc {} AdminStateEnabled false", update.getEvcId().getValue());
-            }
-            log.info("Updating {} instance: {}", isEtree ? "etree" : "elan", instanceName);
+            synchronized (original.getEvcId().getValue().intern()) {
 
-            List<Uni> originalUni = original.getUnis() != null ? original.getUnis().getUni() : Collections.emptyList();
-            if (update == null || update.getUnis() == null) {
-                log.info("update uni is null");
-            }
-            List<Uni> updateUni = update.getUnis().getUni();
-            if (updateUni != null && !updateUni.isEmpty()) {
-                List<Uni> existingClonedUni = new ArrayList<>();
-                if (originalUni != null && !originalUni.isEmpty()) {
-                    existingClonedUni.addAll(0, originalUni);
-                    originalUni.removeAll(updateUni);
-                    updateUni.removeAll(existingClonedUni);
-                    // removing the Uni which are not presented in the updated
-                    // List
-                    for (Uni uni : originalUni) {
-                        if (!uni.isAdminStateEnabled()) {
-                            log.info("uni {} AdminStateEnabled false", uni.getUniId().getValue());
-                        } else {
-                            removeElanInterface(instanceName, uni);
-                        }
-                    }
-                }
+                String instanceName = original.getEvcId().getValue();
+                boolean isEtree = update.getEvcType() == EvcType.RootedMultipoint;
+                log.info("Updating {} instance: {}", isEtree ? "etree" : "elan", instanceName);
 
-                // Adding the new Uni which are presented in the updated List
-                if (updateUni.size() > 0) {
-                    for (Uni uni : updateUni) {
-                        if (!uni.isAdminStateEnabled()) {
-                            log.info("uni {} AdminStateEnabled false", uni.getUniId().getValue());
-                        } else {
-                            createInterface(instanceName, uni, isEtree);
-                        }
-                    }
+                // Changed Uni will be deleted / recreated
+                List<Uni> uniToRemove = new ArrayList<>(originalUni);
+                uniToRemove.removeAll(updateUni);
+                for (Uni uni : uniToRemove) {
+                    removeUniElanInterfaces(evcId, instanceName, uni);
                 }
-            } else if (originalUni != null && !originalUni.isEmpty()) {
-                for (Uni uni : originalUni) {
-                    if (!uni.isAdminStateEnabled()) {
-                        log.info("uni {} AdminStateEnabled false", uni.getUniId().getValue());
-                    } else {
-                        removeElanInterface(instanceName, uni);
-                    }
+
+                List<Uni> uniToCreate = new ArrayList<>(updateUni);
+                uniToCreate.removeAll(originalUni);
+                for (Uni uni : uniToCreate) {
+                    createUniElanInterfaces(evcId, instanceName, uni, isEtree);
                 }
             }
         } catch (final Exception e) {
@@ -171,51 +182,103 @@ public class EvcListener extends UnimgrDataTreeChangeListener<Evc> {
         }
     }
 
-    private void removeEvc(DataTreeModification<Evc> removedDataObject) {
-        try {
-            Evc data = removedDataObject.getRootNode().getDataBefore();
-            if (!data.isAdminStateEnabled()) {
-                log.info("remove - evc {} AdminStateEnabled false", data.getEvcId().getValue());
-            }
+    private void createUniElanInterfaces(InstanceIdentifier<Evc> evcId, String instanceName, Uni uni, boolean isEtree) {
+        EvcUniRoleType role = uni.getRole();
+        EvcUniCeVlans evcUniCeVlans = uni.getEvcUniCeVlans();
 
-            String instanceName = data.getEvcId().getValue();
+        List<EvcUniCeVlan> evcUniCeVlan = evcUniCeVlans != null && evcUniCeVlans.getEvcUniCeVlan() != null
+                && !evcUniCeVlans.getEvcUniCeVlan().isEmpty() ? evcUniCeVlans.getEvcUniCeVlan()
+                        : Collections.emptyList();
 
-            for (Uni uni : data.getUnis().getUni()) {
-                if (!uni.isAdminStateEnabled()) {
-                    log.info("uni {} AdminStateEnabled false", uni.getUniId().getValue());
-                } else {
+        for (EvcUniCeVlan ceVlan : evcUniCeVlan) {
+            Long vlan = safeCastVlan(ceVlan.getVid());
+            uniPortManager.addCeVlan(uni.getUniId().getValue(), vlan);
+        }
 
-                    removeElanInterface(instanceName, uni);
+        if (evcUniCeVlan.isEmpty()) {
+            String interfaceName = uniPortManager.getUniVlanInterface(uni.getUniId().getValue(), Long.valueOf(0));
+            if (isOperEvcElanPort(evcId, interfaceName)) {
+                log.info("elan interface for elan {} vlan {} interface {} exists already", instanceName, 0,
+                        interfaceName);
+                return;
+            }
+            log.info("Creting elan interface for elan {} vlan {} interface {}", instanceName, 0, interfaceName);
+            NetvirtUtils.createElanInterface(dataBroker, instanceName, interfaceName, roleToInterfaceType(role),
+                    isEtree);
+            setOperEvcElanPort(evcId, instanceName, interfaceName);
+        } else {
+            for (EvcUniCeVlan ceVlan : evcUniCeVlan) {
+                Long vlan = safeCastVlan(ceVlan.getVid());
+                String interfaceName = uniPortManager.getUniVlanInterface(uni.getUniId().getValue(), vlan);
+                if (isOperEvcElanPort(evcId, interfaceName)) {
+                    log.info("elan interface for elan {} vlan {} interface {} exists already", instanceName, 0,
+                            interfaceName);
+                    return;
                 }
+                log.info("Creting elan interface for elan {} vlan {} interface {}", instanceName, 0, interfaceName);
+                NetvirtUtils.createElanInterface(dataBroker, instanceName, interfaceName, roleToInterfaceType(role),
+                        isEtree);
+                setOperEvcElanPort(evcId, instanceName, interfaceName);
             }
-
-            log.info("Removing elan instance: " + instanceName);
-            NetvirtUtils.deleteElanInstance(dataBroker, instanceName);
-        } catch (final Exception e) {
-            log.error("Remove evc failed !", e);
         }
     }
 
-    private void createInterface(String instanceName, Uni uni, boolean isEtree) {
-        EvcUniUtils.addUni(dataBroker, uni);
-        String interfaceName = uni.getUniId().getValue();
-        EvcUniRoleType role = uni.getRole();
+    private void removeUniElanInterfaces(InstanceIdentifier<Evc> evcId, String instanceName, Uni uni) {
         EvcUniCeVlans evcUniCeVlans = uni.getEvcUniCeVlans();
 
-        if (evcUniCeVlans != null && evcUniCeVlans.getEvcUniCeVlan() != null
-                && !evcUniCeVlans.getEvcUniCeVlan().isEmpty()) {
-            for (EvcUniCeVlan x : evcUniCeVlans.getEvcUniCeVlan()) {
-                interfaceName = NetvirtUtils.getInterfaceNameForVlan(interfaceName, x.getVid().toString());
+        List<EvcUniCeVlan> evcUniCeVlan = evcUniCeVlans != null && evcUniCeVlans.getEvcUniCeVlan() != null
+                && !evcUniCeVlans.getEvcUniCeVlan().isEmpty() ? evcUniCeVlans.getEvcUniCeVlan()
+                        : Collections.emptyList();
 
-                NetvirtUtils.createInterface(dataBroker, instanceName, interfaceName, RoleToInterfaceType(role),
-                        isEtree);
+        for (EvcUniCeVlan ceVlan : evcUniCeVlan) {
+            Long vlan = safeCastVlan(ceVlan.getVid());
+            uniPortManager.removeCeVlan(uni.getUniId().getValue(), vlan);
+        }
+
+        if (evcUniCeVlan.isEmpty()) {
+            String interfaceName = uniPortManager.getUniVlanInterface(uni.getUniId().getValue(), Long.valueOf(0));
+            if (!isOperEvcElanPort(evcId, interfaceName)) {
+                log.info("elan interface for elan {} vlan {} is not operational, nothing to remove", instanceName, 0,
+                        interfaceName);
+                return;
             }
+            removeElanInterface(evcId, interfaceName);
         } else {
-            NetvirtUtils.createInterface(dataBroker, instanceName, interfaceName, RoleToInterfaceType(role), isEtree);
+            for (EvcUniCeVlan ceVlan : evcUniCeVlan) {
+                Long vlan = safeCastVlan(ceVlan.getVid());
+                String interfaceName = uniPortManager.getUniVlanInterface(uni.getUniId().getValue(), vlan);
+                if (!isOperEvcElanPort(evcId, interfaceName)) {
+                    log.info("elan interface for elan {} vlan {} is not operational, nothing to remove", instanceName,
+                            vlan, interfaceName);
+                    return;
+                }
+                removeElanInterface(evcId, interfaceName);
+            }
         }
     }
 
-    private static EtreeInterfaceType RoleToInterfaceType(EvcUniRoleType role) {
+    private void removeElanInterface(InstanceIdentifier<Evc> identifier, String interfaceName) {
+        log.info("Removing elan interface: " + interfaceName);
+        NetvirtUtils.deleteElanInterface(dataBroker, interfaceName);
+
+        EvcElan evcElan = getOperEvcElan(identifier);
+        if (evcElan == null) {
+            log.error("Removing non-operational Elan interface {}", interfaceName);
+        }
+        deleteOperEvcElanPort(identifier, interfaceName);
+    }
+
+    // Expected from API is Long
+    private Long safeCastVlan(Object vid) {
+        if (!(vid instanceof Long)) {
+            String errorMessage = String.format("vlan id %s cannot be cast to Long", vid);
+            log.error(errorMessage);
+            throw new UnsupportedOperationException(errorMessage);
+        }
+        return (Long) vid;
+    }
+
+    private static EtreeInterfaceType roleToInterfaceType(EvcUniRoleType role) {
         if (role == EvcUniRoleType.Root) {
             return EtreeInterfaceType.Root;
         } else {
@@ -223,23 +286,60 @@ public class EvcListener extends UnimgrDataTreeChangeListener<Evc> {
         }
     }
 
-    private void removeElanInterface(String instanceName, Uni uni) {
-        EvcUniUtils.removeUni(dataBroker, uni);
+    private EvcElan getOperEvcElan(InstanceIdentifier<Evc> identifier) {
+        InstanceIdentifier<EvcElan> path = identifier.augmentation(EvcElan.class);
+        Optional<EvcElan> evcElan = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
+        if (evcElan.isPresent()) {
+            return evcElan.get();
+        } else {
+            return null;
+        }
+    }
 
-        String uniId = uni.getUniId().getValue();
-        EvcUniCeVlans evcUniCeVlans = uni.getEvcUniCeVlans();
-        String interfaceName = uniId;
+    private void removeOperEvcElan(InstanceIdentifier<Evc> identifier) {
+        InstanceIdentifier<EvcElan> path = identifier.augmentation(EvcElan.class);
+        MdsalUtils.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
+    }
+
+    private boolean isOperEvcElanPort(InstanceIdentifier<Evc> identifier, String elanPort) {
+        EvcElan evcElan = getOperEvcElan(identifier);
+        if (evcElan == null || evcElan.getElanPorts() == null) {
+            return false;
+        }
+        List<ElanPorts> exPorts = evcElan.getElanPorts();
+        return exPorts.stream().anyMatch(p -> p.getPortId().equals(elanPort));
+    }
 
-        if (evcUniCeVlans != null && !evcUniCeVlans.getEvcUniCeVlan().isEmpty()) {
-            for (EvcUniCeVlan x : evcUniCeVlans.getEvcUniCeVlan()) {
+    private void setOperEvcElanPort(InstanceIdentifier<Evc> identifier, String elanName, String elanPort) {
+        InstanceIdentifier<EvcElan> path = identifier.augmentation(EvcElan.class);
+        EvcElan evcElan = getOperEvcElan(identifier);
+        EvcElanBuilder evcElanBuilder = evcElan != null ? new EvcElanBuilder(evcElan) : new EvcElanBuilder();
+        List<ElanPorts> exPorts =  evcElan != null && evcElan.getElanPorts() != null ? evcElan.getElanPorts() : new ArrayList<>();
+
+        ElanPortsBuilder portB = new ElanPortsBuilder();
+        portB.setPortId(elanPort);
+        exPorts.add(portB.build());
+        evcElanBuilder.setElanId(elanName);
+        evcElanBuilder.setElanPorts(exPorts);
+        MdsalUtils.write(dataBroker, LogicalDatastoreType.OPERATIONAL, path, evcElanBuilder.build());
+    }
 
-                interfaceName = NetvirtUtils.getInterfaceNameForVlan(uniId, x.getVid().toString());
-                log.info("Removing elan interface: " + interfaceName);
-                NetvirtUtils.deleteElanInterface(dataBroker, instanceName, interfaceName);
-            }
+    private void deleteOperEvcElanPort(InstanceIdentifier<Evc> identifier, String elanPort) {
+        InstanceIdentifier<EvcElan> path = identifier.augmentation(EvcElan.class);
+        EvcElan evcElan = getOperEvcElan(identifier);
+        EvcElanBuilder evcElanBuilder = null;
+        List<ElanPorts> exPorts = Collections.emptyList();
+        if (evcElan != null) {
+            evcElanBuilder = new EvcElanBuilder(evcElan);
+            exPorts = evcElan.getElanPorts() != null ? evcElan.getElanPorts() : Collections.emptyList();
         } else {
-            log.info("Removing elan interface: " + uniId);
-            NetvirtUtils.deleteElanInterface(dataBroker, instanceName, interfaceName);
+            Log.error("Deleting non-operational Elan port {}", elanPort);
+            return;
         }
+        List<ElanPorts> newList = exPorts.stream().filter(p -> !p.getPortId().equals(elanPort))
+                .collect(Collectors.toList());
+        evcElanBuilder.setElanPorts(newList);
+        MdsalUtils.write(dataBroker, LogicalDatastoreType.OPERATIONAL, path, evcElanBuilder.build());
     }
+
 }
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcUniUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/EvcUniUtils.java
deleted file mode 100644 (file)
index 0fde190..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.unimgr.mef.netvirt;
-
-import java.util.List;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayers;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.Links;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.uni.EvcUniCeVlans;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.uni.evc.uni.ce.vlans.EvcUniCeVlan;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
-public class EvcUniUtils {
-
-    private static final Logger logger = LoggerFactory.getLogger(EvcUniUtils.class);
-
-    public static Link getLink(DataBroker dataBroker, String uniId) {
-        Optional<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni> optional = MdsalUtils
-                .read(dataBroker, LogicalDatastoreType.CONFIGURATION, MefUtils.getUniInstanceIdentifier(uniId));
-
-        if (!optional.isPresent()) {
-            logger.error("A matching Uni doesn't exist for EvcUni {}", uniId);
-            return null;
-        }
-
-        org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = optional
-                .get();
-
-        PhysicalLayers physicalLayers = uni.getPhysicalLayers();
-        if (physicalLayers == null) {
-            logger.warn("Uni {} is missing PhysicalLayers", uniId);
-            return null;
-        }
-
-        Links links = physicalLayers.getLinks();
-        if (links == null || links.getLink() == null) {
-            logger.warn("Uni {} is has no links", uniId);
-            return null;
-        }
-
-        Link link = links.getLink().get(0);
-        return link;
-    }
-
-    public static void removeUni(DataBroker dataBroker, Uni data) {
-        try {
-            String uniId = data.getUniId().getValue();
-            WriteTransaction tx = createTransaction(dataBroker);
-
-            logger.info("Removing trunk {}", uniId);
-
-            NetvirtUtils.delete(uniId, tx);
-
-            Optional<List<EvcUniCeVlan>> ceVlansOptional = getCeVlans(data);
-            if (!ceVlansOptional.isPresent()) {
-                return;
-            }
-
-            removeTrunkMemberInterfaces(uniId, ceVlansOptional.get(), tx);
-            commitTransaction(tx);
-        } catch (final Exception e) {
-            logger.error("Remove uni failed !", e);
-        }
-    }
-
-    public static void addUni(DataBroker dataBroker, Uni data) {
-        try {
-            String uniId = data.getUniId().getValue();
-            WriteTransaction tx = createTransaction(dataBroker);
-            Link link = EvcUniUtils.getLink(dataBroker, uniId);
-            String interfaceName = uniId;
-            addTrunkInterface(interfaceName, MefUtils.getTrunkParentName(link), tx);
-
-            Optional<List<EvcUniCeVlan>> ceVlansOptional = getCeVlans(data);
-            if (ceVlansOptional.isPresent()) {
-                addTrunkMemberInterfaces(interfaceName, ceVlansOptional.get(), tx);
-            }
-
-            commitTransaction(tx);
-        } catch (final Exception e) {
-            logger.error("Add uni failed !", e);
-        }
-    }
-
-    private static void addTrunkInterface(String interfaceName, String parentInterfaceName, WriteTransaction tx) {
-        logger.info("Adding VLAN trunk {} ParentRef {}", interfaceName, parentInterfaceName);
-        Interface trunkInterface = NetvirtUtils.createTrunkInterface(interfaceName, parentInterfaceName);
-        NetvirtUtils.write(trunkInterface, tx);
-    }
-
-    private static void addTrunkMemberInterfaces(String parentInterfaceName, Iterable<EvcUniCeVlan> ceVlans,
-            WriteTransaction tx) {
-        for (EvcUniCeVlan ceVlan : ceVlans) {
-            Object vid = ceVlan.getVid();
-            if (!(vid instanceof Long)) {
-                String errorMessage = String.format("vlan id {} cannot be cast to Long", vid);
-                logger.error(errorMessage);
-                throw new UnsupportedOperationException(errorMessage);
-            }
-
-            Long vlanId = (Long) vid;
-            String interfaceName = NetvirtUtils.getInterfaceNameForVlan(parentInterfaceName, vlanId.toString());
-            logger.info("Adding VLAN trunk-member {} ParentRef {}", interfaceName, parentInterfaceName);
-            Interface trunkMemberInterface = NetvirtUtils.createTrunkMemberInterface(interfaceName, parentInterfaceName,
-                    vlanId.intValue());
-            NetvirtUtils.write(trunkMemberInterface, tx);
-        }
-    }
-
-    private static void removeTrunkMemberInterfaces(String parentInterfaceName, Iterable<EvcUniCeVlan> ceVlans,
-            WriteTransaction tx) {
-        for (EvcUniCeVlan ceVlan : ceVlans) {
-            Object vid = ceVlan.getVid();
-            if (!(vid instanceof Long)) {
-                String errorMessage = String.format("vlan id {} cannot be cast to Long", vid);
-                logger.error(errorMessage);
-                throw new UnsupportedOperationException(errorMessage);
-            }
-
-            Long vlanId = (Long) vid;
-            String interfaceName = NetvirtUtils.getInterfaceNameForVlan(parentInterfaceName, vlanId.toString());
-            logger.info("Removing VLAN trunk-member {}", interfaceName);
-            NetvirtUtils.delete(interfaceName, tx);
-        }
-    }
-
-    private static WriteTransaction createTransaction(DataBroker dataBroker) {
-        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
-        return tx;
-    }
-
-    private static void commitTransaction(WriteTransaction tx) {
-        try {
-            CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
-            futures.get();
-        } catch (Exception e) {
-            logger.error("failed to commit transaction due to exception ", e);
-        }
-    }
-
-    private static Optional<List<EvcUniCeVlan>> getCeVlans(Uni uni) {
-        EvcUniCeVlans ceVlans = uni.getEvcUniCeVlans();
-        if (ceVlans == null) {
-            return Optional.absent();
-        }
-
-        return Optional.fromNullable(ceVlans.getEvcUniCeVlan());
-    }
-}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/GwMacListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/GwMacListener.java
new file mode 100644 (file)
index 0000000..4e6b218
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GwMacListener extends UnimgrDataTreeChangeListener<VpnPortipToPort> implements IGwMacListener {
+    private static final Logger Log = LoggerFactory.getLogger(GwMacListener.class);
+    private ListenerRegistration<GwMacListener> gwMacListenerRegistration;
+    private final OdlArputilService arpUtilService;
+    private final ExecutorService retriesHandler;
+    private final Short sleepInterval;
+
+    private final ConcurrentHashMap<GwMacKey, GwMacValue> gwMacResolver;
+
+    public GwMacListener(final DataBroker dataBroker, final OdlArputilService arputilService, Short sleepInterval) {
+        super(dataBroker);
+        this.arpUtilService = arputilService;
+        this.gwMacResolver = new ConcurrentHashMap<>();
+        this.sleepInterval = sleepInterval;
+        retriesHandler = Executors.newSingleThreadExecutor();
+        registerListener();
+    }
+
+    public void registerListener() {
+        try {
+            final DataTreeIdentifier<VpnPortipToPort> dataTreeIid = new DataTreeIdentifier<>(
+                    LogicalDatastoreType.OPERATIONAL, NetvirtVpnUtils.getVpnPortipToPortIdentifier());
+            gwMacListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
+            startRetriesThread();
+            Log.info("GwMacListener created and registered");
+        } catch (final Exception e) {
+            Log.error("GwMacListener listener registration failed !", e);
+            throw new IllegalStateException("GwMacListener Listener failed.", e);
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        gwMacListenerRegistration.close();
+        retriesHandler.shutdown();
+        if (!retriesHandler.awaitTermination(10, TimeUnit.SECONDS)) {
+            retriesHandler.shutdownNow();
+        }
+    }
+
+    @Override
+    public void add(DataTreeModification<VpnPortipToPort> newDataObject) {
+        if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
+            VpnPortipToPort portIpToPort = newDataObject.getRootNode().getDataAfter();
+            updateMac(portIpToPort);
+        }
+    }
+
+    @Override
+    public void remove(DataTreeModification<VpnPortipToPort> removedDataObject) {
+    }
+
+    @Override
+    public void update(DataTreeModification<VpnPortipToPort> modifiedDataObject) {
+        if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
+            VpnPortipToPort portIpToPort = modifiedDataObject.getRootNode().getDataAfter();
+            updateMac(portIpToPort);
+        }
+    }
+
+    private void updateMac(VpnPortipToPort portIpToPort) {
+        String portName = portIpToPort.getPortName();
+        String macAddress = portIpToPort.getMacAddress();
+        String vpnName = portIpToPort.getVpnName();
+        String ipAddress = portIpToPort.getPortFixedip();
+        GwMacKey gwMacKey = new GwMacKey(vpnName, portName, ipAddress);
+
+        if (!gwMacResolver.containsKey(gwMacKey)) {
+            Log.debug("Ignoring MAC update for vpn {} port {} ip {}", vpnName, portName, ipAddress);
+            return;
+        }
+
+        if (macAddress != null && vpnName != null) {
+            Log.trace("Updating vpn {} port {} with IP {} MAC {}", vpnName, portName, ipAddress, macAddress);
+        }
+
+        if (gwMacResolver.get(gwMacKey).getGwMac() == null || !gwMacResolver.get(gwMacKey).getGwMac().equals(macAddress)) {
+            Log.info("Creating GW for vpn {} port {} ip {} MAC {}", vpnName, portName, ipAddress, macAddress);
+            NetvirtVpnUtils.createUpdateVpnInterface(dataBroker, vpnName, portName, gwMacResolver.get(gwMacKey).getSubnet(), macAddress,
+                    false, gwMacResolver.get(gwMacKey).getPortIp());
+
+            gwMacResolver.get(gwMacKey).setGwMac(macAddress);
+        }
+    }
+
+    @Override
+    public void resolveGwMac(String vpnName, String portName, IpAddress srcIpAddress, IpAddress dstIpAddress, String subnet) {
+        String dstIpAddressStr = NetvirtVpnUtils.ipAddressToString(dstIpAddress);
+        GwMacKey gwMacKey = new GwMacKey(vpnName, portName, dstIpAddressStr);
+
+        if (!gwMacResolver.containsKey(gwMacKey)) {
+            // check if IP was resolved already
+            gwMacResolver.putIfAbsent(gwMacKey, new GwMacValue(NetvirtVpnUtils.ipAddressToString(srcIpAddress), subnet));
+            VpnPortipToPort portIpToPort = NetvirtVpnUtils.getVpnPortFixedIp(dataBroker, vpnName, dstIpAddressStr);
+            if (portIpToPort != null) {
+                updateMac(portIpToPort);
+            }
+
+            Log.info("Starting GW mac resolution for vpn {} port {} GW ip {}", vpnName, portName, dstIpAddress);
+            NetvirtVpnUtils.sendArpRequest(arpUtilService, srcIpAddress, dstIpAddress, portName);
+        }
+    }
+
+    @Override
+    public void unResolveGwMac(String vpnName, String portName, IpAddress srcIpAddress, IpAddress dstIpAddress) {
+        String dstIpAddressStr = NetvirtVpnUtils.ipAddressToString(dstIpAddress);
+        GwMacKey gwMacKey = new GwMacKey(vpnName, portName, dstIpAddressStr);
+        if (gwMacResolver.containsKey(gwMacKey)) {
+            Log.info("Stopping GW mac resolution for vpn {} port {} GW ip {}", vpnName, portName, dstIpAddress);
+            gwMacResolver.remove(gwMacKey);
+        }
+    }
+
+    private void resolveRetry() {
+        gwMacResolver.forEach((k, v) -> {
+            if (v.getGwMac() == null) {
+                IpAddress dstIpAddress = new IpAddress(k.gwIp.toCharArray());
+                IpAddress srcIpAddress = new IpAddress(v.portIp.toCharArray());
+                Log.debug("Resending ARP for IP {} port {}", dstIpAddress, k.getGwIp());
+
+                NetvirtVpnUtils.sendArpRequest(arpUtilService, srcIpAddress, dstIpAddress, k.portId);
+            }
+        });
+    }
+
+    void startRetriesThread() {
+        retriesHandler.submit(() -> {
+            Thread t = Thread.currentThread();
+            t.setName("ResolveSubnetGW");
+            Log.info("ResolveSubnetGW: started {}", t.getName());
+            while (true) {
+                NetvirtUtils.safeSleep(sleepInterval);
+                resolveRetry();
+            }
+        });
+        Log.debug("Subnet GW Arp Retries");
+    }
+
+    public static class GwMacKey {
+        private final String vpId;
+        private final String portId;
+        private final String gwIp;
+
+        public GwMacKey(String vpId, String portId, String gwIp) {
+            this.vpId = vpId;
+            this.portId = portId;
+            this.gwIp = gwIp;
+        }
+
+        public String getGwIp() {
+            return gwIp;
+        }
+
+        public String getVpId() {
+            return vpId;
+        }
+
+        public String getPortId() {
+            return portId;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + (gwIp == null ? 0 : gwIp.hashCode());
+            result = prime * result + (portId == null ? 0 : portId.hashCode());
+            result = prime * result + (vpId == null ? 0 : vpId.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            GwMacKey other = (GwMacKey) obj;
+            if (gwIp == null) {
+                if (other.gwIp != null) {
+                    return false;
+                }
+            } else if (!gwIp.equals(other.gwIp)) {
+                return false;
+            }
+            if (portId == null) {
+                if (other.portId != null) {
+                    return false;
+                }
+            } else if (!portId.equals(other.portId)) {
+                return false;
+            }
+            if (vpId == null) {
+                if (other.vpId != null) {
+                    return false;
+                }
+            } else if (!vpId.equals(other.vpId)) {
+                return false;
+            }
+            return true;
+        }
+
+
+    }
+
+    public static class GwMacValue {
+        String portIp;
+        String subnet;
+        String gwMac;
+
+        public GwMacValue(String portIp, String subnet) {
+            this.portIp = portIp;
+            this.subnet = subnet;
+        }
+
+        public String getGwMac() {
+            return gwMac;
+        }
+
+        public void setGwMac(String gwMac) {
+            this.gwMac = gwMac;
+        }
+
+        public String getPortIp() {
+            return portIp;
+        }
+
+        public String getSubnet() {
+            return subnet;
+        }
+
+    }
+
+}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IGwMacListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IGwMacListener.java
new file mode 100644 (file)
index 0000000..4a083f9
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+
+public interface IGwMacListener {
+    // IpPrefix srcIpPrefix, IpAddress dstIpAddress, String interf
+    public void resolveGwMac (String vpnName, String portName, IpAddress srcIpAddress, IpAddress dstIpAddress, String subnet);
+
+    public void unResolveGwMac (String vpnName, String portName, IpAddress srcIpAddress, IpAddress dstIpAddress);
+
+}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/ISubnetManager.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/ISubnetManager.java
new file mode 100644 (file)
index 0000000..6b1b126
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface ISubnetManager {
+    public void assignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId);
+
+    public void unAssignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId);
+}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IUniPortManager.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IUniPortManager.java
new file mode 100644 (file)
index 0000000..270f01a
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import java.util.List;
+
+public interface IUniPortManager {
+
+    void updateOperUni(String uniId);
+
+    void removeUniPorts(String uniId);
+
+    void addCeVlan(String uniId, Long vlanId);
+
+    void removeCeVlan(String uniId, Long vlanId);
+
+    List<String> getUniVlanInterfaces(String uniId);
+
+    String getUniVlanInterface(String uniId, Long vlanId);
+
+}
index 181c4a40104a0a6578aada874d8ed629479aa105..de9d487cc7e7984344c45d1153287eb36d35690c 100644 (file)
@@ -9,43 +9,50 @@
 package org.opendaylight.unimgr.mef.netvirt;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.SubnetBuilder;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.ip.uni.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElans;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.unis.Uni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class IpvcListener extends UnimgrDataTreeChangeListener<Ipvc> {
     private static final Logger Log = LoggerFactory.getLogger(IpvcListener.class);
+    private final IUniPortManager uniPortManager;
+    private final ISubnetManager subnetManager;
     private ListenerRegistration<IpvcListener> ipvcListenerRegistration;
-    private final NotificationPublishService notificationPublishService;
-    private final OdlArputilService arpUtilService;
 
-    public IpvcListener(final DataBroker dataBroker, final NotificationPublishService notPublishService,
-            final OdlArputilService arputilService) {
+    public IpvcListener(final DataBroker dataBroker, final IUniPortManager uniPortManager,
+            final ISubnetManager subnetManager) {
         super(dataBroker);
-        this.notificationPublishService = notPublishService;
-        this.arpUtilService = arputilService;
+        this.uniPortManager = uniPortManager;
+        this.subnetManager = subnetManager;
+
         registerListener();
     }
 
     public void registerListener() {
         try {
             final DataTreeIdentifier<Ipvc> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
-                    MefUtils.getIpvcInstanceIdentifier());
+                    MefServicesUtils.getIpvcsInstanceIdentifier());
             ipvcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
             Log.info("IpvcDataTreeChangeListener created and registered");
         } catch (final Exception e) {
@@ -85,148 +92,262 @@ public class IpvcListener extends UnimgrDataTreeChangeListener<Ipvc> {
 
     private void addIpvc(DataTreeModification<Ipvc> newDataObject) {
         try {
-            Ipvc data = newDataObject.getRootNode().getDataAfter();
-            String instanceName = data.getIpvcId().getValue();
+            WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+            Ipvc ipvc = newDataObject.getRootNode().getDataAfter();
+            String instanceName = ipvc.getIpvcId().getValue();
             final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
+            InstanceIdentifier<Ipvc> ipvcId = newDataObject.getRootPath().getRootIdentifier();
+            List<Uni> unis = new ArrayList<>();
+            synchronized (vpnName.intern()) {
+                Log.info("Adding vpn instance: " + instanceName);
+                NetvirtVpnUtils.createVpnInstance(vpnName, tx);
+                MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, tx);
+                if (ipvc.getUnis() != null && ipvc.getUnis() != null) {
+                    unis = ipvc.getUnis().getUni();
+                }
+                Log.info("Number of UNI's: " + unis.size());
 
-            Log.info("Adding vpn instance: " + instanceName);
-            NetvirtVpnUtils.createVpnInstance(dataBroker, vpnName);
-            Log.info("Number of UNI's: " + data.getUnis().getUni().size());
-
-
-            // Create elan interfaces
-            for (Uni uni : data.getUnis().getUni()) {
-                createInterfaces(vpnName, uni);
+                // Create elan/vpn interfaces
+                for (Uni uni : unis) {
+                    createInterfaces(vpnName, uni, ipvcId, tx);
+                }
+                MdsalUtils.commitTransaction(tx);
+            }
+            for (Uni uni : unis) {
+                IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uni.getUniId(), uni.getIpUniId(),
+                        LogicalDatastoreType.CONFIGURATION);
+                createDirectSubnet(uni, ipUni);
+                subnetManager.assignIpUniNetworks(uni.getUniId(), ipUni.getIpUniId(), ipvcId);
             }
         } catch (final Exception e) {
             Log.error("Add ipvc failed !", e);
         }
     }
 
-    private void updateIpvc(DataTreeModification<Ipvc> modifiedDataObject) {
+    private void removeIpvc(DataTreeModification<Ipvc> removedDataObject) {
         try {
-            Ipvc original = modifiedDataObject.getRootNode().getDataBefore();
-            Ipvc update = modifiedDataObject.getRootNode().getDataAfter();
+            Ipvc ipvc = removedDataObject.getRootNode().getDataBefore();
+            InstanceIdentifier<Ipvc> ipvcId = removedDataObject.getRootPath().getRootIdentifier();
+            IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
+            if (operIpvcVpn == null) {
+                Log.error("Ipvc {} hasn't been created as required", ipvc.getIpvcId());
+                return;
+            }
+            String vpnName = operIpvcVpn.getVpnId();
+
+            synchronized (vpnName.intern()) {
+                // remove elan/vpn interfaces
+                // must be in different transactios
+                WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+                removeUni(ipvcId, operIpvcVpn, ipvc.getUnis().getUni(), tx);
+                MdsalUtils.commitTransaction(tx);
+                // Let to work for listeners
+                // TODO : change to listener
+                NetvirtUtils.safeSleep();
+
+                WriteTransaction txvpn = MdsalUtils.createTransaction(dataBroker);
+                NetvirtVpnUtils.removeVpnInstance(operIpvcVpn.getVpnId(), txvpn);
+                MefServicesUtils.removeOperIpvcVpn(ipvcId, txvpn);
+                MdsalUtils.commitTransaction(txvpn);
+            }
+        } catch (final Exception e) {
+            Log.error("Remove ipvc failed !", e);
+        }
+    }
 
-            String instanceName = original.getIpvcId().getValue();
-            final String vpnName = NetvirtVpnUtils.getUUidFromString(instanceName);
+    private void removeUni(InstanceIdentifier<Ipvc> ipvcId, IpvcVpn operIpvcVpn, List<Uni> uniToRemove,
+            WriteTransaction tx) {
+        if (uniToRemove == null) {
+            Log.trace("No UNI's to remove");
+        }
+        for (Uni uni : uniToRemove) {
+            Identifier45 uniId = uni.getUniId();
+            Identifier45 ipUniId = uni.getIpUniId();
+            IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uniId, ipUniId, LogicalDatastoreType.CONFIGURATION);
+            if (ipUni == null) {
+                String errorMessage = String.format("Couldn't find ipuni %s for uni %s", ipUniId, uniId);
+                Log.error(errorMessage);
+                throw new UnsupportedOperationException(errorMessage);
+            }
 
-            Log.info("Updating elan instance: " + instanceName);
+            removeDirectSubnet(uni, ipUni);
+            subnetManager.unAssignIpUniNetworks(uni.getUniId(), ipUni.getIpUniId(), ipvcId);
+            removeInterfaces(ipvcId, operIpvcVpn, uni, ipUni, tx);
+        }
+    }
 
-            if (original == null || original.getUnis() == null || original.getUnis().getUni() == null) {
-                addIpvc(modifiedDataObject);
+    private void updateIpvc(DataTreeModification<Ipvc> modifiedDataObject) {
+        try {
+            Ipvc origIpvc = modifiedDataObject.getRootNode().getDataBefore();
+            Ipvc updateIpvc = modifiedDataObject.getRootNode().getDataAfter();
+            InstanceIdentifier<Ipvc> ipvcId = modifiedDataObject.getRootPath().getRootIdentifier();
+            IpvcVpn operIpvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
+            if (operIpvcVpn == null) {
+                Log.error("Ipvc {} hasn't been created as required", origIpvc.getIpvcId());
                 return;
             }
-
-            List<Uni> originalUni = original.getUnis().getUni();
-            List<Uni> updateUni = update.getUnis().getUni();
-            if (updateUni != null && !updateUni.isEmpty()) {
-                List<Uni> existingClonedUni = new ArrayList<>();
-                if (originalUni != null && !originalUni.isEmpty()) {
-                    existingClonedUni.addAll(0, originalUni);
-                    originalUni.removeAll(updateUni);
-                    updateUni.removeAll(existingClonedUni);
-                    // removing the Uni which are not presented in the updated
-                    // List
-                    for (Uni uni : originalUni) {
-                        removeElanInterface(vpnName, uni);
-                    }
+            String vpnName = operIpvcVpn.getVpnId();
+
+            List<Uni> originalUni = origIpvc.getUnis() != null && origIpvc.getUnis().getUni() != null
+                    ? origIpvc.getUnis().getUni() : Collections.emptyList();
+            List<Uni> updateUni = updateIpvc.getUnis() != null && updateIpvc.getUnis().getUni() != null
+                    ? updateIpvc.getUnis().getUni() : Collections.emptyList();
+
+            synchronized (vpnName.intern()) {
+                WriteTransaction txRemove = MdsalUtils.createTransaction(dataBroker);
+                List<Uni> uniToRemove = new ArrayList<>(originalUni);
+                uniToRemove.removeAll(updateUni);
+                removeUni(ipvcId, operIpvcVpn, uniToRemove, txRemove);
+                MdsalUtils.commitTransaction(txRemove);
+
+                WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+                List<Uni> uniToCreate = new ArrayList<>(updateUni);
+                uniToCreate.removeAll(originalUni);
+                for (Uni uni : uniToCreate) {
+                    createInterfaces(vpnName, uni, ipvcId, tx);
                 }
+                MdsalUtils.commitTransaction(tx);
 
-                // Adding the new Uni which are presented in the updated List
-                if (updateUni.size() > 0) {
-                    for (Uni uni : updateUni) {
-                        createInterfaces(vpnName, uni);
-                    }
-                }
-            } else if (originalUni != null && !originalUni.isEmpty()) {
-                for (Uni uni : originalUni) {
-                    removeElanInterface(vpnName, uni);
+                for (Uni uni : uniToCreate) {
+                    IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uni.getUniId(), uni.getIpUniId(),
+                            LogicalDatastoreType.CONFIGURATION);
+                    createDirectSubnet(uni, ipUni);
+                    subnetManager.assignIpUniNetworks(uni.getUniId(), ipUni.getIpUniId(), ipvcId);
                 }
             }
+
         } catch (final Exception e) {
             Log.error("Update ipvc failed !", e);
         }
     }
 
-    private void removeIpvc(DataTreeModification<Ipvc> removedDataObject) {
-        try {
-            Ipvc data = removedDataObject.getRootNode().getDataBefore();
+    private void createInterfaces(String vpnName, Uni uniInService, InstanceIdentifier<Ipvc> ipvcId,
+            WriteTransaction tx) {
+        String uniId = uniInService.getUniId().getValue();
+        String ipUniId = uniInService.getIpUniId().getValue();
+        org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = MefInterfaceUtils
+                .getUni(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
+        if (uni == null) {
+            String errorMessage = String.format("Couldn't find uni %s for ipvc", uniId);
+            Log.error(errorMessage);
+            throw new UnsupportedOperationException(errorMessage);
+        }
+        IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, uniInService.getUniId(), uniInService.getIpUniId(),
+                LogicalDatastoreType.CONFIGURATION);
+        if (ipUni == null) {
+            String errorMessage = String.format("Couldn't find ipuni %s for uni %s", ipUniId, uniId);
+            Log.error(errorMessage);
+            throw new UnsupportedOperationException(errorMessage);
+        }
 
-            String instanceName = data.getIpvcId().getValue();
+        Long vlan = ipUni.getVlan() != null ? Long.valueOf(ipUni.getVlan().getValue()) : null;
+        String elanName = NetvirtVpnUtils.getElanNameForVpnPort(uniId);
+        String interfaceName = createElanInterface(vpnName, ipvcId, uniId, elanName, vlan, tx);
+        createVpnInterface(vpnName, uni, ipUni, interfaceName, tx);
+        MefServicesUtils.addOperIpvcVpnElan(ipvcId, vpnName, uniInService.getUniId(), uniInService.getIpUniId(),
+                elanName, interfaceName, null, tx);
+    }
 
-            for (Uni uni : data.getUnis().getUni()) {
-                removeElanInterface(instanceName, uni);
-            }
+    private String createElanInterface(String vpnName, InstanceIdentifier<Ipvc> ipvcId, String uniId, String elanName,
+            Long vlan, WriteTransaction tx) {
+        Log.info("Adding elan instance: " + elanName);
+        NetvirtUtils.updateElanInstance(elanName, tx);
 
-            Log.info("Removing elan instance: " + instanceName);
-            NetvirtUtils.deleteElanInstance(dataBroker, instanceName);
-        } catch (final Exception e) {
-            Log.error("Remove ipvc failed !", e);
+        Log.info("Added trunk interface for uni {} vlan: {}", uniId, vlan);
+        if (vlan != null) {
+            uniPortManager.addCeVlan(uniId, vlan);
         }
+        String interfaceName = uniPortManager.getUniVlanInterface(uniId, vlan);
+        if (interfaceName == null) {
+            String errorMessage = String.format("Couldn't create  uni %s vlan interface %s", uniId, vlan);
+            Log.error(errorMessage);
+            throw new UnsupportedOperationException(errorMessage);
+        }
+
+        Log.info("Adding elan interface: " + interfaceName);
+        NetvirtUtils.createElanInterface(elanName, interfaceName, EtreeInterfaceType.Root, false, tx);
+        return interfaceName;
+    }
+
+    private void createVpnInterface(String vpnName,
+            org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni,
+            IpUni ipUni, String interfaceName, WriteTransaction tx) {
+
+        Log.info("Adding vpn interface: " + interfaceName);
+        NetvirtVpnUtils.createUpdateVpnInterface(vpnName, interfaceName, ipUni.getIpAddress(),
+                uni.getMacAddress().getValue(), true, null, tx);
+        NetvirtVpnUtils.createVpnPortFixedIp(vpnName, interfaceName, ipUni.getIpAddress(), uni.getMacAddress(), tx);
+        Log.info("Finished working on vpn instance: " + vpnName);
     }
 
-    private void createInterfaces(Ipvc ipvc, Uni uni) {
-        String instanceName = ipvc.getIpvcId().getValue();
-        createInterfaces(instanceName, uni);
+    private void createDirectSubnet(Uni uni, IpUni ipUni) {
+        IpPrefix uniIpPrefix = ipUni.getIpAddress();
+        String subnetIp = NetvirtVpnUtils.getSubnetFromPrefix(uniIpPrefix);
+        IpPrefix subnetPrefix = new IpPrefix(new Ipv4Prefix(subnetIp));
+        InstanceIdentifier<Subnet> path = MefInterfaceUtils.getSubnetInstanceIdentifier(uni.getUniId(),
+                ipUni.getIpUniId(), subnetPrefix);
+        SubnetBuilder subnet = new SubnetBuilder();
+        subnet.setUniId(uni.getUniId());
+        subnet.setIpUniId(ipUni.getIpUniId());
+        subnet.setSubnet(subnetPrefix);
+        MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, path, subnet.build());
     }
 
-    private void createInterfaces(String vpnName, Uni uniInService) {
+    private void removeInterfaces(InstanceIdentifier<Ipvc> ipvcId, IpvcVpn ipvcVpn, Uni uniInService, IpUni ipUni,
+            WriteTransaction tx) {
         String uniId = uniInService.getUniId().getValue();
-        String ipUniId = uniInService.getIpUniId().getValue();
+        org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = MefInterfaceUtils
+                .getUni(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
+        if (uni == null) {
+            String errorMessage = String.format("Couldn't find uni %s for ipvc", uniId);
+            Log.error(errorMessage);
+            throw new UnsupportedOperationException(errorMessage);
+        }
 
-        Log.info("Adding/updating elan instance: " + uniId);
+        String vpnName = ipvcVpn.getVpnId();
 
-        org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni = IpvcUniUtils
-                .getUni(dataBroker, uniId);
-        if (uni == null) {
-            Log.error("Couldn't find uni {} for ipvc-uni", uniId);
-            throw new UnsupportedOperationException();
+        VpnElans vpnElans = MefServicesUtils.findVpnElanForNetwork(new Identifier45(uniId), ipUni.getIpUniId(),
+                ipvcVpn);
+        if (vpnElans == null) {
+            Log.error("Trying to remome non-operational vpn/elan for Uni {} Ip-UNi {}", uniId, ipUni.getIpUniId());
         }
-        IpUni ipUni = IpvcUniUtils.getIpUni(dataBroker, uniId, ipUniId);
-        Integer vlan = ipUni.getVlan() != null ? ipUni.getVlan().getValue() : null;
 
-        String elanName = NetvirtVpnUtils.getElanNameForVpnPort(uniId);
-        Log.info("Adding elan instance: " + elanName);
-        NetvirtUtils.updateElanInstance(dataBroker, elanName);
+        NetvirtVpnUtils.removeVpnInterfaceAdjacencies(dataBroker, vpnName, vpnElans.getElanPort());
+        // TODO : change to listener
+        NetvirtUtils.safeSleep();
+        removeElan(vpnElans, uniId, ipUni, tx);
+        removeVpnInterface(vpnName, vpnElans, uniId, ipUni, tx);
+        MefServicesUtils.removeOperIpvcElan(dataBroker, ipvcId, ipvcVpn.getVpnId(), uniInService.getUniId(),
+                uniInService.getIpUniId(), vpnElans.getElanId(), vpnElans.getElanPort());
+    }
 
-        String interfaceName = NetvirtVpnUtils.getInterfaceNameForVlan(ipUniId, vlan);
-        Log.info("Adding trunk interface: " + interfaceName);
-        IpvcUniUtils.addUni(dataBroker, uniInService, interfaceName, vlan);
+    private void removeElan(VpnElans vpnElans, String uniId, IpUni ipUni, WriteTransaction tx) {
+        Long vlan = ipUni.getVlan() != null ? Long.valueOf(ipUni.getVlan().getValue()) : 0;
+        Log.info("Removing trunk interface for uni {} vlan: {}", uniId, vlan);
+        uniPortManager.removeCeVlan(uniId, vlan);
 
-        Log.info("Adding elan interface: " + interfaceName);
-        NetvirtUtils.createInterface(dataBroker, elanName, interfaceName, EtreeInterfaceType.Root, false);
+        String elanName = vpnElans.getElanId();
+        String interfaceName = vpnElans.getElanPort();
 
-        Log.info("Adding vpn interface: " + interfaceName);
-        NetvirtVpnUtils.createUpdateVpnInterface(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
-                uni.getMacAddress(), true, null);
-        NetvirtVpnUtils.createVpnPortFixedIp(dataBroker, vpnName, interfaceName, ipUni.getIpAddress(),
-                uni.getMacAddress());
-
-        Log.info("Adding connected network for interface : " + interfaceName);
-        NetvirtVpnUtils.addDirectSubnetToVpn(dataBroker, notificationPublishService, vpnName, elanName,
-                ipUni.getIpAddress(), interfaceName);
-
-        if (ipUni != null && ipUni.getSubnets() != null && ipUni.getSubnets().getSubnet() != null) {
-            for (Subnet subnet : ipUni.getSubnets().getSubnet()) {
-                Log.info("Resolving MAC address for gateway: " + subnet.getGateway());
-                MacAddress gwMacAddress = NetvirtVpnUtils.resolveGwMac(dataBroker, arpUtilService, vpnName,
-                        ipUni.getIpAddress(), subnet.getGateway(), interfaceName); // trunk
-                if (gwMacAddress == null) {
-                    continue;
-                }
-                Log.info("update vpn interface: " + interfaceName);
-                NetvirtVpnUtils.createUpdateVpnInterface(dataBroker, vpnName, interfaceName, subnet.getSubnet(),
-                        gwMacAddress, false, ipUni.getIpAddress());
-            }
-        }
-        Log.info("Finished working on elan instance: " + uniId);
+        Log.info("Removing elan instance {} and interface {}: ", elanName, interfaceName);
+        NetvirtUtils.deleteElanInterface(interfaceName, tx);
+        NetvirtUtils.deleteElanInstance(elanName, tx);
+    }
+
+    private void removeVpnInterface(String vpnName, VpnElans vpnElans, String uniId, IpUni ipUni, WriteTransaction tx) {
+        String interfaceName = vpnElans.getElanPort();
+        Log.info("Removing vpn interface: " + interfaceName);
+        NetvirtVpnUtils.removeVpnInterface(interfaceName, tx);
+        NetvirtVpnUtils.removeVpnPortFixedIp(vpnName, ipUni.getIpAddress(), tx);
+        Log.info("Finished working on vpn instance: " + vpnName);
     }
 
-    private void removeElanInterface(String instanceName, Uni uni) {
-        String uniId = uni.getIpUniId().getValue();
-        String interfaceName = uniId;
-        Log.info("Removing elan interface: " + uniId);
-        NetvirtUtils.deleteElanInterface(dataBroker, instanceName, interfaceName);
+    private void removeDirectSubnet(Uni uni, IpUni ipUni) {
+        IpPrefix uniIpPrefix = ipUni.getIpAddress();
+        String subnetIp = NetvirtVpnUtils.getSubnetFromPrefix(uniIpPrefix);
+        IpPrefix subnetPrefix = new IpPrefix(new Ipv4Prefix(subnetIp));
+        InstanceIdentifier<Subnet> path = MefInterfaceUtils.getSubnetInstanceIdentifier(uni.getUniId(),
+                ipUni.getIpUniId(), subnetPrefix);
+        MdsalUtils.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
     }
 }
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcUniUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/IpvcUniUtils.java
deleted file mode 100644 (file)
index 29357ab..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.unimgr.mef.netvirt;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.unis.Uni;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
-
-public class IpvcUniUtils {
-
-    private static final Logger logger = LoggerFactory.getLogger(IpvcUniUtils.class);
-
-    public static void addUni(DataBroker dataBroker, Uni data, String interfaceName, Integer vlanId) {
-        try {
-            String uniId = data.getUniId().getValue();
-            WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
-            Link link = EvcUniUtils.getLink(dataBroker, uniId);
-            addTrunkInterface(interfaceName, MefUtils.getTrunkParentName(link), vlanId, tx);
-            commitTransaction(tx);
-        } catch (final Exception e) {
-            logger.error("Add uni failed !", e);
-        }
-    }
-
-    private static void addTrunkInterface(String interfaceName, String parentInterfaceName, Integer vlanId,
-            WriteTransaction tx) {
-        logger.info("Adding VLAN trunk {} ParentRef {}", interfaceName, parentInterfaceName);
-        Interface trunkInterface = null;
-        if (vlanId != null) {
-            trunkInterface = NetvirtUtils.createTrunkMemberInterface(interfaceName, parentInterfaceName, vlanId);
-        } else {
-            trunkInterface = NetvirtUtils.createTrunkInterface(interfaceName, parentInterfaceName);
-        }
-        NetvirtUtils.writeInterface(trunkInterface, tx);
-    }
-
-    public static org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni getUni(
-            DataBroker dataBroker, String uniId) {
-        Optional<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni> optional = MdsalUtils
-                .read(dataBroker, LogicalDatastoreType.CONFIGURATION, MefUtils.getUniInstanceIdentifier(uniId));
-        if (!optional.isPresent()) {
-            logger.error("Couldn't find uni {} for ipvc-uni", uniId);
-            return null;
-        }
-        return optional.get();
-    }
-
-    public static IpUni getIpUni(DataBroker dataBroker, String uniId, String ipUniId) {
-        Optional<IpUni> optional = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                MefUtils.getIpUniInstanceIdentifier(uniId, ipUniId));
-
-        if (!optional.isPresent()) {
-            logger.error("A matching IpUni doesn't exist Uni {} IpUni {}", uniId, ipUniId);
-            return null;
-        }
-
-        return optional.get();
-    }
-
-    private static void commitTransaction(WriteTransaction tx) {
-        try {
-            CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
-            futures.get();
-        } catch (Exception e) {
-            logger.error("failed to commit transaction due to exception ", e);
-        }
-    }
-}
index f32df0408221b0d9a6545adb1257092e1846e13e..5b6b7deb98806a696f47adcfe5ce5e93358e629e 100644 (file)
@@ -98,4 +98,20 @@ public class MdsalUtils {
 
         return result;
     }
+
+
+    public static WriteTransaction createTransaction(DataBroker dataBroker) {
+        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        return tx;
+    }
+
+    public static void commitTransaction(WriteTransaction tx) {
+        try {
+            CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+            futures.get();
+        } catch (Exception e) {
+            logger.error("failed to commit transaction due to exception ", e);
+        }
+    }
+
 }
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefInterfaceUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefInterfaceUtils.java
new file mode 100644 (file)
index 0000000..19fd125
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.MefInterfaces;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.Subnets;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.Unis;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.SubnetKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.IpUnis;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayers;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUniKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.Links;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.MefTopology;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.Devices;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.Device;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.DeviceKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.Interfaces;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public final class MefInterfaceUtils {
+    private static final Logger logger = LoggerFactory.getLogger(MefInterfaceUtils.class);
+    public final static String VLAN_SEPARATOR = ".";
+    private final static String TRUNK_SUFFIX = "-trunk";
+
+    public static InstanceIdentifier<Interface> getDeviceInterfaceInstanceIdentifier(String deviceId,
+            String interfaceId) {
+        return InstanceIdentifier.builder(MefTopology.class).child(Devices.class)
+                .child(Device.class, new DeviceKey(new Identifier45(deviceId))).child(Interfaces.class)
+                .child(Interface.class, new InterfaceKey(new Identifier45(interfaceId))).build();
+    }
+
+    public static InstanceIdentifier<Uni> getUniInstanceIdentifier(String uniId) {
+        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
+                .child(Uni.class, new UniKey(new Identifier45(uniId))).build();
+    }
+
+    public static InstanceIdentifier<Uni> getUniListInstanceIdentifier() {
+        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class).child(Uni.class).build();
+    }
+
+    public static InstanceIdentifier<Link> getUniLinkInstanceIdentifier(String uniId, String deviceId,
+            String interfaceId) {
+        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
+                .child(Uni.class, new UniKey(new Identifier45(uniId))).child(PhysicalLayers.class).child(Links.class)
+                .child(Link.class, new LinkKey(new Identifier45(deviceId), interfaceId)).build();
+    }
+
+    private static InstanceIdentifier<IpUni> getIpUniInstanceIdentifier(Identifier45 uniId, Identifier45 ipUniId) {
+        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
+                .child(Uni.class, new UniKey(uniId)).child(IpUnis.class)
+                .child(IpUni.class, new IpUniKey(ipUniId)).build();
+    }
+
+    public static InstanceIdentifier<Subnets> getSubnetListInstanceIdentifier() {
+        return InstanceIdentifier.builder(MefInterfaces.class).child(Subnets.class).build();
+    }
+
+    public static InstanceIdentifier<Subnet> getSubnetsInstanceIdentifier() {
+        return InstanceIdentifier.builder(MefInterfaces.class).child(Subnets.class).child(Subnet.class).build();
+    }
+
+    public static InstanceIdentifier<Subnet> getSubnetInstanceIdentifier(Identifier45 uniId, Identifier45 ipUniId,
+            IpPrefix subnet) {
+        return InstanceIdentifier.builder(MefInterfaces.class).child(Subnets.class)
+
+                .child(Subnet.class, new SubnetKey(ipUniId, subnet, uniId)).build();
+    }
+
+    public static Link getLink(DataBroker dataBroker, String uniId, LogicalDatastoreType datastoreType) {
+        Uni uni = getUni(dataBroker, uniId, datastoreType);
+
+        if (uni == null) {
+            logger.error("A matching Uni doesn't exist for EvcUni {}", uniId);
+            return null;
+        }
+
+        PhysicalLayers physicalLayers = uni.getPhysicalLayers();
+        if (physicalLayers == null) {
+            logger.warn("Uni {} is missing PhysicalLayers", uniId);
+            return null;
+        }
+
+        Links links = physicalLayers.getLinks();
+        if (links == null || links.getLink() == null) {
+            logger.warn("Uni {} is has no links", uniId);
+            return null;
+        }
+
+        Link link = links.getLink().get(0);
+        return link;
+    }
+
+    public static Uni getUni(DataBroker dataBroker, String uniId, LogicalDatastoreType datastoreType) {
+        Optional<Uni> optional = MdsalUtils.read(dataBroker, datastoreType,
+                MefInterfaceUtils.getUniInstanceIdentifier(uniId));
+
+        if (!optional.isPresent()) {
+            logger.debug("A matching Uni doesn't exist {}", uniId);
+            return null;
+        }
+
+        return optional.get();
+    }
+
+    public static IpUni getIpUni(DataBroker dataBroker, Identifier45 uniId, Identifier45 ipUniId,
+            LogicalDatastoreType datastoreType) {
+        Optional<IpUni> optional = MdsalUtils.read(dataBroker, datastoreType,
+                MefInterfaceUtils.getIpUniInstanceIdentifier(uniId, ipUniId));
+
+        if (!optional.isPresent()) {
+            logger.error("A matching IpUni doesn't exist Uni {} IpUni {}", uniId, ipUniId);
+            return null;
+        }
+
+        return optional.get();
+    }
+
+    public static Interface getInterface(DataBroker dataBroker, String deviceId, String uniId,
+            LogicalDatastoreType datastoreType) {
+        InstanceIdentifier<Interface> interfacePath = MefInterfaceUtils.getDeviceInterfaceInstanceIdentifier(deviceId,
+                uniId);
+        Optional<Interface> optional = MdsalUtils.read(dataBroker, datastoreType, interfacePath);
+
+        if (!optional.isPresent()) {
+            logger.debug("A matching Uni doesn't exist {}", uniId);
+            return null;
+        }
+
+        return optional.get();
+    }
+
+    public static String getInterfaceNameForVlan(String interfaceName, Long vlan) {
+        final StringBuilder s = new StringBuilder();
+        s.append(interfaceName);
+        if (vlan != null) {
+            s.append(VLAN_SEPARATOR).append(vlan);
+        }
+        s.append(TRUNK_SUFFIX);
+
+        return getUUidFromString(s.toString());
+    }
+
+    private static String getUUidFromString(String key) {
+        return java.util.UUID.nameUUIDFromBytes(key.getBytes()).toString();
+    }
+
+    public static String getTrunkParentName(Link link) {
+        String interfaceName = link.getInterface().toString();
+        return interfaceName;
+    }
+
+    public static String getInterfaceName(Link link, String uniId) {
+        String device = link.getDevice().getValue();
+        return getDeviceInterfaceName(device, uniId);
+    }
+
+    public static String getDeviceInterfaceName(String deviceName, String interfaceName) {
+        return deviceName + IfmConstants.OF_URI_SEPARATOR + interfaceName;
+    }
+}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefServicesUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefServicesUtils.java
new file mode 100644 (file)
index 0000000..810d6c3
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpnBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefServiceKey;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.Evc;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.Unis;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElans;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElansBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.vpn.elans.Subnets;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.vpn.elans.SubnetsBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.RetailSvcIdType;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+
+public class MefServicesUtils {
+
+    public static InstanceIdentifier<Unis> getIpvcUnisInstanceIdentifier() {
+        return InstanceIdentifier.builder(MefServices.class).child(MefService.class).child(Ipvc.class).child(Unis.class)
+                .build();
+    }
+
+    public static InstanceIdentifier<Evc> getEvcsInstanceIdentifier() {
+        return getMefServiceInstanceIdentifier().child(Evc.class);
+    }
+
+    public static InstanceIdentifier<MefService> getMefServiceInstanceIdentifier() {
+        return InstanceIdentifier.create(MefServices.class).child(MefService.class);
+    }
+
+    public static InstanceIdentifier<MefServices> getMefServicesInstanceIdentifier() {
+        return InstanceIdentifier.create(MefServices.class);
+    }
+
+    public static InstanceIdentifier<Ipvc> getIpvcsInstanceIdentifier() {
+        return InstanceIdentifier.create(MefServices.class).child(MefService.class).child(Ipvc.class);
+    }
+
+    public static InstanceIdentifier<Ipvc> getIpvcsInstanceIdentifier(RetailSvcIdType svcId) {
+        return InstanceIdentifier.create(MefServices.class).child(MefService.class, new MefServiceKey(svcId))
+                .child(Ipvc.class);
+    }
+
+    public static VpnElans findVpnForNetwork(Subnet newSubnet, IpvcVpn ipvcVpn) {
+        return findVpnElanForNetwork(newSubnet.getUniId(), newSubnet.getIpUniId(), ipvcVpn);
+    }
+
+    public static VpnElans findVpnElanForNetwork(Identifier45 uniId, Identifier45 ipUniId, IpvcVpn ipvcVpn) {
+        List<VpnElans> vpnElans = ipvcVpn != null && ipvcVpn.getVpnElans() != null ? ipvcVpn.getVpnElans()
+                : Collections.emptyList();
+
+        for (VpnElans vpnElan : vpnElans) {
+            if (vpnElan.getUniId().equals(uniId) && vpnElan.getIpUniId().equals(ipUniId)) {
+                return vpnElan;
+            }
+        }
+        return null;
+    }
+
+    public static VpnElans findNetwork(Subnet newSubnet, VpnElans vpnElan) {
+        String subnetStr = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
+        return findNetwork(subnetStr, vpnElan);
+    }
+
+    public static VpnElans findNetwork(String newSubnet, VpnElans vpnElan) {
+        List<Subnets> subnets = vpnElan != null && vpnElan.getSubnets() != null ? vpnElan.getSubnets()
+                : Collections.emptyList();
+        if (subnets.stream().anyMatch((s) -> s.getSubnet().equals(newSubnet))) {
+            return vpnElan;
+        }
+        return null;
+    }
+
+
+    public static IpvcVpn getOperIpvcVpn(DataBroker dataBroker, InstanceIdentifier<Ipvc> identifier) {
+        InstanceIdentifier<IpvcVpn> path = identifier.augmentation(IpvcVpn.class);
+        Optional<IpvcVpn> ipvcVpn = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
+        if (ipvcVpn.isPresent()) {
+            return ipvcVpn.get();
+        } else {
+            return null;
+        }
+    }
+
+    public static void addOperIpvcVpnElan(InstanceIdentifier<Ipvc> identifier, String vpnId, WriteTransaction tx) {
+
+        synchronized (vpnId.intern()) {
+            InstanceIdentifier<IpvcVpn> path = identifier.augmentation(IpvcVpn.class);
+
+            IpvcVpnBuilder ipvcVpnBuilder = new IpvcVpnBuilder();
+            ipvcVpnBuilder.setVpnId(vpnId);
+
+            tx.merge(LogicalDatastoreType.OPERATIONAL, path, ipvcVpnBuilder.build(), true);
+        }
+    }
+
+    public static void addOperIpvcVpnElan(InstanceIdentifier<Ipvc> identifier, String vpnId, Identifier45 uniId,
+            Identifier45 ipUniId, String elanId, String elanPortId, List<String> newSubnets, WriteTransaction tx) {
+
+        synchronized (vpnId.intern()) {
+            InstanceIdentifier<IpvcVpn> path = identifier.augmentation(IpvcVpn.class);
+
+            IpvcVpnBuilder ipvcVpnBuilder = new IpvcVpnBuilder();
+            ipvcVpnBuilder.setVpnId(vpnId);
+
+            List<VpnElans> vpnElansEx = new ArrayList<>();
+            VpnElansBuilder vpnElans = new VpnElansBuilder();
+            vpnElans.setElanId(elanId);
+            vpnElans.setUniId(uniId);
+            vpnElans.setIpUniId(ipUniId);
+            vpnElans.setElanPort(elanPortId);
+            List<Subnets> subnets = new ArrayList<>();
+            if (newSubnets != null) {
+                newSubnets.forEach(s -> {
+                    SubnetsBuilder sb = new SubnetsBuilder();
+                    sb.setSubnet(s);
+                    subnets.add(sb.build());
+                });
+            }
+            vpnElans.setSubnets(subnets);
+            vpnElansEx.add(vpnElans.build());
+            ipvcVpnBuilder.setVpnElans(vpnElansEx);
+
+            tx.merge(LogicalDatastoreType.OPERATIONAL, path, ipvcVpnBuilder.build(), true);
+        }
+    }
+
+    public static void addOperIpvcVpnElan(DataBroker dataBroker, InstanceIdentifier<Ipvc> identifier, String vpnId,
+            Identifier45 uniId, Identifier45 ipUniId, String elanId, String elanPortId, List<String> newSubnets) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        addOperIpvcVpnElan(identifier, vpnId, uniId, ipUniId, elanId, elanPortId, newSubnets, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    public static void removeOperIpvcVpn(InstanceIdentifier<Ipvc> identifier, WriteTransaction tx) {
+        InstanceIdentifier<IpvcVpn> path = identifier.augmentation(IpvcVpn.class);
+        tx.delete(LogicalDatastoreType.OPERATIONAL, path);
+    }
+
+    public static void removeOperIpvcSubnet(DataBroker dataBroker, InstanceIdentifier<Ipvc> identifier, String vpnId,
+            Identifier45 uniId, Identifier45 ipUniId, String elanId, String elanPortId, String deleteSubnet) {
+        InstanceIdentifier<IpvcVpn> path = identifier.augmentation(IpvcVpn.class);
+        IpvcVpn ipvcVpn = getOperIpvcVpn(dataBroker, identifier);
+        if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
+            return;
+        }
+        IpvcVpnBuilder ipvcVpnBuilder = new IpvcVpnBuilder(ipvcVpn);
+        List<VpnElans> vpnElansEx = ipvcVpnBuilder.getVpnElans();
+
+        VpnElans vpnElans = findVpnElanForNetwork(uniId, ipUniId, ipvcVpn);
+        vpnElans = findNetwork(deleteSubnet, vpnElans);
+
+        if (vpnElans != null) {
+            vpnElansEx.remove(vpnElans);
+            VpnElansBuilder vpnElansB = new VpnElansBuilder(vpnElans);
+            List<Subnets> exSubnets = vpnElansB.getSubnets();
+            List<Subnets> newSubnets = exSubnets.stream().filter(s -> ! s.getSubnet().equals(deleteSubnet)).collect(Collectors.toList());
+            vpnElansB.setSubnets(newSubnets);
+            vpnElansEx.add(vpnElansB.build());
+        }
+        MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, path, ipvcVpnBuilder.build());
+    }
+
+    public static void removeOperIpvcElan(DataBroker dataBroker, InstanceIdentifier<Ipvc> identifier, String vpnId,
+            Identifier45 uniId, Identifier45 ipUniId, String elanId, String elanPortId) {
+        InstanceIdentifier<IpvcVpn> path = identifier.augmentation(IpvcVpn.class);
+        IpvcVpn ipvcVpn = getOperIpvcVpn(dataBroker, identifier);
+        if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
+            return;
+        }
+        IpvcVpnBuilder ipvcVpnBuilder = new IpvcVpnBuilder(ipvcVpn);
+        List<VpnElans> vpnElansEx = ipvcVpnBuilder.getVpnElans();
+
+        VpnElans vpnElans = findVpnElanForNetwork(uniId, ipUniId, ipvcVpn);
+        if (vpnElans != null) {
+            vpnElansEx.remove(vpnElans);
+        }
+        MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, path, ipvcVpnBuilder.build());
+    }
+
+}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/MefUtils.java
deleted file mode 100644 (file)
index 6790051..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.unimgr.mef.netvirt;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.MefInterfaces;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.Unis;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniKey;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.IpUnis;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayers;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUniKey;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.Links;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkKey;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefServiceKey;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.Evc;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.EvcBuilder;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.MefTopology;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.Devices;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.Device;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.DeviceKey;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.Interfaces;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.Interface;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.InterfaceKey;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.EvcIdType;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.EvcType;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.RetailSvcIdType;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-
-public final class MefUtils {
-    @SuppressWarnings("unused")
-    private static final Logger logger = LoggerFactory.getLogger(MefUtils.class);
-
-    public static InstanceIdentifier<Interface> getDeviceInterfaceInstanceIdentifier(String deviceId,
-            String interfaceId) {
-        return InstanceIdentifier.builder(MefTopology.class).child(Devices.class)
-                .child(Device.class, new DeviceKey(new Identifier45(deviceId))).child(Interfaces.class)
-                .child(Interface.class, new InterfaceKey(new Identifier45(interfaceId))).build();
-    }
-
-    public static InstanceIdentifier<Uni> getUniInstanceIdentifier(String uniId) {
-        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
-                .child(Uni.class, new UniKey(new Identifier45(uniId))).build();
-    }
-
-    public static InstanceIdentifier<Uni> getUniListInterfaceInstanceIdentifier() {
-        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class).child(Uni.class).build();
-    }
-
-    public static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.Unis> getUnisInstanceIdentifier(
-            String evcId) {
-        return InstanceIdentifier.builder(MefServices.class)
-                .child(MefService.class, new MefServiceKey(RetailSvcIdType.getDefaultInstance(evcId))).child(Evc.class)
-                .child(org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.Unis.class)
-                .build();
-    }
-
-    public static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni> getEvcUniInstanceIdentifier(
-            String uniId) {
-        return InstanceIdentifier.builder(MefServices.class).child(MefService.class).child(Evc.class)
-                .child(org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.Unis.class)
-                .child(org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni.class,
-                        new org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.UniKey(
-                                new Identifier45(uniId)))
-                .build();
-    }
-
-    public static InstanceIdentifier<Link> getUniLinkInstanceIdentifier(String uniId, String deviceId,
-            String interfaceId) {
-        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
-                .child(Uni.class, new UniKey(new Identifier45(uniId))).child(PhysicalLayers.class).child(Links.class)
-                .child(Link.class, new LinkKey(new Identifier45(deviceId), interfaceId)).build();
-    }
-
-    public static InstanceIdentifier<IpUni> getIpUniInstanceIdentifier(String uniId, String ipUniId) {
-        return InstanceIdentifier.builder(MefInterfaces.class).child(Unis.class)
-                .child(Uni.class, new UniKey(new Identifier45(uniId))).child(IpUnis.class)
-                .child(IpUni.class, new IpUniKey(new Identifier45(ipUniId))).build();
-    }
-
-    public static InstanceIdentifier<Evc> getEvcInstanceIdentifier() {
-        return getMefServiceInstanceIdentifier().child(Evc.class);
-    }
-
-    public static InstanceIdentifier<MefService> getMefServiceInstanceIdentifier() {
-        return InstanceIdentifier.create(MefServices.class).child(MefService.class);
-    }
-
-    public static InstanceIdentifier<MefService> getMefServiceInstanceIdentifier(RetailSvcIdType retailSvcIdType) {
-        return InstanceIdentifier.create(MefServices.class).child(MefService.class, new MefServiceKey(retailSvcIdType));
-    }
-
-    public static InstanceIdentifier<MefServices> getMefServicesInstanceIdentifier() {
-        return InstanceIdentifier.create(MefServices.class);
-    }
-
-    public static void createEvcInstance(DataBroker dataBroker, String instanceName) {
-        Evc einst = createEvcInstance(instanceName);
-
-        MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                getEvcInstanceInstanceIdentifier(instanceName), einst);
-    }
-
-    private static InstanceIdentifier<Evc> getEvcInstanceInstanceIdentifier(String instanceName) {
-        return InstanceIdentifier.builder(MefServices.class)
-                .child(MefService.class, new MefServiceKey(RetailSvcIdType.getDefaultInstance(instanceName)))
-                .child(Evc.class).build();
-    }
-
-    private static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni> getEvcUniInstanceIdentifier(
-            String serviceName, String uniId) {
-        return InstanceIdentifier.builder(MefServices.class)
-                .child(MefService.class, new MefServiceKey(RetailSvcIdType.getDefaultInstance(serviceName)))
-                .child(Evc.class)
-                .child(org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.Unis.class)
-                .child(org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni.class, //
-                        new org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.UniKey(
-                                Identifier45.getDefaultInstance(uniId)))
-                .build();
-    }
-
-    private static Evc createEvcInstance(String instanceName) {
-        EvcBuilder evcBuilder = new EvcBuilder();
-        evcBuilder.setAdminStateEnabled(false);
-        evcBuilder.setEvcId(EvcIdType.getDefaultInstance(instanceName));
-        evcBuilder.setEvcType(EvcType.MultipointToMultipoint);
-        return evcBuilder.build();
-    }
-
-    public static Boolean EvcExists(DataBroker dataBroker, String instanceName) {
-        Optional<Evc> evc = getEvc(dataBroker, instanceName);
-        return evc.isPresent();
-    }
-
-    public static Boolean isEvcAdminStateEnabled(DataBroker dataBroker, String instanceName) {
-        Optional<Evc> evc = getEvc(dataBroker, instanceName);
-        return evc.isPresent() && evc.get().isAdminStateEnabled();
-
-    }
-
-    public static Optional<Evc> getEvc(DataBroker dataBroker, String instanceName) {
-        Optional<Evc> evc = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                getEvcInstanceInstanceIdentifier(instanceName));
-        return evc;
-    }
-
-    public static Boolean EvcUniExists(DataBroker dataBroker, String instanceName, String uniId) {
-        logger.info("searching for uni id {} in service {}", uniId, instanceName);
-        Optional<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni> uni = MdsalUtils
-                .read(dataBroker, LogicalDatastoreType.CONFIGURATION, getEvcUniInstanceIdentifier(instanceName, uniId));
-        if (uni.isPresent()) {
-            logger.info("found uni");
-        } else {
-            logger.info("no uni");
-        }
-        return uni.isPresent();
-    }
-
-    public static String getTrunkParentName(Link link) {
-        String interfaceName = link.getInterface().toString();
-        return interfaceName;
-    }
-
-    public static String getInterfaceName(Link link, String uniId) {
-        String device = link.getDevice().getValue();
-        return NetvirtUtils.getDeviceInterfaceName(device, uniId);
-    }
-
-    public static InstanceIdentifier<Ipvc> getIpvcInstanceIdentifier() {
-        return InstanceIdentifier.create(MefServices.class).child(MefService.class).child(Ipvc.class);
-    }
-
-    public static String ipPrefixToString(IpPrefix ipAddress) {
-        if (ipAddress.getIpv4Prefix() != null) {
-            return ipAddress.getIpv4Prefix().getValue();
-        }
-
-        return ipAddress.getIpv6Prefix().getValue();
-    }
-
-    public static String ipAddressToString(IpAddress ipAddress) {
-        if (ipAddress.getIpv4Address() != null) {
-            return ipAddress.getIpv4Address().getValue();
-        }
-
-        return ipAddress.getIpv6Address().getValue();
-    }
-
-}
index 6fa79605691e84b0dea428198e9730b160063c54..10199cf227e9d7295a1e31082abd00b2580499ef 100644 (file)
@@ -11,18 +11,8 @@ package org.opendaylight.unimgr.mef.netvirt;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
-import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
@@ -44,7 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVxlan;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
 import org.slf4j.Logger;
@@ -55,8 +45,6 @@ import com.google.common.base.Optional;
 public class NetvirtUtils {
     private static final Logger logger = LoggerFactory.getLogger(NetvirtUtils.class);
 
-    public final static String VLAN_SEPARATOR = ".";
-
     public static void createElanInstance(DataBroker dataBroker, String instanceName, boolean isEtree) {
         ElanInstanceBuilder einstBuilder = createElanInstance(instanceName);
 
@@ -69,27 +57,17 @@ public class NetvirtUtils {
                 getElanInstanceInstanceIdentifier(instanceName), einstBuilder.build());
     }
 
-    public static void createElanInterface(DataBroker dataBroker, String instanceName, String interfaceName) {
-        ElanInterfaceBuilder einterfaceBuilder = createElanInterface(instanceName, interfaceName);
-
-        MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                getElanInterfaceInstanceIdentifier(interfaceName), einterfaceBuilder.build());
-    }
-
-    public static void createEtreeInterface(DataBroker dataBroker, String instanceName, String interfaceName,
-            EtreeInterfaceType type) {
-        ElanInterfaceBuilder einterfaceBuilder = createEtreeInterface(instanceName, interfaceName, type);
-
-        MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                getElanInterfaceInstanceIdentifier(interfaceName), einterfaceBuilder.build());
-    }
-
     public static void updateElanInstance(DataBroker dataBroker, String instanceName) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        updateElanInstance(instanceName, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
 
+    public static void updateElanInstance(String instanceName, WriteTransaction tx) {
         ElanInstanceBuilder einstBuilder = createElanInstance(instanceName);
 
-        MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                getElanInstanceInstanceIdentifier(instanceName), einstBuilder.build());
+        tx.merge(LogicalDatastoreType.CONFIGURATION, getElanInstanceInstanceIdentifier(instanceName),
+                einstBuilder.build());
     }
 
     public static void updateElanInterface(DataBroker dataBroker, String instanceName, String interfaceName) {
@@ -104,9 +82,18 @@ public class NetvirtUtils {
                 getElanInstanceInstanceIdentifier(instanceName));
     }
 
-    public static void deleteElanInterface(DataBroker dataBroker, String instanceName, String interfaceName) {
-        MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                getElanInterfaceInstanceIdentifier(interfaceName));
+    public static void deleteElanInstance(String instanceName, WriteTransaction tx) {
+        tx.delete(LogicalDatastoreType.CONFIGURATION, getElanInstanceInstanceIdentifier(instanceName));
+    }
+
+    public static void deleteElanInterface(DataBroker dataBroker, String interfaceName) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        deleteElanInterface(interfaceName, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    public static void deleteElanInterface(String interfaceName, WriteTransaction tx) {
+        tx.delete(LogicalDatastoreType.CONFIGURATION, getElanInterfaceInstanceIdentifier(interfaceName));
     }
 
     public static Interface createTrunkInterface(String interfaceName, String parentIfaceName) {
@@ -129,15 +116,12 @@ public class NetvirtUtils {
         return interfaceBuilder.build();
     }
 
-    public static String getInterfaceNameForVlan(String uniId, String vlanId) {
-        return uniId + VLAN_SEPARATOR + vlanId;
-    }
-
     private static ElanInstanceBuilder createElanInstance(String instanceName) {
         ElanInstanceBuilder einstBuilder = new ElanInstanceBuilder();
         einstBuilder.setElanInstanceName(instanceName);
         einstBuilder.setKey(new ElanInstanceKey(instanceName));
-        einstBuilder.setSegmentationId(Math.abs((long) instanceName.hashCode()));
+        einstBuilder.setSegmentationId(Long.valueOf(Math.abs((short) instanceName.hashCode())));
+        einstBuilder.setSegmentType(SegmentTypeVxlan.class);
         return einstBuilder;
     }
 
@@ -176,18 +160,6 @@ public class NetvirtUtils {
                 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
     }
 
-    public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getStateInterfaceIdentifier(
-            String interfaceName) {
-        InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder = InstanceIdentifier
-                .builder(InterfacesState.class)
-                .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
-                        new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
-                                interfaceName));
-        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder
-                .build();
-        return id;
-    }
-
     public static InstanceIdentifier<Interface> getInterfaceIdentifier(String interfaceName) {
         InstanceIdentifierBuilder<Interface> idBuilder = InstanceIdentifier.builder(Interfaces.class)
                 .child(Interface.class, new InterfaceKey(interfaceName));
@@ -199,83 +171,69 @@ public class NetvirtUtils {
         return MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
     }
 
-    public static String getDeviceInterfaceName(String deviceName, String interfaceName) {
-        return deviceName + IfmConstants.OF_URI_SEPARATOR + interfaceName;
-    }
-
     public static void writeInterface(Interface iface, WriteTransaction tx) {
         String interfaceName = iface.getName();
         InstanceIdentifier<Interface> interfaceIdentifier = createInterfaceIdentifier(interfaceName);
         tx.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, iface, true);
     }
 
-    public static void write(Interface iface, WriteTransaction tx) {
-        String interfaceName = iface.getName();
-        InstanceIdentifier<Interface> interfaceIdentifier = createInterfaceIdentifier(interfaceName);
-        tx.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, iface, true);
-    }
-
-    public static void delete(String interfaceName, WriteTransaction tx) {
+    public static void deleteInterface(String interfaceName, WriteTransaction tx) {
         InstanceIdentifier<Interface> interfaceIdentifier = createInterfaceIdentifier(interfaceName);
         tx.delete(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
     }
 
-    public static boolean waitForGeniusToUpdateInterface(DataBroker dataBroker, String interfaceName) {
-        int retries = 10;
-
-        while (retries > 0) {
-            Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> optional = MdsalUtils
-                    .read(dataBroker, LogicalDatastoreType.OPERATIONAL, getStateInterfaceIdentifier(interfaceName));
-
-            if (!optional.isPresent()) {
-                logger.info("State interface {} doesn't exist", interfaceName);
-            } else {
-                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateInterface = optional
-                        .get();
-
-                if (stateInterface.getIfIndex() != null) {
-                    logger.info("State interface configured with ifIndex {}", stateInterface.getIfIndex());
-
-                    // Wait a bit, because if we continue too soon this will not
-                    // work.
-                    try {
-                        Thread.sleep(1000);
-                    } catch (InterruptedException e) {
-                    }
-
-                    return true;
-                }
-            }
-
-            retries -= 1;
-            try {
-                Thread.sleep(1500);
-            } catch (InterruptedException e) {
-            }
-        }
-
-        return false;
-    }
-
     private static InstanceIdentifier<Interface> createInterfaceIdentifier(String interfaceName) {
         return InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName))
                 .build();
     }
 
-    public static void createInterface(DataBroker dataBroker, String instanceName, String interfaceName,
+    public static void createElanInterface(DataBroker dataBroker, String instanceName, String interfaceName,
             EtreeInterfaceType etreeInterfaceType, boolean isEtree) {
-        boolean result = NetvirtUtils.waitForGeniusToUpdateInterface(dataBroker, interfaceName);
-        if (!result) {
-            logger.error("State interface {} is not configured (missing ifIndex)", interfaceName);
-            return;
-        }
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        createElanInterface(instanceName, interfaceName, etreeInterfaceType, isEtree, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
 
+    public static void createElanInterface(String instanceName, String interfaceName,
+            EtreeInterfaceType etreeInterfaceType, boolean isEtree, WriteTransaction tx) {
         logger.info("Adding {} interface: {}", isEtree ? "etree" : "elan", interfaceName);
 
         if (isEtree) {
-            NetvirtUtils.createEtreeInterface(dataBroker, instanceName, interfaceName, etreeInterfaceType);
+            NetvirtUtils.createEtreeInterface(instanceName, interfaceName, etreeInterfaceType, tx);
         } else {
-            NetvirtUtils.createElanInterface(dataBroker, instanceName, interfaceName);
+            NetvirtUtils.createElanInterface(instanceName, interfaceName, tx);
         }
     }
+
+    private static void createEtreeInterface(String instanceName, String interfaceName, EtreeInterfaceType type,
+            WriteTransaction tx) {
+        ElanInterfaceBuilder einterfaceBuilder = createEtreeInterface(instanceName, interfaceName, type);
+
+        tx.put(LogicalDatastoreType.CONFIGURATION, getElanInterfaceInstanceIdentifier(interfaceName),
+                einterfaceBuilder.build());
+    }
+
+    private static void createElanInterface(String instanceName, String interfaceName, WriteTransaction tx) {
+        ElanInterfaceBuilder einterfaceBuilder = createElanInterface(instanceName, interfaceName);
+
+        tx.put(LogicalDatastoreType.CONFIGURATION, getElanInterfaceInstanceIdentifier(interfaceName),
+                einterfaceBuilder.build());
+    }
+
+    public static void safeSleep() {
+        try {
+            Thread.yield();
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+        }
+    }
+    public static void safeSleep(short sec) {
+        try {
+            Thread.yield();
+            Thread.sleep(1000*sec);
+        } catch (InterruptedException e) {
+        }
+    }
+
+
 }
index af8d77ee9179813accbd7821fc4273f0f1f59fb8..7d13db1b5edc46e9113b746c35c399804608e60d 100644 (file)
@@ -17,11 +17,13 @@ import org.apache.commons.net.util.SubnetUtils;
 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
@@ -45,9 +47,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adj
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
@@ -66,48 +70,84 @@ import com.google.common.base.Optional;
 public class NetvirtVpnUtils {
     private static final Logger logger = LoggerFactory.getLogger(NetvirtVpnUtils.class);
     private final static String ELAN_PREFIX = "elan.";
-    private final static String TRUNK_SUFFIX = "-trunk";
-    private final static String VLAN_SEPARATOR = ".";
     private final static String IP_ADDR_SUFFIX = "/32";
     private final static String IP_MUSK_SEPARATOR = "/";
-    private final static int MaxRetries = 10;
 
     public static void createVpnInstance(DataBroker dataBroker, String instanceName) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        createVpnInstance(instanceName, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    public static void createVpnInstance(String instanceName, WriteTransaction tx) {
         VpnInstanceBuilder builder = new VpnInstanceBuilder();
         builder.setVpnInstanceName(instanceName);
         Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder();
-        ipv4FamilyBuilder.setVpnTargets(new VpnTargetsBuilder().build());
+        VpnTargetsBuilder vpnTargetsB = new VpnTargetsBuilder();
+        vpnTargetsB.setVpnTarget(new ArrayList<VpnTarget>());
+        ipv4FamilyBuilder.setVpnTargets(vpnTargetsB.build());
+
         // WA till netvirt will allow creation of VPN without RD
         UUID vpnId = UUID.fromString(instanceName);
         String rd = String.valueOf(Math.abs(vpnId.getLeastSignificantBits()));
         ipv4FamilyBuilder.setRouteDistinguisher(rd);
         builder.setIpv4Family(ipv4FamilyBuilder.build());
 
-        MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                getVpnInstanceInstanceIdentifier(instanceName), builder.build());
+        tx.put(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName), builder.build());
+    }
+
+    public static void removeVpnInstance(String instanceName, WriteTransaction tx) {
+        tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName));
+    }
+
+    private static InstanceIdentifier<VpnInstance> getVpnInstanceInstanceIdentifier(String instanceName) {
+        return InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey(instanceName))
+                .build();
     }
 
     public static void createUpdateVpnInterface(DataBroker dataBroker, String vpnName, String interfaceName,
-            IpPrefix ifPrefix, MacAddress macAddress, boolean primary, IpPrefix gwIpAddress) {
+            String ifAddr, String macAddress, boolean primary, String gwIpAddress) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        createUpdateVpnInterface(vpnName, interfaceName, ifAddr, macAddress, primary, gwIpAddress, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    public static void createUpdateVpnInterface(String vpnName, String interfaceName, IpPrefix ifPrefix,
+            String macAddress, boolean primary, IpPrefix gwIpAddress, WriteTransaction tx) {
         synchronized (interfaceName.intern()) {
             String ipAddress = null;
             String nextHopIp = null;
             if (primary) {
-                ipAddress = getPrefixFromSubnet(MefUtils.ipPrefixToString(ifPrefix));
+                ipAddress = getAddressFromSubnet(ipPrefixToString(ifPrefix));
             } else {
-                ipAddress = MefUtils.ipPrefixToString(ifPrefix);
-                nextHopIp = getIpAddressFromPrefix(MefUtils.ipPrefixToString(gwIpAddress));
+                ipAddress = ipPrefixToString(ifPrefix);
+                nextHopIp = getIpAddressFromPrefix(ipPrefixToString(gwIpAddress));
             }
+            createUpdateVpnInterface(vpnName, interfaceName, ipAddress, macAddress, primary, nextHopIp, tx);
+        }
+    }
 
+    public static void createUpdateVpnInterface(String vpnName, String interfaceName, String ipAddress,
+            String  macAddress, boolean primary, String nextHopIp, WriteTransaction tx) {
+        synchronized (interfaceName.intern()) {
             Adjacencies adjancencies = buildInterfaceAdjacency(ipAddress, macAddress, primary, nextHopIp);
             VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, adjancencies);
 
-            MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                    getVpnInterfaceInstanceIdentifier(interfaceName), einterfaceBuilder.build());
+            tx.merge(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName),
+                    einterfaceBuilder.build());
         }
     }
 
-    private static Adjacencies buildInterfaceAdjacency(String ipAddress, MacAddress macAddress, boolean primary,
+    private static VpnInterfaceBuilder createVpnInterface(String instanceName, String interfaceName,
+            Adjacencies adjacencies) {
+        VpnInterfaceBuilder einterfaceBuilder = new VpnInterfaceBuilder();
+        einterfaceBuilder.setVpnInstanceName(instanceName);
+        einterfaceBuilder.setName(interfaceName);
+        einterfaceBuilder.addAugmentation(Adjacencies.class, adjacencies);
+        return einterfaceBuilder;
+    }
+
+    private static Adjacencies buildInterfaceAdjacency(String ipAddress, String macAddress, boolean primary,
             String nextHopIp) {
         AdjacenciesBuilder builder = new AdjacenciesBuilder();
         List<Adjacency> list = new ArrayList<>();
@@ -115,7 +155,7 @@ public class NetvirtVpnUtils {
         AdjacencyBuilder aBuilder = new AdjacencyBuilder();
         aBuilder.setIpAddress(ipAddress);
         if (macAddress != null) {
-            aBuilder.setMacAddress(macAddress.getValue());
+            aBuilder.setMacAddress(macAddress);
         }
         aBuilder.setPrimaryAdjacency(primary);
         if (nextHopIp != null) {
@@ -127,18 +167,46 @@ public class NetvirtVpnUtils {
         return builder.build();
     }
 
-    private static VpnInterfaceBuilder createVpnInterface(String instanceName, String interfaceName,
-            Adjacencies adjacencies) {
-        VpnInterfaceBuilder einterfaceBuilder = new VpnInterfaceBuilder();
-        einterfaceBuilder.setVpnInstanceName(instanceName);
-        einterfaceBuilder.setName(interfaceName);
-        einterfaceBuilder.addAugmentation(Adjacencies.class, adjacencies);
-        return einterfaceBuilder;
+    public static void removeVpnInterface(String interfaceName, WriteTransaction tx) {
+        synchronized (interfaceName.intern()) {
+            tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName));
+        }
     }
 
-    private static InstanceIdentifier<VpnInstance> getVpnInstanceInstanceIdentifier(String instanceName) {
-        return InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey(instanceName))
-                .build();
+    public static void removeVpnInterfaceAdjacencies(DataBroker dataBroker, String vpnName, String interfaceName) {
+        AdjacenciesBuilder builder = new AdjacenciesBuilder();
+        List<Adjacency> list = new ArrayList<>();
+        builder.setAdjacency(list);
+        VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, builder.build());
+
+        MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                getVpnInterfaceInstanceIdentifier(interfaceName), einterfaceBuilder.build());
+
+    }
+
+    public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpPrefix ifPrefix) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        String ipAddress = ipPrefixToString(ifPrefix);
+        removeVpnInterfaceAdjacency(interfaceName, ipAddress, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpAddress ifAddress) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        String ifAddressStr = getAddressFromSubnet(ipAddressToString(ifAddress));
+        removeVpnInterfaceAdjacency(interfaceName, ifAddressStr, tx);
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    private static void removeVpnInterfaceAdjacency(String interfaceName, String ipAddress, WriteTransaction tx) {
+        synchronized (interfaceName.intern()) {
+
+            InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class)
+                    .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).augmentation(Adjacencies.class)
+                    .child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
+
+            tx.delete(LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
+        }
     }
 
     private static InstanceIdentifier<VpnInterface> getVpnInterfaceInstanceIdentifier(String interfaceName) {
@@ -148,64 +216,47 @@ public class NetvirtVpnUtils {
 
     public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, IpPrefix ipAddress,
             MacAddress macAddress) {
-        String fixedIpPrefix = MefUtils.ipPrefixToString(ipAddress);
+        String fixedIpPrefix = ipPrefixToString(ipAddress);
         String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
-        createVpnPortFixedIp(dataBroker, vpnName, portName, fixedIp, macAddress);
+
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        createVpnPortFixedIp(vpnName, portName, fixedIp, macAddress, tx);
+        MdsalUtils.commitTransaction(tx);
     }
 
-    public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, IpAddress ipAddress,
-            MacAddress macAddress) {
-        String fixedIp = MefUtils.ipAddressToString(ipAddress);
-        createVpnPortFixedIp(dataBroker, vpnName, portName, fixedIp, macAddress);
+    public static void createVpnPortFixedIp(String vpnName, String portName, IpPrefix ipAddress, MacAddress macAddress,
+            WriteTransaction tx) {
+        String fixedIpPrefix = ipPrefixToString(ipAddress);
+        String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
+        createVpnPortFixedIp(vpnName, portName, fixedIp, macAddress, tx);
     }
 
-    public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, String fixedIp,
-            MacAddress macAddress) {
+    private static void createVpnPortFixedIp(String vpnName, String portName, String fixedIp, MacAddress macAddress,
+            WriteTransaction tx) {
         synchronized ((vpnName + fixedIp).intern()) {
-            InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
+            InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
             VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder()
                     .setKey(new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp)
                     .setPortName(portName).setMacAddress(macAddress.getValue()).setSubnetIp(true).setConfig(true)
                     .setLearnt(false);
-            MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, builder.build());
+            tx.put(LogicalDatastoreType.OPERATIONAL, id, builder.build());
             logger.debug(
                     "Interface to fixedIp added: {}, vpn {}, interface {}, mac {} added to " + "VpnPortipToPort DS",
                     fixedIp, vpnName, portName, macAddress);
         }
     }
 
-    static InstanceIdentifier<NetworkMap> buildNetworkMapIdentifier(Uuid networkId) {
-        InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
-                .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
-        return id;
-    }
-
-    private static void createSubnetToNetworkMapping(DataBroker dataBroker, Uuid subnetId, Uuid networkId) {
-        InstanceIdentifier<NetworkMap> networkMapIdentifier = buildNetworkMapIdentifier(networkId);
-        Optional<NetworkMap> optionalNetworkMap = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                networkMapIdentifier);
-        NetworkMapBuilder nwMapBuilder = null;
-        if (optionalNetworkMap.isPresent()) {
-            nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
-        } else {
-            nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
-            logger.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
-        }
-        List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
-        if (subnetIdList == null) {
-            subnetIdList = new ArrayList<>();
-        }
-        subnetIdList.add(subnetId);
-        nwMapBuilder.setSubnetIdList(subnetIdList);
-        MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
-        logger.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
-                networkId.getValue());
+    public static VpnPortipToPort getVpnPortFixedIp(DataBroker dataBroker, String vpnName, String fixedIp) {
+        InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
+        Optional<VpnPortipToPort> opt = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+        return opt != null && opt.isPresent() ? opt.get() : null;
     }
 
-    private static InstanceIdentifier<VpnPortipToPort> buildVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
-        InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
-                .child(VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
-        return id;
+    public static void removeVpnPortFixedIp(String vpnName, IpPrefix ipAddress, WriteTransaction tx) {
+        String fixedIpPrefix = ipPrefixToString(ipAddress);
+        String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
+        InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
+        tx.delete(LogicalDatastoreType.OPERATIONAL, id);
     }
 
     public static void addDirectSubnetToVpn(DataBroker dataBroker,
@@ -213,24 +264,25 @@ public class NetvirtVpnUtils {
             IpPrefix subnetIpPrefix, String interfaceName) {
         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
                 .child(ElanInstance.class, new ElanInstanceKey(subnetName)).build();
-        Optional<ElanInstance> elanInstance = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
+        Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
                 elanIdentifierId);
         if (!elanInstance.isPresent()) {
             logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
             return;
         }
-        Long elanTag = elanInstance.get().getElanTag();
+        Long elanTag = elanInstance.get().getElanTag() != null ? elanInstance.get().getElanTag()
+                : elanInstance.get().getSegmentationId();
 
         Uuid subnetId = new Uuid(subnetName);
-        logger.info("Adding subnet {} {} to elan map", subnetId);
+        logger.info("Adding subnet {} {} to elan map", subnetId, subnetId);
         createSubnetToNetworkMapping(dataBroker, subnetId, subnetId);
 
-        String subnetIp = getSubnetFromPrefix(MefUtils.ipPrefixToString(subnetIpPrefix));
+        String subnetIp = getSubnetFromPrefix(ipPrefixToString(subnetIpPrefix));
         logger.info("Adding subnet {} {} to vpn {}", subnetName, subnetIp, vpnName);
         updateSubnetNode(dataBroker, new Uuid(vpnName), subnetId, subnetIp);
 
         logger.info("Adding port {} to subnet {}", interfaceName, subnetName);
-        updateSubnetmapNodeWithPorts(dataBroker, subnetId, new Uuid(interfaceName));
+        updateSubnetmapNodeWithPorts(dataBroker, subnetId, new Uuid(interfaceName), null);
 
         logger.info("Publish subnet {}", subnetName);
         publishSubnetAddNotification(notificationPublishService, subnetId, subnetIp, vpnName, elanTag);
@@ -238,6 +290,64 @@ public class NetvirtVpnUtils {
 
     }
 
+    public static void removeDirectSubnetFromVpn(DataBroker dataBroker,
+            final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
+            String interfaceName) {
+        InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
+                .child(ElanInstance.class, new ElanInstanceKey(subnetName)).build();
+        Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                elanIdentifierId);
+        if (!elanInstance.isPresent()) {
+            logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
+            return;
+        }
+        Long elanTag = elanInstance.get().getElanTag() != null ? elanInstance.get().getElanTag()
+                : elanInstance.get().getSegmentationId();
+        Uuid subnetId = new Uuid(subnetName);
+
+        logger.info("Publish subnet remove {}", subnetName);
+        publishSubnetRemoveNotification(notificationPublishService, subnetId, vpnName, elanTag);
+
+        logger.info("Removing port {} from subnet {}", interfaceName, subnetName);
+        updateSubnetmapNodeWithPorts(dataBroker, subnetId, null, new Uuid(interfaceName));
+
+        logger.info("Removing subnet {} from vpn {}", subnetName, vpnName);
+        removeSubnetNode(dataBroker, new Uuid(vpnName));
+
+        logger.info("Removing subnet {} to elan map", subnetId);
+        removeSubnetToNetworkMapping(dataBroker, subnetId);
+
+        logger.info("Finished Working on subnet {}", subnetName);
+    }
+
+    private static void createSubnetToNetworkMapping(DataBroker dataBroker, Uuid subnetId, Uuid networkId) {
+        InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
+        Optional<NetworkMap> optionalNetworkMap = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                networkMapIdentifier);
+        NetworkMapBuilder nwMapBuilder = null;
+        if (optionalNetworkMap.isPresent()) {
+            nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
+        } else {
+            nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
+            logger.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
+        }
+        List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
+        if (subnetIdList == null) {
+            subnetIdList = new ArrayList<>();
+        }
+        subnetIdList.add(subnetId);
+        nwMapBuilder.setSubnetIdList(subnetIdList);
+        MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
+        logger.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
+                networkId.getValue());
+    }
+
+    private static void removeSubnetToNetworkMapping(DataBroker dataBroker, Uuid networkId) {
+        InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
+        MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
+        logger.debug("Deleted subnet-network mapping for  network {}", networkId.getValue());
+    }
+
     protected static void updateSubnetNode(DataBroker dataBroker, Uuid vpnId, Uuid subnetId, String subnetIp) {
         Subnetmap subnetmap = null;
         SubnetmapBuilder builder = null;
@@ -245,7 +355,7 @@ public class NetvirtVpnUtils {
                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
 
         synchronized (subnetId.getValue().intern()) {
-            Optional<Subnetmap> sn = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+            Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
             if (sn.isPresent()) {
                 builder = new SubnetmapBuilder(sn.get());
                 logger.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
@@ -264,22 +374,43 @@ public class NetvirtVpnUtils {
         }
     }
 
-    private static void updateSubnetmapNodeWithPorts(DataBroker dataBroker, Uuid subnetId, Uuid portId) {
+    protected static void removeSubnetNode(DataBroker dataBroker, Uuid subnetId) {
+        InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
+                .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+
+        synchronized (subnetId.getValue().intern()) {
+            logger.debug("Deleting subnetMap node: {} ", subnetId.getValue());
+            MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+        }
+    }
+
+    private static void updateSubnetmapNodeWithPorts(DataBroker dataBroker, Uuid subnetId, Uuid portIdToAdd,
+            Uuid portIdToRemove) {
         Subnetmap subnetmap = null;
         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
         synchronized (subnetId.getValue().intern()) {
-            Optional<Subnetmap> sn = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+            Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
             if (sn.isPresent()) {
                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
-                if (null != portId) {
+                if (null != portIdToAdd) {
                     List<Uuid> portList = builder.getPortList();
                     if (null == portList) {
                         portList = new ArrayList<>();
                     }
-                    portList.add(portId);
+                    if (portIdToAdd != null) {
+                        portList.add(portIdToAdd);
+                        logger.debug("Updating subnetmap node {} with port {}", subnetId.getValue(),
+                                portIdToAdd.getValue());
+
+                    }
+                    if (portIdToRemove != null) {
+                        portList.remove(portIdToRemove);
+                        logger.debug("Updating subnetmap node {} removing port {}", subnetId.getValue(),
+                                portIdToRemove.getValue());
+
+                    }
                     builder.setPortList(portList);
-                    logger.debug("Updating subnetmap node {} with port {}", subnetId.getValue(), portId.getValue());
                 }
                 subnetmap = builder.build();
                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
@@ -289,11 +420,27 @@ public class NetvirtVpnUtils {
         }
     }
 
+    private static InstanceIdentifier<NetworkMap> getNetworkMapIdentifier(Uuid networkId) {
+        InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
+                .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
+        return id;
+    }
+
+    private static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
+        InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
+                .child(VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
+        return id;
+    }
+
+    public static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier() {
+        return InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child(VpnPortipToPort.class).build();
+    }
+
     private static void publishSubnetAddNotification(final NotificationPublishService notificationPublishService,
             Uuid subnetId, String subnetIp, String vpnName, Long elanTag) {
         SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
 
-        logger.info("publish notification called");
+        logger.info("publish notification called for network creation");
 
         builder.setSubnetId(subnetId);
         builder.setSubnetIp(subnetIp);
@@ -309,7 +456,43 @@ public class NetvirtVpnUtils {
         }
     }
 
-    private static String getIpAddressFromPrefix(String prefix) {
+    private static void publishSubnetRemoveNotification(final NotificationPublishService notificationPublishService,
+            Uuid subnetId, String vpnName, Long elanTag) {
+        SubnetDeletedFromVpnBuilder builder = new SubnetDeletedFromVpnBuilder();
+
+        logger.info("publish notification called for network deletion");
+
+        builder.setSubnetId(subnetId);
+        builder.setVpnName(vpnName);
+        builder.setExternalVpn(true);
+        builder.setElanTag(elanTag);
+
+        try {
+            notificationPublishService.putNotification(builder.build());
+        } catch (InterruptedException e) {
+            logger.error("Fail to publish notification {}", builder, e);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    public static void sendArpRequest(OdlArputilService arpUtilService, IpAddress srcIpAddress, IpAddress dstIpAddress,
+            String interf) {
+        try {
+            List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
+            interfaceAddresses
+                    .add(new InterfaceAddressBuilder().setInterface(interf).setIpAddress(srcIpAddress).build());
+
+            SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(dstIpAddress)
+                    .setInterfaceAddress(interfaceAddresses).build();
+            arpUtilService.sendArpRequest(sendArpRequestInput);
+        } catch (Exception e) {
+            logger.error("Failed to send ARP request to IP {} from interfaces {}",
+                    dstIpAddress.getIpv4Address().getValue(), interf, e);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    public static String getIpAddressFromPrefix(String prefix) {
         return prefix.split(IP_MUSK_SEPARATOR)[0];
     }
 
@@ -317,12 +500,17 @@ public class NetvirtVpnUtils {
         return prefix.split(IP_MUSK_SEPARATOR)[1];
     }
 
-    private static String getSubnetFromPrefix(String prefix) {
+    public static String getSubnetFromPrefix(String prefix) {
         SubnetInfo subnet = new SubnetUtils(prefix).getInfo();
         return subnet.getNetworkAddress() + IP_MUSK_SEPARATOR + getMaskFromPrefix(prefix);
     }
 
-    private static String getPrefixFromSubnet(String prefix) {
+    public static String getSubnetFromPrefix(IpPrefix prefix) {
+        String prefixStr = ipPrefixToString(prefix);
+        return getSubnetFromPrefix(prefixStr);
+    }
+
+    private static String getAddressFromSubnet(String prefix) {
         String myAddress = getIpAddressFromPrefix(prefix);
         return myAddress + IP_ADDR_SUFFIX;
     }
@@ -331,82 +519,23 @@ public class NetvirtVpnUtils {
         return getUUidFromString(ELAN_PREFIX + portName);
     }
 
-    public static String getInterfaceNameForVlan(String interfaceName, Integer vlan) {
-        final StringBuilder s = new StringBuilder();
-        s.append(interfaceName);
-        if (vlan != null) {
-            s.append(VLAN_SEPARATOR).append(vlan);
-        }
-        s.append(TRUNK_SUFFIX);
-        return getUUidFromString(s.toString());
-    }
-
     public static String getUUidFromString(String key) {
         return java.util.UUID.nameUUIDFromBytes(key.getBytes()).toString();
     }
 
-    public static MacAddress resolveGwMac(DataBroker dataBroker, OdlArputilService arpUtilService, String vpnName,
-            IpPrefix srcIpPrefix, IpAddress dstIpAddress, String interf) {
-
-        String srcTpAddressStr = getIpAddressFromPrefix(MefUtils.ipPrefixToString(srcIpPrefix));
-        IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
-
-        if (srcIpAddress == null || dstIpAddress == null) {
-            logger.error("Can't send ARP to srcIp {} dstIp {}", srcIpAddress, dstIpAddress);
-            throw new RuntimeException("Can't send ARP for dstIp " + dstIpAddress);
+    public static String ipPrefixToString(IpPrefix ipAddress) {
+        if (ipAddress.getIpv4Prefix() != null) {
+            return ipAddress.getIpv4Prefix().getValue();
         }
 
-        MacAddress macAddress = null;
-        int retries = MaxRetries;
-        while (retries > 0 && macAddress == null) {
-            logger.info("Sending ARP request to dstIp {} take {}", dstIpAddress, MaxRetries - retries + 1);
-            sendArpRequest(arpUtilService, srcIpAddress, dstIpAddress, interf);
-            macAddress = waitForArpReplyProcessing(dataBroker, vpnName, dstIpAddress, MaxRetries);
-            retries--;
-        }
-        return macAddress;
+        return ipAddress.getIpv6Prefix().getValue();
     }
 
-    private static void sendArpRequest(OdlArputilService arpUtilService, IpAddress srcIpAddress, IpAddress dstIpAddress,
-            String interf) {
-        try {
-            List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
-            interfaceAddresses
-                    .add(new InterfaceAddressBuilder().setInterface(interf).setIpAddress(srcIpAddress).build());
-
-            SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(dstIpAddress)
-                    .setInterfaceAddress(interfaceAddresses).build();
-            arpUtilService.sendArpRequest(sendArpRequestInput);
-        } catch (Exception e) {
-            logger.error("Failed to send ARP request to IP {} from interfaces {}",
-                    dstIpAddress.getIpv4Address().getValue(), interf, e);
-            throw new RuntimeException(e.getMessage());
-        }
-    }
-
-    public static MacAddress waitForArpReplyProcessing(DataBroker dataBroker, String vpnName, IpAddress dstIpAddress,
-            int retries) {
-        while (retries > 0) {
-            logger.info("Waiting for ARP reply from dstIp {} take {}", dstIpAddress, MaxRetries - retries + 1);
-            InstanceIdentifier<VpnPortipToPort> optionalPortIpId = buildVpnPortipToPortIdentifier(vpnName,
-                    MefUtils.ipAddressToString(dstIpAddress));
-            Optional<VpnPortipToPort> optionalPortIp = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
-                    optionalPortIpId);
-
-            if (optionalPortIp.isPresent()) {
-                return new MacAddress(optionalPortIp.get().getMacAddress());
-            } else {
-                sleep();
-            }
-            retries--;
+    public static String ipAddressToString(IpAddress ipAddress) {
+        if (ipAddress.getIpv4Address() != null) {
+            return ipAddress.getIpv4Address().getValue();
         }
-        return null;
-    }
 
-    private static void sleep() {
-        try {
-            Thread.sleep(1000);
-        } catch (InterruptedException e) {
-        }
+        return ipAddress.getIpv6Address().getValue();
     }
 }
index db8c3dbb17a4df0300701cc1dec41167057ac3eb..80985333430c7855ba36d4e83e3e2627c92ec0a1 100644 (file)
@@ -20,11 +20,13 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
 import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.PhysicalLayersBuilder;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.LinksBuilder;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.LinkBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.topology.rev150526.mef.topology.devices.device.interfaces.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
@@ -35,7 +37,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfigBuilder;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,11 +47,12 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
 
     private static final Logger log = LoggerFactory.getLogger(NodeConnectorListener.class);
     private static boolean generateMac = false;
-    private static boolean handleRemovedNodeConnectors = false;
-    private ListenerRegistration<NodeConnectorListener> evcListenerRegistration;
+    private final UniPortManager uniPortManager;
+    private ListenerRegistration<NodeConnectorListener> nodeConnectorListenerRegistration;
 
-    public NodeConnectorListener(final DataBroker dataBroker, boolean generateMac) {
+    public NodeConnectorListener(final DataBroker dataBroker, final UniPortManager uniPortManager, final boolean generateMac) {
         super(dataBroker);
+        this.uniPortManager = uniPortManager;
         NodeConnectorListener.generateMac = generateMac;
         registerListener();
     }
@@ -59,7 +61,7 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
         try {
             final DataTreeIdentifier<FlowCapableNodeConnector> dataTreeIid = new DataTreeIdentifier<>(
                     LogicalDatastoreType.OPERATIONAL, getInstanceIdentifier());
-            evcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
+            nodeConnectorListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
             log.info("NodeConnectorListener created and registered");
 
             configIntegrationBridge();
@@ -69,6 +71,7 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
         }
     }
 
+    @SuppressWarnings("deprecation")
     private InstanceIdentifier<FlowCapableNodeConnector> getInstanceIdentifier() {
         return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
                 .augmentation(FlowCapableNodeConnector.class);
@@ -76,7 +79,7 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
 
     @Override
     public void close() throws Exception {
-        evcListenerRegistration.close();
+        nodeConnectorListenerRegistration.close();
     }
 
     @Override
@@ -140,6 +143,7 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
         }
     }
 
+    @SuppressWarnings("deprecation")
     private String getDpnIdFromNodeConnector(DataTreeModification<FlowCapableNodeConnector> newDataObject) {
         InstanceIdentifier<FlowCapableNodeConnector> key = newDataObject.getRootPath().getRootIdentifier();
         NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
@@ -148,6 +152,7 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
         return dpnFromNodeConnectorId;
     }
 
+    @SuppressWarnings("deprecation")
     private static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
         /*
          * NodeConnectorId is of form 'openflow:dpnid:portnum'
@@ -162,22 +167,22 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
 
         log.info("Adding mef uni/device interface {} with device {}", nodeConnector.getName(), dpnId);
 
-        String uniName = NetvirtUtils.getDeviceInterfaceName(dpnId, nodeConnector.getName());
-        InstanceIdentifier interfacePath = MefUtils.getDeviceInterfaceInstanceIdentifier(dpnId, uniName);
+        String uniName = MefInterfaceUtils.getDeviceInterfaceName(dpnId, nodeConnector.getName());
+        InstanceIdentifier<Interface> interfacePath = MefInterfaceUtils.getDeviceInterfaceInstanceIdentifier(dpnId,
+                uniName);
         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
         interfaceBuilder.setPhy(new Identifier45(uniName));
-        DataObject deviceInterface = interfaceBuilder.build();
+        Interface deviceInterface = interfaceBuilder.build();
+        tx.merge(LogicalDatastoreType.OPERATIONAL, interfacePath, deviceInterface, true);
 
-        tx.merge(LogicalDatastoreType.CONFIGURATION, interfacePath, deviceInterface, true);
-
-        InstanceIdentifier uniPath = MefUtils.getUniInstanceIdentifier(uniName);
+        InstanceIdentifier<Uni> uniPath = MefInterfaceUtils.getUniInstanceIdentifier(uniName);
         UniBuilder uniBuilder = new UniBuilder();
         uniBuilder.setUniId(new Identifier45(uniName));
         uniBuilder.setMacAddress(nodeConnector.getHardwareAddress());
 
         PhysicalLayersBuilder physicalLayersBuilder = new PhysicalLayersBuilder();
         LinksBuilder linksBuilder = new LinksBuilder();
-        List<Link> links = new ArrayList();
+        List<Link> links = new ArrayList<>();
         LinkBuilder linkBuilder = new LinkBuilder();
         linkBuilder.setDevice(new Identifier45(dpnId));
         linkBuilder.setInterface(uniName);
@@ -185,11 +190,10 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
         linksBuilder.setLink(links);
         physicalLayersBuilder.setLinks(linksBuilder.build());
         uniBuilder.setPhysicalLayers(physicalLayersBuilder.build());
-        DataObject uni = uniBuilder.build();
+        Uni uni = uniBuilder.build();
+        tx.merge(LogicalDatastoreType.OPERATIONAL, uniPath, uni, true);
 
-        tx.merge(LogicalDatastoreType.CONFIGURATION, uniPath, uni, true);
         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
-
         try {
             futures.get();
         } catch (InterruptedException | ExecutionException e) {
@@ -197,22 +201,27 @@ public class NodeConnectorListener extends UnimgrDataTreeChangeListener<FlowCapa
                     uniPath, uni);
             throw new RuntimeException(e.getMessage());
         }
+
+        // Reply UNI port configuration
+        uniPortManager.updateOperUni(uni.getUniId().getValue());
     }
 
     private void handleNodeConnectorRemoved(DataBroker dataBroker, String dpnId,
             FlowCapableNodeConnector nodeConnector) {
 
-        String uniName = NetvirtUtils.getDeviceInterfaceName(dpnId, nodeConnector.getName());
-
-        if (!handleRemovedNodeConnectors) {
-            return;
+        String uniName = MefInterfaceUtils.getDeviceInterfaceName(dpnId, nodeConnector.getName());
+        InstanceIdentifier<Interface> interfacePath = MefInterfaceUtils.getDeviceInterfaceInstanceIdentifier(dpnId,
+                uniName);
+        if (MefInterfaceUtils.getInterface(dataBroker, dpnId, uniName, LogicalDatastoreType.OPERATIONAL) != null) {
+            MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, interfacePath);
         }
 
-        MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                MefUtils.getDeviceInterfaceInstanceIdentifier(dpnId, uniName));
-
-        MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                MefUtils.getUniLinkInstanceIdentifier(nodeConnector.getName(), dpnId, uniName));
+        // Reply UNI port configuration
+        uniPortManager.removeUniPorts(uniName);
+        InstanceIdentifier<Uni> uniPath = MefInterfaceUtils.getUniInstanceIdentifier(uniName);
+        if (MefInterfaceUtils.getUni(dataBroker, uniName, LogicalDatastoreType.OPERATIONAL) != null) {
+            MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, uniPath);
+        }
     }
 
     private void handleNodeConnectorUpdated(DataBroker dataBroker, String dpnFromNodeConnectorId,
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/SubnetListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/SubnetListener.java
new file mode 100644 (file)
index 0000000..2f98c3c
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.Subnets;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ip.unis.IpUni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.IpvcVpn;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.IpvcChoice;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.Ipvc;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.VpnElans;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.ipvc.choice.ipvc.unis.Uni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.Identifier45;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class SubnetListener extends UnimgrDataTreeChangeListener<Subnet> implements ISubnetManager {
+    private static final Logger Log = LoggerFactory.getLogger(SubnetListener.class);
+    private ListenerRegistration<SubnetListener> subnetListenerRegistration;
+    private final NotificationPublishService notificationPublishService;
+    private final IGwMacListener gwMacListener;
+
+
+    public SubnetListener(final DataBroker dataBroker, final NotificationPublishService notPublishService,
+             final IGwMacListener gwMacListener ) {
+        super(dataBroker);
+        this.notificationPublishService = notPublishService;
+        this.gwMacListener = gwMacListener;
+        registerListener();
+    }
+
+    public void registerListener() {
+        try {
+            final DataTreeIdentifier<Subnet> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                    MefInterfaceUtils.getSubnetsInstanceIdentifier());
+            subnetListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
+            Log.info("IpvcDataTreeChangeListener created and registered");
+        } catch (final Exception e) {
+            Log.error("Ipvc DataChange listener registration failed !", e);
+            throw new IllegalStateException("Ipvc registration Listener failed.", e);
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        subnetListenerRegistration.close();
+    }
+
+    @Override
+    public void add(DataTreeModification<Subnet> newDataObject) {
+        if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
+            Log.info("subnet {} created", newDataObject.getRootNode().getIdentifier());
+        }
+
+        createNetwork(newDataObject);
+    }
+
+    @Override
+    public void remove(DataTreeModification<Subnet> removedDataObject) {
+        if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
+            Log.info("subnet {} deleted", removedDataObject.getRootNode().getIdentifier());
+        }
+        removeNetwork(removedDataObject);
+    }
+
+    @Override
+    public void update(DataTreeModification<Subnet> modifiedDataObject) {
+        if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
+            Log.info("subnet {} updated", modifiedDataObject.getRootNode().getIdentifier());
+            Log.info("process as delete / create");
+            removeNetwork(modifiedDataObject);
+            createNetwork(modifiedDataObject);
+        }
+    }
+
+    @Override
+    public void assignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId) {
+        InstanceIdentifier<Subnets> id = MefInterfaceUtils.getSubnetListInstanceIdentifier();
+        Optional<Subnets> allList = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+        Subnets allSubnets = allList.isPresent() ? allList.get() : null;
+        List<Subnet> allSubnet = allSubnets != null && allSubnets.getSubnet() != null ? allSubnets.getSubnet()
+                : Collections.emptyList();
+        List<Subnet> ipUniSubnets = allSubnet.stream()
+                .filter(s -> s.getUniId().equals(uniId) && s.getIpUniId().equals(ipUniId)).collect(Collectors.toList());
+        // recreate networks on restart
+        ipUniSubnets.forEach(s -> createNetwork(s, uniId, ipUniId));
+    }
+
+    @Override
+    public void unAssignIpUniNetworks(Identifier45 uniId, Identifier45 ipUniId, InstanceIdentifier<Ipvc> ipvcId) {
+        InstanceIdentifier<Subnets> id = MefInterfaceUtils.getSubnetListInstanceIdentifier();
+        Optional<Subnets> allList = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+        Subnets allSubnets = allList.isPresent() ? allList.get() : null;
+        List<Subnet> allSubnet = allSubnets != null && allSubnets.getSubnet() != null ? allSubnets.getSubnet()
+                : Collections.emptyList();
+        List<Subnet> ipUniSubnets = allSubnet.stream()
+                .filter(s -> s.getUniId().equals(uniId) && s.getIpUniId().equals(ipUniId)).collect(Collectors.toList());
+        ipUniSubnets.forEach(s -> removeNetwork(s, uniId, ipUniId, ipvcId));
+    }
+
+
+    private void createNetwork(DataTreeModification<Subnet> newDataObject) {
+        Subnet newSubnet = newDataObject.getRootNode().getDataAfter();
+
+        Identifier45 nwUniId = newSubnet.getUniId();
+        Identifier45 nwIpUniId = newSubnet.getIpUniId();
+
+        createNetwork(newSubnet, nwUniId, nwIpUniId);
+    }
+
+    private void createNetwork(Subnet newSubnet, Identifier45 nwUniId, Identifier45 nwIpUniId) {
+        String subnetStr = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
+
+        InstanceIdentifier<Ipvc> ipvcId = findService(nwUniId, nwIpUniId);
+        if (ipvcId == null) {
+            Log.info("Subnet Uni {} IpUNI {} is not assosiated to service", nwUniId, nwIpUniId);
+            return;
+        }
+        IpvcVpn ipvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
+        if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
+            Log.error("Subnet Uni {} IpUNI {} is not operational", nwUniId, nwIpUniId);
+            return;
+        }
+        VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(newSubnet, ipvcVpn);
+        if (vpnElan == null) {
+            Log.error("Subnet Uni {} IpUNI {} for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
+            return;
+        }
+        if (MefServicesUtils.findNetwork(newSubnet, vpnElan) != null) {
+            Log.info("Network {} exists already", subnetStr);
+            return;
+        }
+
+        String vpnId = ipvcVpn.getVpnId();
+        synchronized (vpnId.intern()) {
+            if (newSubnet.getGateway() == null) {
+                checkCreateDirectNetwork(newSubnet, ipvcVpn, ipvcId, vpnElan);
+            } else {
+                createNonDirectNetwork(newSubnet, ipvcVpn, ipvcId, vpnElan);
+            }
+        }
+        MefServicesUtils.addOperIpvcVpnElan(dataBroker, ipvcId, ipvcVpn.getVpnId(), nwUniId, nwIpUniId,
+                vpnElan.getElanId(), vpnElan.getElanPort(), Collections.singletonList(subnetStr));
+
+    }
+
+    private void createNonDirectNetwork(Subnet newSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId,
+            VpnElans vpnElan) {
+        if (newSubnet.getGateway() == null) {
+            return;
+        }
+
+        Identifier45 nwUniId = newSubnet.getUniId();
+        Identifier45 nwIpUniId = newSubnet.getIpUniId();
+        String subnetStr = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
+
+        IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, nwUniId, nwIpUniId, LogicalDatastoreType.CONFIGURATION);
+        if (ipUni == null) {
+            Log.error("Uni {} IpUni {}  for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
+            return;
+        }
+
+        String srcTpAddressStr = NetvirtVpnUtils.getIpAddressFromPrefix(NetvirtVpnUtils.ipPrefixToString(ipUni.getIpAddress()));
+        IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
+        String subnet = NetvirtVpnUtils.ipPrefixToString(newSubnet.getSubnet());
+        gwMacListener.resolveGwMac(ipvcVpn.getVpnId(), vpnElan.getElanPort(), srcIpAddress, newSubnet.getGateway(), subnet);
+    }
+
+    private void checkCreateDirectNetwork(Subnet newSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId,
+            VpnElans vpnElan) {
+        if (newSubnet.getGateway() != null) {
+            return;
+        }
+
+        NetvirtVpnUtils.addDirectSubnetToVpn(dataBroker, notificationPublishService, ipvcVpn.getVpnId(),
+                vpnElan.getElanId(), newSubnet.getSubnet(), vpnElan.getElanPort());
+
+    }
+
+    private void removeNetwork(DataTreeModification<Subnet> deletedDataObject) {
+        Subnet deletedSubnet = deletedDataObject.getRootNode().getDataBefore();
+        Identifier45 dlUniId = deletedSubnet.getUniId();
+        Identifier45 dlIpUniId = deletedSubnet.getIpUniId();
+        InstanceIdentifier<Ipvc> ipvcId = findService(dlUniId, dlIpUniId);
+        if (ipvcId == null) {
+            Log.info("Subnet Uni {} IpUNI {} for deleted network is not assosiated to service", dlUniId, dlIpUniId);
+            return;
+        }
+        removeNetwork(deletedSubnet, dlUniId, dlIpUniId, ipvcId);
+    }
+
+    private void removeNetwork(Subnet dlSubnet, Identifier45 dlUniId, Identifier45 dlIpUniId,
+            InstanceIdentifier<Ipvc> ipvcId) {
+        String subnetStr = NetvirtVpnUtils.ipPrefixToString(dlSubnet.getSubnet());
+        IpvcVpn ipvcVpn = MefServicesUtils.getOperIpvcVpn(dataBroker, ipvcId);
+        if (ipvcVpn == null || ipvcVpn.getVpnElans() == null) {
+            Log.error("Subnet Uni {} IpUNI {} is not operational", dlUniId, dlIpUniId);
+            return;
+        }
+        VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(dlSubnet, ipvcVpn);
+        if (vpnElan == null) {
+            Log.error("Trying to remove non-operational network {}", subnetStr);
+            return;
+        }
+        if (MefServicesUtils.findNetwork(dlSubnet, vpnElan) == null) {
+            Log.error("Trying to remove non-operational network {}", subnetStr);
+            return;
+        }
+
+        String vpnId = ipvcVpn.getVpnId();
+        synchronized (vpnId.intern()) {
+            if (dlSubnet.getGateway() == null) {
+                removeDirectNetwork(dlSubnet, ipvcVpn, ipvcId);
+            } else {
+                removeNonDirectNetwork(dlSubnet, ipvcVpn, ipvcId);
+            }
+        }
+        MefServicesUtils.removeOperIpvcSubnet(dataBroker, ipvcId, ipvcVpn.getVpnId(), dlUniId, dlIpUniId,
+                vpnElan.getElanId(), vpnElan.getElanPort(), subnetStr);
+    }
+
+
+    private void removeDirectNetwork(Subnet deletedSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId) {
+        if (deletedSubnet.getGateway() != null) {
+            return;
+        }
+
+        String subnetStr = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
+        VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(deletedSubnet, ipvcVpn);
+        if (vpnElan == null) {
+            Log.error("Network {} has not been created as required, nothing to remove", subnetStr);
+            return;
+        }
+
+        NetvirtVpnUtils.removeDirectSubnetFromVpn(dataBroker, notificationPublishService, ipvcVpn.getVpnId(),
+                vpnElan.getElanId(), vpnElan.getElanPort());
+
+    }
+
+    private void removeNonDirectNetwork(Subnet deletedSubnet, IpvcVpn ipvcVpn, InstanceIdentifier<Ipvc> ipvcId) {
+        if (deletedSubnet.getGateway() == null) {
+            return;
+        }
+
+        Identifier45 nwUniId = deletedSubnet.getUniId();
+        Identifier45 nwIpUniId = deletedSubnet.getIpUniId();
+        String subnetStr = NetvirtVpnUtils.ipPrefixToString(deletedSubnet.getSubnet());
+        VpnElans vpnElan = MefServicesUtils.findVpnForNetwork(deletedSubnet, ipvcVpn);
+        if (vpnElan == null) {
+            Log.error("Network {} has not been created as required, nothing to remove", subnetStr);
+            return;
+        }
+
+        IpUni ipUni = MefInterfaceUtils.getIpUni(dataBroker, nwUniId, nwIpUniId, LogicalDatastoreType.CONFIGURATION);
+        if (ipUni == null) {
+            Log.error("Uni {} IpUni {}  for network {} is not operational", nwUniId, nwIpUniId, subnetStr);
+            return;
+        }
+
+        String srcTpAddressStr = NetvirtVpnUtils.getIpAddressFromPrefix(NetvirtVpnUtils.ipPrefixToString(ipUni.getIpAddress()));
+        IpAddress srcIpAddress = new IpAddress(srcTpAddressStr.toCharArray());
+        gwMacListener.unResolveGwMac(ipvcVpn.getVpnId(), vpnElan.getElanPort(), srcIpAddress, deletedSubnet.getGateway() );
+
+        NetvirtVpnUtils.removeVpnInterfaceAdjacency(dataBroker, vpnElan.getElanPort(), deletedSubnet.getSubnet());
+        NetvirtVpnUtils.removeVpnInterfaceAdjacency(dataBroker, vpnElan.getElanPort(), deletedSubnet.getGateway());
+    }
+
+    private InstanceIdentifier<Ipvc> findService(Identifier45 uniId, Identifier45 ipUniId) {
+        InstanceIdentifier<MefServices> path = MefServicesUtils.getMefServicesInstanceIdentifier();
+        Optional<MefServices> mefServices = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
+        if (!mefServices.isPresent() || mefServices.get() == null) {
+            Log.info("Uni {} IpUni {} is not assosiated with service", uniId, ipUniId);
+            return null;
+        }
+        for (MefService service : mefServices.get().getMefService()) {
+            if (service.getMefServiceChoice() instanceof IpvcChoice) {
+                Ipvc ipvc = ((IpvcChoice) service.getMefServiceChoice()).getIpvc();
+                if (ipvc.getUnis() == null || ipvc.getUnis().getUni() == null) {
+                    continue;
+                }
+                List<Uni> unis = ipvc.getUnis().getUni();
+                for (Uni uni : unis) {
+                    if (uni.getUniId().equals(uniId) && uni.getIpUniId().equals(ipUniId)) {
+                        Log.info("Find service {} for uni {} ipuni {}", service.getSvcId(), uniId, ipUniId);
+                        return MefServicesUtils.getIpvcsInstanceIdentifier(service.getSvcId());
+                    }
+                }
+            }
+        }
+        Log.info("Uni {} IpUni {} is not assosiated with service", uniId, ipUniId);
+        return null;
+    }
+}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantEnhancerUtils.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantEnhancerUtils.java
deleted file mode 100644 (file)
index c7d7798..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.unimgr.mef.netvirt;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefServiceBuilder;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.EvcChoice;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.Evc;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TenantEnhancerUtils {
-    private static final Logger log = LoggerFactory.getLogger(TenantEnhancerUtils.class);
-
-    public static boolean isServiceTenanted(MefService service) {
-        return service.getTenantId().equals("");
-    }
-
-    public static boolean isUniTenanted(
-            org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uni) {
-        return uni.getTenantId().equals("");
-    }
-
-    public static void updateService(DataBroker dataBroker, String tenant, MefService service) {
-        log.info("service is {}", service);
-
-        MefServiceBuilder builder = new MefServiceBuilder();
-        builder.setKey(service.getKey());
-        builder.setTenantId(tenant);
-        MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                MefUtils.getMefServiceInstanceIdentifier(service.getSvcId()), service);
-    }
-
-    public static Evc GetEvc(MefService service) {
-        if (!(service.getMefServiceChoice() instanceof EvcChoice)) {
-            return null;
-        }
-
-        return ((EvcChoice) service.getMefServiceChoice()).getEvc();
-    }
-}
\ No newline at end of file
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantUniListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantUniListener.java
deleted file mode 100644 (file)
index abb3a9a..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.unimgr.mef.netvirt;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.MefServices;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-
-public class TenantUniListener extends UnimgrDataTreeChangeListener<Uni> {
-
-    private static final Logger log = LoggerFactory.getLogger(TenantUniListener.class);
-    private ListenerRegistration<TenantUniListener> evcListenerRegistration;
-
-    public TenantUniListener(final DataBroker dataBroker) {
-        super(dataBroker);
-
-        registerListener();
-    }
-
-    public void registerListener() {
-        try {
-            final DataTreeIdentifier<Uni> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
-                    MefUtils.getUniListInterfaceInstanceIdentifier());
-            evcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
-            log.info("TenantUniListener created and registered");
-        } catch (final Exception e) {
-            log.error("TenantUniListener registration failed !", e);
-            throw new IllegalStateException("Evc registration Listener failed.", e);
-        }
-    }
-
-    @Override
-    public void close() throws Exception {
-        evcListenerRegistration.close();
-    }
-
-    @Override
-    public void add(DataTreeModification<Uni> newDataObject) {
-        log.info("received add Uni notification");
-        handleUniChanged(newDataObject.getRootNode().getDataAfter());
-    }
-
-    @Override
-    public void remove(DataTreeModification<Uni> removedDataObject) {
-    }
-
-    @Override
-    public void update(DataTreeModification<Uni> modifiedDataObject) {
-        log.info("received update Uni notification");
-        handleUniChanged(modifiedDataObject.getRootNode().getDataAfter());
-    }
-
-    private void handleUniChanged(Uni uni) {
-        if (!TenantEnhancerUtils.isUniTenanted(uni)) {
-            return;
-        }
-
-        String tenant = uni.getTenantId();
-
-        Optional<MefServices> optionalServices = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                MefUtils.getMefServicesInstanceIdentifier());
-        if (!optionalServices.isPresent()) {
-            return;
-        }
-
-        for (MefService service : optionalServices.get().getMefService()) {
-            for (org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni serviceUni : TenantEnhancerUtils
-                    .GetEvc(service).getUnis().getUni()) {
-                if (!TenantEnhancerUtils.isServiceTenanted(service) && serviceUni.getUniId().equals(uni.getUniId())) {
-                    log.info("instance identifier is {}", MefUtils.getMefServiceInstanceIdentifier(service.getSvcId()));
-                    TenantEnhancerUtils.updateService(dataBroker, tenant, service);
-                }
-            }
-        }
-    }
-}
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantlessEvcListener.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/TenantlessEvcListener.java
deleted file mode 100644 (file)
index 4ba3f4a..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.unimgr.mef.netvirt;
-
-import java.util.List;
-
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
-import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.Evc;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.MefService;
-import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.services.rev150526.mef.services.mef.service.mef.service.choice.evc.choice.evc.unis.Uni;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-
-public class TenantlessEvcListener extends UnimgrDataTreeChangeListener<MefService> {
-
-    private static final Logger log = LoggerFactory.getLogger(TenantlessEvcListener.class);
-    private ListenerRegistration<TenantlessEvcListener> evcListenerRegistration;
-
-    public TenantlessEvcListener(final DataBroker dataBroker) {
-        super(dataBroker);
-
-        registerListener();
-    }
-
-    public void registerListener() {
-        try {
-            final DataTreeIdentifier<MefService> dataTreeIid = new DataTreeIdentifier<>(
-                    LogicalDatastoreType.CONFIGURATION, MefUtils.getMefServiceInstanceIdentifier());
-            evcListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
-            log.info("TenantlessEvcListener created and registered");
-        } catch (final Exception e) {
-            log.error("TenantlessEvcListener registration failed !", e);
-            throw new IllegalStateException("Evc registration Listener failed.", e);
-        }
-    }
-
-    @Override
-    public void close() throws Exception {
-        evcListenerRegistration.close();
-    }
-
-    @Override
-    public void add(DataTreeModification<MefService> newDataObject) {
-        if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
-            log.info("service {} created", newDataObject.getRootNode().getIdentifier());
-            handleService(newDataObject.getRootNode().getDataAfter());
-        }
-    }
-
-    @Override
-    public void remove(DataTreeModification<MefService> removedDataObject) {
-    }
-
-    @Override
-    public void update(DataTreeModification<MefService> modifiedDataObject) {
-        if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
-            log.info("service {} updated", modifiedDataObject.getRootNode().getIdentifier());
-            handleService(modifiedDataObject.getRootNode().getDataAfter());
-        }
-    }
-
-    private void handleService(MefService service) {
-        if (TenantEnhancerUtils.isServiceTenanted(service)) {
-            log.info("Service {} is already connected to a Service", service.getSvcId().getValue());
-            return;
-        }
-        Evc evc = TenantEnhancerUtils.GetEvc(service);
-        if (evc.getUnis() == null) {
-            log.info("No UNI's in service {}, exiting", service.getSvcId().getValue());
-            return;
-        }
-        List<Uni> unis = evc.getUnis().getUni();
-        for (Uni uni : unis) {
-            Optional<org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni> optonalUniInterface = MdsalUtils
-                    .read(dataBroker, LogicalDatastoreType.CONFIGURATION,
-                            MefUtils.getUniInstanceIdentifier(uni.getUniId().getValue()));
-            if (optonalUniInterface.isPresent()) {
-                org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni uniInterface = optonalUniInterface
-                        .get();
-                if (TenantEnhancerUtils.isUniTenanted(uniInterface)) {
-                    String tenant = uniInterface.getTenantId();
-                    log.info("updating service {} with tenant {}", service.getSvcId().getValue(), tenant);
-                    TenantEnhancerUtils.updateService(dataBroker, tenant, service);
-                    return;
-                }
-            } else {
-                log.info("Couldn't find uni {}", uni.getUniId());
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/UniPortManager.java b/netvirt/src/main/java/org/opendaylight/unimgr/mef/netvirt/UniPortManager.java
new file mode 100644 (file)
index 0000000..7b50902
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.unimgr.mef.netvirt;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.unimgr.api.UnimgrDataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.PortVlanMapping;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.PortVlanMappingBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.Uni;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.UniBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.CeVlansBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.VlanToPort;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.VlanToPortBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ce.vlans.CeVlan;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.ce.vlans.CeVlanBuilder;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.interfaces.rev150526.mef.interfaces.unis.uni.physical.layers.links.Link;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.VlanIdOrNoneType;
+import org.opendaylight.yang.gen.v1.http.metroethernetforum.org.ns.yang.mef.types.rev150526.VlanIdType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
+
+public class UniPortManager extends UnimgrDataTreeChangeListener<Uni> implements IUniPortManager {
+
+    private static final Logger log = LoggerFactory.getLogger(UniPortManager.class);
+    private ListenerRegistration<UniPortManager> uniListenerRegistration;
+    private static int maxWaitRetries = 3;
+
+    public UniPortManager(final DataBroker dataBroker) {
+        super(dataBroker);
+
+        registerListener();
+    }
+
+    public void registerListener() {
+        try {
+            final DataTreeIdentifier<Uni> dataTreeIid = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
+                    getInstanceIdentifier());
+            uniListenerRegistration = dataBroker.registerDataTreeChangeListener(dataTreeIid, this);
+            log.info("UniPortListener created and registered");
+        } catch (final Exception e) {
+            log.error("UniPortListener registration failed !", e);
+            throw new IllegalStateException("UniPortListener registration failed.", e);
+        }
+    }
+
+    private InstanceIdentifier<Uni> getInstanceIdentifier() {
+        return MefInterfaceUtils.getUniListInstanceIdentifier();
+    }
+
+    @Override
+    public void close() throws Exception {
+        uniListenerRegistration.close();
+    }
+
+    @Override
+    public void add(DataTreeModification<Uni> newDataObject) {
+        if (newDataObject.getRootPath() != null && newDataObject.getRootNode() != null) {
+            log.info("uni node {} created", newDataObject.getRootNode().getIdentifier());
+        }
+        Uni confUni = newDataObject.getRootNode().getDataAfter();
+        String uniId = confUni.getUniId().getValue();
+
+        synchronized (uniId.intern()) {
+            if (!checkOperUni(uniId)) {
+                return;
+            }
+            addCheckUniPorts(confUni);
+        }
+    }
+
+    @Override
+    public void remove(DataTreeModification<Uni> removedDataObject) {
+        if (removedDataObject.getRootPath() != null && removedDataObject.getRootNode() != null) {
+            log.info("uni node {} deleted", removedDataObject.getRootNode().getIdentifier());
+        }
+        Uni confUni = removedDataObject.getRootNode().getDataBefore();
+        String uniId = confUni.getUniId().getValue();
+        synchronized (uniId.intern()) {
+            if (!checkOperUni(uniId)) {
+                return;
+            }
+            removeUniPorts(confUni);
+        }
+    }
+
+    @Override
+    public void update(DataTreeModification<Uni> modifiedDataObject) {
+        if (modifiedDataObject.getRootPath() != null && modifiedDataObject.getRootNode() != null) {
+            log.info("node connector {} updated", modifiedDataObject.getRootNode().getIdentifier());
+        }
+        Uni confUni = modifiedDataObject.getRootNode().getDataAfter();
+        String uniId = confUni.getUniId().getValue();
+        synchronized (uniId.intern()) {
+            if (!checkOperUni(uniId)) {
+                return;
+            }
+            removeCheckUniPorts(confUni);
+            addCheckUniPorts(confUni);
+        }
+    }
+
+    @Override
+    public void updateOperUni(String uniId) {
+        Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
+        if (confUni == null) {
+            log.debug("No UNI {} exists, nothing to update");
+            return;
+        }
+        synchronized (uniId.intern()) {
+            if (!checkOperUni(uniId)) {
+                return;
+            }
+            log.info("UNI  {} ports updated", uniId);
+
+            removeCheckUniPorts(confUni);
+            addCheckUniPorts(confUni);
+        }
+    }
+
+    @Override
+    public void removeUniPorts(String uniId) {
+        Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
+        if (confUni == null) {
+            log.debug("No UNI {} exists, nothing to update");
+            return;
+        }
+        synchronized (uniId.intern()) {
+            if (!checkOperUni(uniId)) {
+                return;
+            }
+            removeUniPorts(confUni);
+        }
+    }
+
+    private boolean checkOperUni(String uniId) {
+        Uni operUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
+        if (operUni == null) {
+            log.info("Uni {} is not operational", uniId);
+            return false;
+        }
+        return true;
+    }
+
+    private void addCheckUniPorts(Uni confUni) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+
+        String uniId = confUni.getUniId().getValue();
+        Link link = MefInterfaceUtils.getLink(dataBroker, uniId, LogicalDatastoreType.OPERATIONAL);
+        String trunkInterface = MefInterfaceUtils.getInterfaceNameForVlan(uniId, null);
+        String parentInterfaceName = MefInterfaceUtils.getTrunkParentName(link);
+        List<VlanToPort> operVlanInterfaces = getOperTrunkInterfaces(uniId);
+        if (!hasVlanPort(operVlanInterfaces, Long.valueOf(0))) {
+            VlanToPort newOperVlanInterface = addTrunkInterface(trunkInterface, parentInterfaceName, tx);
+            operVlanInterfaces.add(newOperVlanInterface);
+        }
+
+        List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
+                : Collections.emptyList();
+        for (CeVlan ceVlan : ceVlans) {
+            Long vlan = ceVlan.getVid().getValue().longValue();
+            if (hasVlanPort(operVlanInterfaces, vlan)) {
+                continue;
+            }
+
+            String trunkMemberName = MefInterfaceUtils.getInterfaceNameForVlan(uniId, vlan);
+            VlanToPort newOperVlanInterface = addTrunkMemberInterface(trunkMemberName, trunkInterface, vlan, tx);
+            operVlanInterfaces.add(newOperVlanInterface);
+        }
+        // set VlanMapping to Uni
+        setOperTrunkInterfaces(uniId, operVlanInterfaces, tx);
+
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    private void removeCheckUniPorts(Uni confUni) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+
+        List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
+                : Collections.emptyList();
+        List<Long> vlansValue = ceVlans.stream().map(x -> x.getVid().getValue()).collect(Collectors.toList());
+
+        String uniId = confUni.getUniId().getValue();
+        List<VlanToPort> operVlanInterfaces = getOperTrunkInterfaces(uniId);
+
+        for (VlanToPort oldPort : getOperTrunkInterfaces(uniId)) {
+            Long oldVlan = oldPort.getVlan().getValue();
+            if (!vlansValue.contains(oldVlan)) {
+                VlanToPort removedOperVlanInterface = removeTrunkInterface(oldPort.getVlanPortId(), oldVlan, tx);
+                operVlanInterfaces.remove(removedOperVlanInterface);
+            }
+        }
+        // set VlanMapping to Uni
+        setOperTrunkInterfaces(uniId, operVlanInterfaces, tx);
+
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    private void removeUniPorts(Uni confUni) {
+        WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
+        String uniId = confUni.getUniId().getValue();
+
+        for (VlanToPort oldPort : getOperTrunkInterfaces(uniId)) {
+            Long oldVlan = oldPort.getVlan().getValue();
+            removeTrunkInterface(oldPort.getVlanPortId(), oldVlan, tx);
+        }
+        setOperTrunkInterfaces(uniId, new ArrayList<>(), tx);
+
+        MdsalUtils.commitTransaction(tx);
+    }
+
+    private VlanToPort addTrunkInterface(String interfaceName, String parentInterfaceName, WriteTransaction tx) {
+        log.info("Adding VLAN trunk {} ParentRef {}", interfaceName, parentInterfaceName);
+        Interface trunkInterface = NetvirtUtils.createTrunkInterface(interfaceName, parentInterfaceName);
+        NetvirtUtils.writeInterface(trunkInterface, tx);
+        return createOperTrunkInterfaceMapping(Long.valueOf(0), trunkInterface.getName());
+    }
+
+    private VlanToPort addTrunkMemberInterface(String interfaceName, String parentInterfaceName, Long vlan,
+            WriteTransaction tx) {
+        log.info("Adding VLAN trunk member {} ParentRef {}", interfaceName, parentInterfaceName);
+        Interface trunkInterface = NetvirtUtils.createTrunkMemberInterface(interfaceName, parentInterfaceName,
+                vlan.intValue());
+        NetvirtUtils.writeInterface(trunkInterface, tx);
+        return createOperTrunkInterfaceMapping(vlan, trunkInterface.getName());
+    }
+
+    private VlanToPort removeTrunkInterface(String interfaceName, Long vlan, WriteTransaction tx) {
+        log.info("Delete VLAN trunk {} ParentRef {}", interfaceName);
+        NetvirtUtils.deleteInterface(interfaceName, tx);
+        return createOperTrunkInterfaceMapping(vlan, interfaceName);
+    }
+
+    private List<VlanToPort> getOperTrunkInterfaces(String operUniId) {
+        InstanceIdentifier<Uni> identifier = MefInterfaceUtils.getUniInstanceIdentifier(operUniId);
+        InstanceIdentifier<PortVlanMapping> path = identifier.augmentation(PortVlanMapping.class);
+        Optional<PortVlanMapping> portVlanMapping = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
+        if (portVlanMapping.isPresent()) {
+            return portVlanMapping.get().getVlanToPort();
+        } else {
+            return new ArrayList<>();
+        }
+    }
+
+    private void setOperTrunkInterfaces(String operUniId, List<VlanToPort> vlanToPort, WriteTransaction tx) {
+        InstanceIdentifier<Uni> identifier = MefInterfaceUtils.getUniInstanceIdentifier(operUniId);
+        InstanceIdentifier<PortVlanMapping> path = identifier.augmentation(PortVlanMapping.class);
+
+        PortVlanMappingBuilder portVlanMappingB = new PortVlanMappingBuilder();
+        portVlanMappingB.setVlanToPort(vlanToPort);
+
+        tx.put(LogicalDatastoreType.OPERATIONAL, path, portVlanMappingB.build());
+    }
+
+    private VlanToPort createOperTrunkInterfaceMapping(Long vlan, String interfaceName) {
+        final Long vlanNotNull = replaceNull(vlan);
+
+        VlanToPortBuilder vlanToPortBuilder = new VlanToPortBuilder();
+        vlanToPortBuilder.setVlan(new VlanIdOrNoneType(vlanNotNull));
+        vlanToPortBuilder.setVlanPortId(interfaceName);
+        return vlanToPortBuilder.build();
+    }
+
+    private boolean hasVlanPort(List<VlanToPort> vlanInterfaces, Long vlan) {
+        if (vlanInterfaces == null) {
+            return false;
+        }
+        final Long vlanNotNull = replaceNull(vlan);
+
+        if (vlanInterfaces.stream().filter(x -> x.getVlan().getValue().equals(vlanNotNull)).findAny().isPresent()) {
+            return true;
+        }
+        return false;
+    }
+
+    private static final Long replaceNull(Long vlan) {
+        if (vlan == null) {
+            return Long.valueOf(0);
+        }
+        return vlan;
+    }
+
+    @Override
+    public void addCeVlan(String uniId, Long vlanId) {
+        if (getUniVlanInterfaceNoRetry(uniId, vlanId) != null) {
+            log.debug("UNI {} Port for vlan {} exists already, nothing to update", uniId, vlanId);
+            return;
+        }
+        synchronized (uniId.intern()) {
+            Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
+            if (confUni == null) {
+                log.debug("No UNI {} exists, nothing to update");
+                return;
+            }
+            if (!checkOperUni(uniId)) {
+                return;
+            }
+            log.info("UNI  {} Vlan {} adding", uniId, vlanId);
+            List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan() : new ArrayList<>();
+            CeVlanBuilder ceVlanBuilder = new CeVlanBuilder();
+            ceVlanBuilder.setVid(new VlanIdType(vlanId));
+            CeVlansBuilder ceVlansBuilder = confUni.getCeVlans() != null ? new CeVlansBuilder(confUni.getCeVlans())
+                    : new CeVlansBuilder();
+            ceVlans.add(ceVlanBuilder.build());
+            ceVlansBuilder.setCeVlan(ceVlans);
+            UniBuilder uniBuilder = new UniBuilder();
+            uniBuilder.setUniId(confUni.getUniId());
+            uniBuilder.setCeVlans(ceVlansBuilder.build());
+            MdsalUtils.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    MefInterfaceUtils.getUniInstanceIdentifier(uniId), uniBuilder.build());
+        }
+    }
+
+    @Override
+    public void removeCeVlan(String uniId, Long vlanId) {
+        if (getUniVlanInterfaceNoRetry(uniId, vlanId) == null) {
+            log.debug("No UNI {} Port for vlan {} exists already, nothing to delete", uniId, vlanId);
+            return;
+        }
+        synchronized (uniId.intern()) {
+            Uni confUni = MefInterfaceUtils.getUni(dataBroker, uniId, LogicalDatastoreType.CONFIGURATION);
+            if (confUni == null) {
+                log.debug("No UNI {} exists, nothing to update");
+                return;
+            }
+            if (!checkOperUni(uniId)) {
+                return;
+            }
+            log.info("UNI  {} Vlan {} deleting", uniId, vlanId);
+            UniBuilder uniBuilder = new UniBuilder(confUni);
+
+            if (vlanId != null && vlanId != 0l) {
+                List<CeVlan> ceVlans = confUni.getCeVlans() != null ? confUni.getCeVlans().getCeVlan()
+                        : Collections.emptyList();
+                CeVlanBuilder ceVlanBuilder = new CeVlanBuilder();
+                ceVlanBuilder.setVid(new VlanIdType(vlanId));
+                CeVlansBuilder ceVlansBuilder = new CeVlansBuilder(confUni.getCeVlans());
+                ceVlans.remove(ceVlanBuilder.build());
+                ceVlansBuilder.setCeVlan(ceVlans);
+                uniBuilder.setCeVlans(ceVlansBuilder.build());
+            } else {
+                uniBuilder.setCeVlans(null);
+            }
+            MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
+                    MefInterfaceUtils.getUniInstanceIdentifier(uniId), uniBuilder.build());
+        }
+
+    }
+
+    @Override
+    public List<String> getUniVlanInterfaces(String uniId) {
+        synchronized (uniId.intern()) {
+            List<VlanToPort> vlanToPorts = getOperTrunkInterfaces(uniId);
+            return vlanToPorts.stream().map(port -> port.getVlanPortId()).collect(Collectors.toList());
+        }
+    }
+
+    @Override
+    public String getUniVlanInterface(String uniId, Long vlanId) {
+        Long vlanNotNull = replaceNull(vlanId);
+        return getUniVlanInterfaceRetry(uniId, vlanNotNull, 0);
+    }
+
+    public String getUniVlanInterfaceNoRetry(String uniId, Long vlanId) {
+        Long vlanNotNull = replaceNull(vlanId);
+        return getUniVlanInterfaceRetry(uniId, vlanNotNull, maxWaitRetries);
+    }
+
+    private String getUniVlanInterfaceRetry(String uniId, Long vlanId, int retries) {
+        log.trace("Retry {} to wait for uniId {} vlan {} interface", retries, uniId, vlanId);
+        List<VlanToPort> vlanToPorts = getOperTrunkInterfaces(uniId);
+        java.util.Optional<String> toReturn = vlanToPorts.stream()
+                .filter(port -> port.getVlan().getValue().equals(vlanId)).map(port -> port.getVlanPortId()).findFirst();
+        if (toReturn.isPresent()) {
+            return toReturn.get();
+        } else {
+            if (retries >= maxWaitRetries) {
+                return null;
+            }
+            NetvirtUtils.safeSleep();
+            return getUniVlanInterfaceRetry(uniId, vlanId, ++retries);
+        }
+    }
+}
index f012dd87306521e635fdc284ec7e16c1797b461d..451e65098015db28693211d2b60762d4f9097f74 100644 (file)
@@ -1,39 +1,51 @@
-<!-- Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others. All rights 
-       reserved. This program and the accompanying materials are made available 
-       under the terms of the Eclipse Public License v1.0 which accompanies this 
-       distribution, and is available at http://www.eclipse.org/legal/epl-v10.html -->
+<!-- Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others. All rights
+    reserved. This program and the accompanying materials are made available
+    under the terms of the Eclipse Public License v1.0 which accompanies this
+    distribution, and is available at http://www.eclipse.org/legal/epl-v10.html -->
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-       xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
-       odl:use-default-for-reference-types="true">
-
-       <reference id="dataBroker"
-               interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" />
-       <reference id="notificationPublishService"
-               interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService" />
-       <odl:rpc-service id="odlArputilService"
-               interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService" />
-
-       <bean class="org.opendaylight.unimgr.mef.netvirt.EvcListener">
-               <argument index="0" ref="dataBroker" />
-       </bean>
-
-       <bean class="org.opendaylight.unimgr.mef.netvirt.NodeConnectorListener">
-               <argument index="0" ref="dataBroker" />
-               <argument index="1" value="false" />
-       </bean>
-
-       <!-- <bean class="org.opendaylight.unimgr.mef.netvirt.TenantlessEvcListener"> -->
-       <!-- <argument index="0" ref="dataBroker" /> -->
-       <!-- </bean> -->
-
-       <!-- <bean class="org.opendaylight.unimgr.mef.netvirt.TenantUniListener"> -->
-       <!-- <argument index="0" ref="dataBroker" /> -->
-       <!-- </bean> -->
-
-       <bean class="org.opendaylight.unimgr.mef.netvirt.IpvcListener">
-               <argument ref="dataBroker" />
-               <argument ref="notificationPublishService" />
-               <argument ref="odlArputilService" />
-       </bean>
-
-</blueprint>
\ No newline at end of file
+    xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+    odl:use-default-for-reference-types="true">
+
+    <reference id="dataBroker"
+        interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" />
+    <reference id="notificationPublishService"
+        interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService" />
+    <odl:rpc-service id="odlArputilService"
+        interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService" />
+
+
+    <bean id="uniPortManager" class="org.opendaylight.unimgr.mef.netvirt.UniPortManager">
+        <argument ref="dataBroker" />
+    </bean>
+
+    <bean id="nodeConnectorListener"
+        class="org.opendaylight.unimgr.mef.netvirt.NodeConnectorListener">
+        <argument ref="dataBroker" />
+        <argument ref="uniPortManager" />
+            <argument value="false" />
+    </bean>
+
+    <bean id="evcListener" class="org.opendaylight.unimgr.mef.netvirt.EvcListener">
+        <argument ref="dataBroker" />
+        <argument ref="uniPortManager" />
+    </bean>
+
+    <bean id="ipvcListener" class="org.opendaylight.unimgr.mef.netvirt.IpvcListener">
+        <argument ref="dataBroker" />
+        <argument ref="uniPortManager" />
+        <argument ref="subnetListener" />
+    </bean>
+
+    <bean id="subnetListener" class="org.opendaylight.unimgr.mef.netvirt.SubnetListener">
+        <argument ref="dataBroker" />
+        <argument ref="notificationPublishService" />
+        <argument ref="qwMacListener" />
+    </bean>
+
+    <bean id="qwMacListener" class="org.opendaylight.unimgr.mef.netvirt.GwMacListener">
+        <argument ref="dataBroker" />
+        <argument ref="odlArputilService" />
+        <argument value="10" />
+    </bean>
+</blueprint>
+