HC2VPP-304 - add SRv6 policy module 80/11680/17
authorMichal Cmarada <[email protected]>
Fri, 15 Jun 2018 11:12:53 +0000 (13:12 +0200)
committerMarek Gradzki <[email protected]>
Tue, 19 Jun 2018 18:56:53 +0000 (18:56 +0000)
new models:
[email protected]
  (ietf draft for srte-policies)
[email protected]
  (augments oc-srte-policy model with VPP specific configuration)
[email protected]
  defines policy contexts for policies and candidate paths

new features:
- adds support for writing/reading SRv6 policies
- adds support for writing/reading L2 steering
- adds support for writing/reading L3 steering
- implements support for FIB table management (HC2VPP-345)

Change-Id: Ie83ac8ecdcc0e46086e1ecdaecbb811746151c2f
Signed-off-by: Michal Cmarada <[email protected]>
56 files changed:
srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/MplsLabelBuilder.java [new file with mode: 0644]
srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/SidValueTypeBuilder.java [new file with mode: 0644]
srv6/srv6-api/src/main/yang/[email protected] [new file with mode: 0755]
srv6/srv6-api/src/main/yang/[email protected] [new file with mode: 0644]
srv6/srv6-api/src/main/yang/[email protected] [new file with mode: 0644]
srv6/srv6-impl/asciidoc/Readme.adoc
srv6/srv6-impl/pom.xml
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/Srv6ModuleTest.java
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PoliciesTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/SteeringTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/JvppRequestTest.java
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/Srv6UtilTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizerTest.java [new file with mode: 0644]
srv6/srv6-impl/src/test/resources/named-segments.json [new file with mode: 0644]
srv6/srv6-impl/src/test/resources/policy.json [new file with mode: 0644]
srv6/srv6_policy_postman_collection.json [new file with mode: 0755]

diff --git a/srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/MplsLabelBuilder.java b/srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/MplsLabelBuilder.java
new file mode 100644 (file)
index 0000000..1afeaea
--- /dev/null
@@ -0,0 +1,20 @@
+package org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ *
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ */
+public class MplsLabelBuilder {
+    private MplsLabelBuilder() {
+        //Exists only to defeat instantiation.
+    }
+
+    public static MplsLabel getDefaultInstance(java.lang.String defaultValue) {
+        throw new java.lang.UnsupportedOperationException("Not yet implemented");
+    }
+
+}
diff --git a/srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/SidValueTypeBuilder.java b/srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/SidValueTypeBuilder.java
new file mode 100644 (file)
index 0000000..4bcbf5d
--- /dev/null
@@ -0,0 +1,20 @@
+package org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ *
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ */
+public class SidValueTypeBuilder {
+    private SidValueTypeBuilder() {
+        //Exists only to defeat instantiation.
+    }
+
+    public static SidValueType getDefaultInstance(java.lang.String defaultValue) {
+        throw new java.lang.UnsupportedOperationException("Not yet implemented");
+    }
+
+}
new file mode 100755 (executable)
index 0000000..bdb8c8a
--- /dev/null
@@ -0,0 +1,1507 @@
+module hc2vpp-oc-srte-policy {
+
+  /*** NAMESPACE / PREFIX DEFINITION ***/
+
+  namespace "http://cisco.com/ns/yang"+
+    "/oc-srte-policy";
+
+
+  prefix "oc-srte";
+
+  /*** LINKAGE (IMPORTS / INCLUDES) ***/
+
+  import ietf-inet-types { prefix "inet"; }
+
+  import ietf-interfaces { prefix if; }
+
+  import ietf-yang-types {
+    prefix "yang";
+  }
+
+  /*** META INFORMATION ***/
+
+  organization "Cisco Systems, Inc.";
+
+  contact
+    "Cisco Systems, Inc.
+     Customer Service
+
+     Postal: 170 West Tasman Drive
+     San Jose, CA 95134
+
+     E-mail: ";
+
+  description
+    "This module contains a collection of YANG definitions
+     for SR TE policy module.
+
+     Copyright (c) 2017 by Cisco Systems, Inc.
+     All rights reserved.";
+
+  revision "2017-09-18" {
+    description
+      "Initial version";
+    reference
+      "draft-filsfils-spring-segment-routing-policy";
+  }
+
+  /* Identities */
+  identity path-not-selected-reason {
+    description
+      "Base identity for which reasons for not selecting
+      candidate path are derived from";
+  }
+  identity path-not-selected-not-best {
+    base path-not-selected-reason;
+    description
+      "Higher preference path exists";
+  }
+  identity path-not-selected-no-active-segmet-list {
+    base path-not-selected-reason;
+    description
+      "Candidate path has no active segment list(s)";
+  }
+  identity path-not-selected-empty-segmet-list {
+    base path-not-selected-reason;
+    description
+      "Candidate path has empty segment list(s)";
+  }
+  identity path-not-selected-invalid-binding-sid {
+    base path-not-selected-reason;
+    description
+      "Candidate path has invalid binding SID";
+  }
+
+  identity resource-affinities-type {
+    description
+      "Base identity for resource affinities";
+  }
+  identity resource-aff-include-all {
+    base resource-affinities-type;
+    description
+      "The set of bitmap attributes all of which
+      must be present on a link so it is considered
+      acceptable";
+  }
+  identity resource-aff-include-any {
+    base resource-affinities-type;
+    description
+      "The set of bitmap attributes any of which
+      must be present on a link so it is considered
+      acceptable";
+  }
+  identity resource-aff-exclude-any {
+    base resource-affinities-type;
+    description
+      "The set of bitmap attributes any of which
+      present reders the link to be considered
+      unacceptable";
+  }
+
+  identity path-computation-method {
+    description
+     "base identity for supported path computation
+      mechanisms";
+  }
+  identity path-locally-computed {
+    base path-computation-method;
+    description
+      "indicates a constrained-path LSP in which the
+      path is computed by the local LER";
+  }
+  identity path-externally-queried {
+    base path-computation-method;
+    description
+     "Constrained-path in which the path is
+      obtained by querying an external source, such as a PCE server.
+      In the case that a path is defined to be externally queried, it
+      may also have associated explicit definitions (which are provided
+      to the external source to aid computation); and the path that is
+      returned by the external source is not required to provide a
+      wholly resolved path back to the originating system - that is to
+      say, some local computation may also be required";
+  }
+  identity path-explicitly-defined {
+    base path-computation-method;
+    description
+     "constrained-path LSP in which the path is
+      explicitly specified as a collection of strict or/and loose
+      hops";
+  }
+
+  identity provisioning-method-type {
+    description "Candidate path provisioning source type";
+  }
+  identity provisioning-method-config {
+    base provisioning-method-type;
+    description
+        "Candidate path is provisioned via configuration";
+  }
+  identity provisioning-method-bgp {
+    base provisioning-method-type;
+    description
+        "Candidate path is provisioned via BGP signaling";
+  }
+  identity provisioning-method-pcep {
+    base provisioning-method-type;
+    description
+        "Candidate path is provisioned via PCEP signaling";
+  }
+
+  /* Typdefs */
+  typedef segment-list-oper-state {
+    type enumeration {
+      enum ACTIVE {
+        description
+          "Segment-list is resolved and active in forwarding";
+      }
+      enum INACTIVE {
+        description
+          "Segment-list is unresolved and inactive in forwarding";
+      }
+    }
+    description
+      "Segment list operational state type";
+  }
+  typedef mpls-label {
+    type union {
+      type uint32 {
+        range 16..1048575;
+      }
+      type enumeration {
+        enum IPV4_EXPLICIT_NULL {
+          value 0;
+          description
+            "valid at the bottom of the label stack,
+            indicates that stack must be popped and packet forwarded
+            based on IPv4 header";
+        }
+        enum ROUTER_ALERT {
+          value 1;
+          description
+            "allowed anywhere in the label stack except
+            the bottom, local router delivers packet to the local CPU
+            when this label is at the top of the stack";
+        }
+        enum IPV6_EXPLICIT_NULL {
+          value 2;
+          description
+            "valid at the bottom of the label stack,
+            indicates that stack must be popped and packet forwarded
+            based on IPv6 header";
+        }
+        enum IMPLICIT_NULL {
+          value 3;
+          description
+            "assigned by local LSR but not carried in
+            packets";
+        }
+        enum ENTROPY_LABEL_INDICATOR {
+          value 7;
+          description
+            "Entropy label indicator, to allow an LSR
+            to distinguish between entropy label and applicaiton
+            labels RFC 6790";
+        }
+      }
+    }
+    description
+      "type for MPLS label value encoding";
+    reference "RFC 3032 - MPLS Label Stack Encoding";
+  }
+  typedef sid-value-type {
+    type union {
+      type mpls-label;
+      type inet:ip-address;
+    }
+    description "The SID value type";
+  }
+  typedef path-margin-type {
+    type enumeration {
+      enum relative {
+        value 1;
+        description "Path margin type relative";
+      }
+      enum absolute {
+        value 2;
+        description "Path margin type relative";
+      }
+    }
+    description "Path margin types";
+  }
+  typedef binding-sid-oper-state {
+    type enumeration {
+      enum ALLOC-PENDING {
+        value 1;
+        description "BSID is allocate pending";
+      }
+      enum PROG-PENDING {
+        value 2;
+        description "BSID is programed pending";
+      }
+      enum PROGRAMMED {
+        value 3;
+        description "BSID is programmed";
+      }
+      enum CONFLICT {
+        value 4;
+        description "BSID is in-conflict state";
+      }
+    }
+    description
+      "Binding SID operational state type";
+  }
+  typedef policy-admin-state {
+    type enumeration {
+      enum UP {
+        value 1;
+        description "SR policy is administratively up";
+      }
+      enum DOWN {
+        value 2;
+        description "SR policy is administratively down";
+      }
+    }
+    description "SR policy admin state";
+  }
+  typedef policy-oper-state {
+    type enumeration {
+      enum UP {
+        value 1;
+        description "SR policy is opertionally up";
+      }
+      enum DOWN {
+        value 2;
+        description "SR policy is opertionally down";
+      }
+    }
+    description "SR policy oper state";
+  }
+  typedef explicit-binding-sid-rule-type {
+    type enumeration {
+      enum fallback-dynamic {
+        value 1;
+        description
+            "Explicit Binding SID falls back to dynamic in
+            case explicit label is not available.";
+      }
+      enum enforce-srlb {
+        value 2;
+        description
+            "Explicit Binding SID is enforced with no
+             fallback if label does not fall in SRLB or
+             if no SRLB is configured";
+      }
+    }
+    description "SRTE binding SID explicit rule";
+  }
+  typedef segment-type {
+    type enumeration {
+      enum type-1 {
+        value 1;
+        description "SID only, in the form of MPLS Label";
+      }
+      enum type-2 {
+        value 2;
+        description "SID only, in the form of IPv6 address";
+      }
+      enum type-3 {
+        value 3;
+        description "IPv4 Node Address with optional SID";
+      }
+      enum type-4 {
+        value 4;
+        description "IPv6 Node Address with optional SID";
+      }
+      enum type-5 {
+        value 5;
+        description "IPv4 Address + index with optional SID";
+      }
+      enum type-6 {
+        value 6;
+        description "IPv4 Local and Remote addresses with optional SID";
+      }
+      enum type-7 {
+        value 7;
+        description "IPv6 Address + index with optional SID";
+      }
+      enum type-8 {
+        value 8;
+        description "IPv6 Local and Remote addresses with optional SID";
+      }
+    }
+    description "SR segment type";
+  }
+  typedef dataplane-type {
+    type enumeration {
+      enum mpls {
+        value 1;
+        description "Segment-routing MPLS";
+      }
+      enum srv6 {
+        value 2;
+        description "Segment-routing v6";
+      }
+    }
+
+    // Add all the types in draft-ietf-idr-segment-routing-te-policy
+    description "SRTE path hop";
+  }
+  typedef path-metric-type {
+    type enumeration {
+      enum igp {
+        value 1;
+        description "IGP path metric type";
+      }
+      enum te {
+        value 2;
+        description "TE path metric type";
+      }
+    }
+    description "Path metric types";
+  }
+  typedef binding-sid-alloc-mode {
+    type enumeration {
+      enum explicit {
+        value 1;
+        description "Explicitly specified BSID";
+      }
+      enum dynamic {
+        value 2;
+        description "Dynamically allocated BSID";
+      }
+    }
+    description "binding SID allocation mode";
+  }
+  typedef auto-route-metric-type {
+    type enumeration {
+      enum constant {
+        value 1;
+        description "Autoroute constant metric type";
+      }
+      enum relative {
+        value 2;
+        description "Autoroute relative metric type";
+      }
+    }
+    description "SRTE auto route metric";
+  }
+
+  grouping ENABLE {
+    description
+      "Reusable node that enables a specific feature";
+    leaf enable {
+      type empty;
+      description "True only";
+    }
+  }
+
+  grouping affinity-constraints-contents_config {
+    description
+      "Path affinities constraints grouping";
+    leaf constraint {
+      type identityref {
+        base resource-affinities-type;
+      }
+      description "Affinities constraint";
+    }
+    list affinity-names {
+      key "name";
+      leaf name {
+        type leafref {
+          path "../config/name";
+        }
+        description "Affinity name";
+      }
+      container config {
+        description
+          "Configuration intended parameters";
+        leaf name {
+          type string;
+          description "Affinity name";
+        }
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        leaf name {
+          type string;
+          description "Affinity name";
+        }
+      }
+      description
+        "List of named affinities";
+    }
+  }
+
+  grouping affinity-constraints {
+    description
+      "Path affinities grouping";
+    container affinity-constraints {
+      description
+        "Path affinities container";
+      list affinity-constraint {
+        key "constraint";
+        description
+          "List of named affinity constraints";
+        leaf constraint {
+          type leafref {
+            path "../config/constraint";
+          }
+          description "Affinities constraint";
+        }
+        container config {
+          description
+            "Configuration intended parameters";
+          uses affinity-constraints-contents_config;
+        }
+        container state {
+          config false;
+          description
+            "Configuration applied parameters and state";
+          uses affinity-constraints-contents_config;
+        }
+      }
+    }
+  }
+
+  grouping segment_config {
+    description "Segment properties grouping";
+    leaf index {
+      type uint32;
+      description "Segment index";
+    }
+    leaf type {
+      type segment-type;
+      description "Segment type";
+    }
+    leaf ip-address {
+      when "../segment-type = 'type-3' or " +
+           "../segment-type = 'type-4' or " +
+           "../segment-type = 'type-5' or " +
+           "../segment-type = 'type-7'";
+      type inet:ip-address;
+      description "Segment IPv4/v6 address";
+    }
+    leaf local-ip-address {
+      when "../segment-type = 'type-6' or " +
+           "../segment-type = 'type-8'";
+      type inet:ip-address;
+      description "Segment local IPv4/v6 adjacency address";
+    }
+    leaf remote-ip-address {
+      when "../segment-type = 'type-6' or " +
+           "../segment-type = 'type-8'";
+      type inet:ip-address;
+      description "Segment remote IPv4/v6 adjacency address";
+    }
+    leaf sid-index {
+      when "../segment-type = 'type-5' or " +
+           "../segment-type = 'type-7'";
+      type uint32;
+      description "Segment SID index";
+    }
+    leaf sid-value  {
+      type sid-value-type;
+      description "Segment MPLS Label";
+    }
+  }
+
+  grouping segment-properties {
+    description
+      "SR segment properties grouping";
+    container config {
+      description
+        "Configuration intended parameters";
+      uses segment_config;
+    }
+    container state {
+      config false;
+      description
+        "Configuration applied parameters and state";
+      uses segment_config;
+    }
+  }
+
+  grouping segment-list_config {
+    description
+      "Segment SID list properties configuration grouping";
+    leaf name {
+      type string;
+      description "Segment-list name";
+    }
+  }
+
+  grouping segment-list-properties {
+    description "Segment SID list properties";
+    container config {
+      description
+        "Configuration intended parameters";
+      uses segment-list_config;
+    }
+    container state {
+      config false;
+      description
+        "Configuration applied parameters and state";
+      uses segment-list_config;
+    }
+  }
+
+  grouping named-segment-lists {
+    description
+      "Named segment lists grouping";
+    container named-segment-lists {
+      description "Segment-lists properties";
+
+      list named-segment-list {
+        key "name";
+        description "Segment-list properties";
+        leaf name {
+          type leafref {
+            path "../config/name";
+          }
+          description "Segment list name";
+        }
+        uses segment-list-properties;
+        container segments {
+          description
+            "Segments for given segment list";
+
+          list segment {
+            key "index";
+            leaf index {
+              type leafref {
+                path "../config/index";
+              }
+              description "The segment index";
+            }
+            description "Configure Segment/hop at the index";
+            uses segment-properties;
+          }
+        }
+      }
+    }
+  }
+
+  grouping named-affinity-bitmap_config {
+    description
+      "Global named administrative groups configuration
+      grouping";
+    leaf name {
+      type string;
+      description
+        "A string name that uniquely identifies a TE
+        interface named admin-group";
+    }
+    leaf bit-position {
+      type uint32;
+      description
+        "Bit position representing the administrative group";
+    }
+  }
+  grouping named-affinity-bitmaps {
+    description
+      "Global named administrative groups grouping";
+    container named-affinity-bitmaps {
+      description "TE named admin groups container";
+      list named-affinity-bitmap {
+        key "name";
+        description
+          "List of named TE admin-groups";
+        leaf name {
+          type leafref {
+            path "../config/name";
+          }
+          description "Admin-group name";
+        }
+        container config {
+          description
+            "Configuration intended parameters";
+          uses named-affinity-bitmap_config;
+        }
+        container state {
+          config false;
+          description
+            "Configuration applied parameters and state";
+          uses named-affinity-bitmap_config;
+        }
+      }
+    }
+  }
+
+  grouping explicit-binding-sid-fallback-rules_config {
+    description "Binding SID fallback rules";
+    leaf fallback-rule {
+      type explicit-binding-sid-rule-type;
+      description "Binding sid explicit rule";
+    }
+  }
+
+  grouping explicit-binding-sid-rules {
+    description
+      "Explicit binding SID rules";
+    container explicit-binding-sid-rules {
+      description "Binding sid rules";
+      container config {
+        description
+          "Configuration intended parameters";
+        uses explicit-binding-sid-fallback-rules_config;
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        uses explicit-binding-sid-fallback-rules_config;
+      }
+    }
+  }
+
+  grouping binding-sid_config {
+    description
+      "Binding SID configuration properties grouping";
+    leaf alloc-mode {
+      type binding-sid-alloc-mode;
+      description "Binding SID type";
+    }
+    leaf type {
+      type dataplane-type;
+      description "Binding SID type";
+    }
+    leaf value {
+      when "../alloc-mode = 'explicit'" {
+        description "This leaf is valid only if alloc-mode is explicit";
+      }
+      /*
+        TODO (HC2VPP-356): This was valid for MPLS label only, there is no definition for SRv6.
+                           Changed to sid-value-type to support both SRv6 and MPLS
+
+      type uint32 {
+        range "16..1048575";
+      }
+      */
+      type sid-value-type;
+      description "Segment SID";
+    }
+  }
+
+  grouping binding-sid_state {
+    description
+      "Binding SID state properties grouping";
+    leaf oper-state {
+      type binding-sid-oper-state;
+      description
+        "Binding SID operational state";
+    }
+    leaf forwarding-stats-pkts {
+      type yang:counter64;
+      description "Number of packets forwarded";
+    }
+    leaf forwarding-stats-bytes {
+      type yang:counter64;
+      units "byte";
+      description "Number of bytes forwarded";
+    }
+  }
+
+  grouping binding-sid-properties {
+    description
+      "Binding SID properties grouping";
+    container binding-sid {
+      description "Binding Segment ID";
+      container config {
+        description
+          "Configuration intended parameters";
+        uses binding-sid_config;
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        uses binding-sid_config;
+        uses binding-sid_state;
+      }
+    }
+  }
+
+  grouping autoroute-metric_config {
+    description
+      "Autoroute metric configuration properties grouping";
+    leaf metric-type {
+      type auto-route-metric-type;
+      description "Metric type";
+    }
+    leaf metric-constant {
+      type uint32 {
+        range "0..1000";
+      }
+      description "Autoroute constant metric";
+    }
+    leaf metric-relative {
+      type int32 {
+        range "-10..10";
+      }
+      description "Autoroute relative metric";
+    }
+  }
+
+  grouping autoroute-metric {
+    description
+      "Autoroute metric properties grouping";
+    container metric {
+      description "Autoroute metric properties";
+      container config {
+        description
+          "Configuration intended parameters";
+        uses autoroute-metric_config;
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        uses autoroute-metric_config;
+      }
+    }
+  }
+
+  grouping prefixes-properties {
+    description
+      "Autoroute include prefix table properties grouping";
+    container prefixes {
+      description
+        "Autoroute include prefix table properties";
+      container config {
+        description
+          "Configuration intended parameters";
+        leaf prefixes-all {
+          type boolean;
+          default 'false';
+          description
+            "Indicates whether all prefixes allowed to be
+            steered over the policy";
+        }
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        leaf prefixes-all {
+          type boolean;
+          description
+            "Indicates whether all prefixes allowed to be
+            steered over the policy";
+        }
+      }
+
+      list prefix {
+        key  "ip-prefix";
+        description "Autoroute IP prefix to include";
+        leaf ip-prefix {
+          type leafref {
+            path "../config/ip-prefix";
+          }
+          description "Autoroute prefix IP address";
+        }
+        uses include-prefix;
+      }
+    }
+  }
+
+  grouping autoroute-include {
+    description
+      "Autoroute include properties grouping";
+    container autoroute-include {
+      description
+        "Autoroute include properties container";
+      container config {
+        description
+          "Configuration intended parameters";
+        uses autoroute-metric_config;
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        uses autoroute-metric_config;
+      }
+      uses prefixes-properties;
+    }
+  }
+
+  grouping include-prefix_config {
+    description
+      "Autoroute include prefix configuration";
+    leaf ip-prefix {
+      type inet:ip-prefix;
+      description "Autoroute prefix IP address";
+    }
+  }
+
+  grouping include-prefix {
+    description
+      "Autoroute include prefixes";
+    container config {
+      description
+        "Configuration intended parameters";
+      uses include-prefix_config;
+    }
+    container state {
+      config false;
+      description
+        "Configuration applied parameters and state";
+      uses include-prefix_config;
+    }
+  }
+
+  grouping metric-properties_config {
+    description
+      "SR path metric properties";
+    leaf metric-type {
+      type path-metric-type;
+      description "Metric type";
+    }
+    leaf metric-margin-absolute {
+      type uint32 {
+        range "0..2147483647";
+      }
+      description "Absolute metric margin";
+    }
+    leaf metric-margin-relative {
+      type uint32 {
+        range "0..100";
+      }
+      description "Relative metric margin";
+    }
+  }
+
+  grouping path-computation-constraints_config {
+    description
+      "Candidate path constraints configuration grouping";
+    leaf sid-limit {
+      type uint32 {
+        range "0..255";
+      }
+      description "The path maximum number of SIDs";
+    }
+    leaf metric-limit {
+      type uint32;
+      description "The path accumulative metric limit";
+    }
+  }
+
+  grouping path-computation-constraints {
+    description
+      "Candidate path computation constraints grouping";
+    container path-computation-constratints {
+      description
+        "Candidate path computation constraints";
+      container config {
+        description
+          "Configuration intended parameters";
+        uses path-computation-constraints_config;
+        uses metric-properties_config;
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        uses path-computation-constraints_config;
+        uses metric-properties_config;
+      }
+      uses affinity-constraints;
+    }
+  }
+
+  grouping path-forwarding_state {
+    description "Policy Forwarding path information";
+    leaf outgoing-interface {
+      type if:interface-ref;
+      description "Outgoing interface handle";
+    }
+    leaf next-hop-address {
+      type inet:ip-address;
+      description "Nexthop address";
+    }
+    leaf next-hop-table {
+      type uint32;
+      description "Table ID for nexthop address";
+    }
+    list out-label-stack {
+      description
+        "Output label stack for this path";
+      leaf index {
+        type mpls-label;
+        description
+          "The index in the MPLS label stack, index 0 indicates
+           the top of the stack";
+      }
+      leaf label {
+        type mpls-label;
+        description "Path outgoing labels";
+      }
+    }
+    leaf is-protected {
+      type boolean;
+      description "Is this path protected ?";
+    }
+    leaf is-pure-backup {
+      type boolean;
+      description "Is this path a pure backup ?";
+    }
+    leaf weight {
+      type uint32;
+      description "Path's weight for W-ECMP balancing";
+    }
+    leaf primary-path-id {
+      type uint8;
+      description "path Id";
+    }
+    leaf backup-path-id {
+      type uint8;
+      description "Backup path Id";
+    }
+    leaf forwarding-stats-pkts {
+      type yang:counter64;
+      description "Number of packets forwarded on this path";
+    }
+    leaf forwarding-stats-bytes {
+      type yang:counter64;
+      units "byte";
+      description "Number of bytes forwarded on this path";
+    }
+  }
+
+  grouping pathlist-forwarding_state {
+    description "Policy forwarding information";
+    list path-list {
+      description "Forwarding paths";
+      uses path-forwarding_state;
+    }
+  }
+
+  grouping path-segment-list_config {
+    description
+      "Candidate path segment list configuration properties";
+    leaf name {
+      type string;
+      description "Segment-list name";
+    }
+    leaf weight {
+      type uint32;
+      description "Segment-list weighted loadshare";
+    }
+  }
+
+  grouping path-segment-list_state {
+    description
+      "Path segment list state grouping";
+    leaf oper-state {
+      type segment-list-oper-state;
+      description
+        "The segment list operation state";
+    }
+    container forwarding {
+      description
+        "Path segment list forwarding state";
+      uses pathlist-forwarding_state;
+    }
+  }
+
+  grouping path-segment-list {
+    description
+      "Candidate path segment list(s) properties";
+    container config {
+      description
+        "Configuration intended parameters";
+      uses path-segment-list_config;
+    }
+    container state {
+      config false;
+      description
+        "Configuration applied parameters and state";
+      uses path-segment-list_config;
+      uses path-segment-list_state;
+    }
+  }
+
+  grouping path-segment-list-properties {
+    description
+      "Candidate path properties ";
+    uses path-computation-constraints;
+    container segment-lists {
+      description
+        "Path segment list(s) properties";
+      list segment-list {
+        key "name";
+        description "SR policy candidate path segment lists";
+
+        leaf name {
+          type leafref {
+            path "../config/name";
+          }
+          description "Segment-list name";
+        }
+        uses path-segment-list;
+      }
+    }
+  }
+
+  grouping candidate-path_config {
+    description
+      "Candidate path configuration properties grouping";
+    leaf name {
+      type string;
+      description "Candidate path name";
+    }
+    leaf provisioning-method {
+      type identityref {
+        base provisioning-method-type;
+      }
+      description "Candidate path provisioning method";
+    }
+    leaf computation-method {
+      type identityref {
+        base path-computation-method;
+      }
+      description "Path computation method";
+    }
+    leaf preference {
+      type uint32 {
+        range "1..65535";
+      }
+      description "Candidate path preference";
+    }
+    leaf distinguisher {
+      type uint32;
+      description "Candidate path distinguisher";
+    }
+  }
+
+  grouping candidate-path_state {
+    description
+      "Candidate path state properties grouping";
+    leaf is-active-path {
+      type boolean;
+      default 'false';
+      description
+        "True if the candidate path is ACTIVE, False otherwise";
+    }
+    leaf not-selected-reason {
+      type identityref {
+        base path-not-selected-reason;
+      }
+      description
+        "Candidate path not selected reason";
+    }
+  }
+
+  grouping unauthorized-steering-apps {
+    description
+      "Unauthorized to steer application properties";
+    container steering-unauthorized-applications {
+      presence
+        "Presence of this container enables unauthorized
+         steering filter. By default steering is authorized";
+      description
+        "Unauthorized to steer application properties";
+      container config {
+        description
+          "Configuration intended parameters";
+        leaf-list steering-unauthorized-application {
+          type string;
+          description
+            "List of unauthorized steering applications";
+        }
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        leaf-list steering-unauthorized-application {
+          type string;
+          description
+            "List of unauthorized steering applications";
+        }
+      }
+    }
+  }
+
+  grouping policy-properties_config {
+    description
+      "SR policy configuration grouping";
+    leaf name {
+      type string {
+        length "1..128";
+      }
+      description "SR policy name";
+    }
+    leaf color {
+      type uint32 {
+        range "1..4294967295";
+      }
+      description "Color associated with the policy";
+    }
+    leaf endpoint {
+      type inet:ip-address;
+      description "Policy end point IP address";
+    }
+    leaf admin-state {
+      type policy-admin-state;
+      default 'UP';
+      description
+        "SR policy administrative state, true for
+        enabled, false for disabled";
+    }
+  }
+
+  grouping policy-properties_state {
+    description
+      "SR policy property grouping";
+    leaf oper-state {
+      type policy-oper-state;
+      description
+        "SR policy operational state";
+    }
+    leaf transition-count {
+      type uint32;
+      description "Indicates number of up/down transitions";
+    }
+    leaf up-time {
+      type yang:date-and-time;
+      description "Policy up time in seconds";
+    }
+    leaf down-time {
+      type yang:date-and-time;
+      description "Policy down time in seconds";
+    }
+  }
+
+  grouping policy-properties {
+    description
+      "SR policy properties";
+    container config {
+      description
+        "Configuration intended parameters";
+      uses policy-properties_config;
+    }
+    container state {
+      config false;
+      description
+        "Configuration applied parameters and state";
+      uses policy-properties_config;
+      uses policy-properties_state;
+    }
+    uses binding-sid-properties;
+    uses unauthorized-steering-apps;
+  }
+
+  grouping candidate-paths {
+    description "SR policy candidate path grouping";
+    container candidate-paths {
+      description "SR policy candidate path(s) ";
+
+      list candidate-path {
+        key "provisioning-method preference distinguisher";
+        description "SR policy Candidate path(s) list entry";
+
+        leaf name {
+          type leafref {
+            path "../config/name";
+          }
+          description "Candidate-path name";
+        }
+        leaf provisioning-method {
+          type leafref {
+            path "../config/provisioning-method";
+          }
+          description "Candidate path provisioning method";
+        }
+        /*
+            TODO (HC2VPP-356): fixed path for preference, probably copy/paste error
+                               before pointed to "../config/name"
+        */
+        leaf preference {
+          type leafref {
+            path "../config/preference";
+          }
+          description "Candidate path preference";
+        }
+        leaf distinguisher {
+          type leafref {
+            path "../config/distinguisher";
+          }
+          description "Candidate path distinguisher";
+        }
+        container config {
+          description
+            "Configuration intended parameters";
+          uses candidate-path_config;
+        }
+        container state {
+          config false;
+          description
+            "Configuration applied parameters and state";
+          uses candidate-path_config;
+          uses candidate-path_state;
+        }
+        uses binding-sid-properties;
+        uses unauthorized-steering-apps;
+        uses path-segment-list-properties;
+      }
+    }
+  }
+
+  grouping policies {
+    description "SR policy grouping";
+    container policies {
+      description "SR Policy container";
+
+      list policy {
+        key "color endpoint";
+        unique "name";
+        description "SR Policy properties";
+
+        leaf name {
+          type leafref {
+            path "../config/name";
+          }
+          description "SR policy name";
+        }
+        leaf color {
+          type leafref {
+            path "../config/color";
+          }
+          description "Policy color";
+        }
+        leaf endpoint {
+          type leafref {
+            path "../config/endpoint";
+          }
+          description "Policy endpoint";
+        }
+
+        uses policy-properties;
+
+        uses candidate-paths;
+
+        uses autoroute-include;
+      }
+    }
+  }
+
+  grouping on-demand-colors_state {
+    description
+      "On demand color template state properties grouping";
+    leaf registered-application-count {
+      type uint8;
+      description "The number of registered application count";
+    }
+    leaf unused-duration {
+      type yang:date-and-time;
+      description
+        "Duration for which the on-demand policy has no
+         no registered clients";
+
+    }
+  }
+
+  grouping on-demand-colors_config {
+    description
+      "On demand color template configuration grouping";
+    leaf color {
+      type uint32;
+      description "The on-demand SR policy color";
+    }
+  }
+
+  grouping on-demand-colors {
+    description "On demand color properties grouping";
+    container on-demand-colors {
+      description "On demand color properties";
+      list on-demand-color {
+        key "color";
+        description "On demand color template list";
+
+        leaf color {
+          type leafref {
+            path "../config/color";
+          }
+          description "The on-demand SR policy color";
+        }
+        container config {
+          description
+            "Configuration intended parameters";
+          uses on-demand-colors_config;
+        }
+        container state {
+          config false;
+          description
+            "Configuration applied parameters and state";
+          uses on-demand-colors_config;
+          uses on-demand-colors_state;
+        }
+        uses path-segment-list-properties;
+      }
+    }
+  }
+
+  grouping segment-routing-te-attributes {
+    description "SRTE attributes configuration grouping";
+    container config {
+      description
+        "Configuration parameters for interface TE
+         attributes";
+      uses srte-interface-attributes_config;
+    }
+    container state {
+      config false;
+      description
+        "State parameters for interface TE metric";
+      uses srte-interface-attributes_config;
+    }
+  }
+
+  grouping srte-interface-attributes_config {
+    description
+      "global level definitions for interfaces
+      on which TE is run";
+
+    leaf name {
+      type if:interface-ref;
+      description
+        "reference to interface name";
+    }
+
+    leaf te-metric {
+      type uint32;
+      description
+        "TE specific metric for the link";
+    }
+
+    leaf-list named-affinities {
+      type string;
+      description
+        "list of admin groups (by name) on the interface";
+    }
+  }
+
+
+  grouping interfaces-grouping {
+    description
+      "Interface TE configuration data grouping";
+    container interfaces {
+      description
+        "Configuration data model for TE interfaces.";
+      list interface {
+        key "interface";
+        description "TE interfaces.";
+        leaf interface {
+          type if:interface-ref;
+          description
+            "TE interface name.";
+        }
+        /* TE interface parameters */
+        uses segment-routing-te-attributes;
+      }
+    }
+  }
+
+
+
+  grouping pcc-pce-peers_config {
+    description
+      "The PCC's PCE peers configuration properties";
+    leaf address {
+      type inet:ip-address;
+      description "Remote PCE address";
+    }
+    leaf precedence {
+      type uint32 {
+        range "0..255";
+      }
+      mandatory true;
+      description "Precedence value of this PCE";
+    }
+  }
+
+  grouping pcc_config {
+    description
+      "The PCC configuration properties";
+    leaf source-address {
+      type inet:ip-address-no-zone;
+      description
+        "Local source IP address to use on PCEP
+        sessions";
+    }
+    leaf delegation-timeout {
+      type uint32 {
+        range "0..4294967295";
+      }
+      description
+        "The maximum time delegated SR-TE policies can
+        remain up without an active connection to a
+        PCE";
+    }
+  }
+
+  grouping pcc {
+    description "Path computation client SRTE properties grouping";
+    container pcc {
+      description "Path Computation Client";
+
+      container pce-peers {
+        description "PCE peer list configuration";
+
+        list pce-peer {
+          key "address";
+          description "PCE peer list";
+          leaf address {
+            type leafref {
+              path "../config/address";
+            }
+            description "Remote PCE address";
+          }
+          // TODO (HC2VPP-356): PCE peer contains leaf address pointing to config/address, but config params were
+          //                    not encapsulated in config container.
+          container config {
+            description
+              "Configuration intended parameters";
+            uses pcc-pce-peers_config;
+          }
+        }
+      }
+      container config {
+        description
+          "Configuration intended parameters";
+        uses pcc_config;
+      }
+      container state {
+        config false;
+        description
+          "Configuration applied parameters and state";
+        uses pcc_config;
+      }
+    }
+  }
+
+  /* Main SR container */
+  container segment-routing {
+    description "Main segment routing container";
+
+    container traffic-engineering {
+      description "Traffic Engineering container";
+
+      uses named-segment-lists;
+
+      uses named-affinity-bitmaps;
+
+      uses explicit-binding-sid-rules;
+
+      uses policies;
+
+      uses interfaces-grouping;
+
+      uses on-demand-colors;
+    }
+  }
+}
new file mode 100644 (file)
index 0000000..2820d62
--- /dev/null
@@ -0,0 +1,126 @@
+module policy-context {
+    yang-version 1;
+    namespace "urn:honeycomb:params:xml:ns:yang:policy:context";
+    prefix "policy-ctx";
+
+    import hc2vpp-oc-srte-policy {
+       prefix "oc-srte";
+       revision-date 2017-09-18;
+    }
+
+    import ietf-inet-types {
+       prefix "inet";
+    }
+
+    import naming-context {
+       prefix "nc";
+    }
+
+    import yang-ext {
+       prefix "ext";
+    }
+
+    organization
+        "FD.io - The Fast Data Project";
+
+    contact
+        "Hc2vpp Wiki <https://wiki.fd.io/view/Hc2vpp>
+         Mailing List <[email protected]>";
+
+    description
+        "This module provides mapping between SRV6 policy identifiers (color and endpoint)
+         defined in the hc2vpp-oc-srte-policy module and identifiers used by the VPP SRV6
+         policy plugin. VPP uses BSID as policy identifier, which is mapped to color and
+         endpoint identifiers in the model.
+
+         The mapping is managed internally by the HC SRV6 plugin.
+         It is exposed as operational state data for debugging purposes.
+
+         Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+
+         Licensed under the Apache License, Version 2.0 (the 'License');
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at:
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an 'AS IS' BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.";
+
+    revision "2018-06-07" {
+        description "Initial revision.";
+    }
+
+    grouping srv6-policy-context-attributes {
+        container srv6-policy-mappings {
+            list srv6-policy-mapping {
+                key "bsid";
+
+                leaf name {
+                    type string;
+                    description "Srv6 policy name";
+                }
+
+                leaf color {
+                    type uint32;
+                    description "Srv6 policy color";
+                }
+
+                leaf endpoint {
+                    type inet:ipv6-address;
+                    description "Policy endpoint represented by IPv6 address";
+                }
+
+                leaf bsid {
+                    type inet:ipv6-address;
+                    description "Policy represented by IPv6 address";
+                }
+            }
+        }
+
+    }
+
+    grouping srv6-candidate-path-context-attributes {
+        container srv6-candidate-path-mappings {
+            list srv6-candidate-path-mapping {
+                key "bsid";
+
+                leaf name {
+                    type string;
+                    description "Srv6 policy candidate path name";
+                }
+
+                leaf provisioning-method {
+                    type identityref {
+                        base oc-srte:provisioning-method-type;
+                    }
+                    description "Srv6 policy candidate path provisioning-method";
+                }
+
+                leaf preference {
+                    type uint32;
+                    description "Srv6 policy candidate path preference";
+                }
+
+                leaf distinguisher {
+                    type uint32;
+                    description "Srv6 policy candidate path distinguisher";
+                }
+
+                leaf bsid {
+                    type inet:ipv6-address;
+                    description "Candidate path represented by IPv6 address";
+                }
+            }
+        }
+    }
+
+    augment /nc:contexts {
+        ext:augment-identifier "srv6-policy-context-augmentation";
+        uses srv6-policy-context-attributes;
+        uses srv6-candidate-path-context-attributes;
+    }
+}
new file mode 100644 (file)
index 0000000..3aafe8a
--- /dev/null
@@ -0,0 +1,151 @@
+module vpp-oc-srte-policy {
+
+    namespace "urn:hc2vpp:params:xml:ns:yang:vpp-oc-srte-policy";
+    prefix vpp-oc-srte-policy;
+
+    import hc2vpp-oc-srte-policy {
+        prefix "oc-srte";
+        revision-date 2017-09-18;
+    }
+
+    import vpp-fib-table-management {
+        prefix fib-management;
+        revision-date 2018-05-21;
+    }
+
+    import ietf-interfaces { prefix if; }
+
+    import yang-ext { prefix "ext"; }
+
+    organization
+        "FD.io - The Fast Data Project";
+
+    contact
+        "Hc2vpp Wiki <https://wiki.fd.io/view/Hc2vpp>
+         Mailing List <[email protected]>";
+
+    description
+        "This module provides VPP specific configuration of L2 steering policy configuration
+         and vpp policy configuration for SRv6 policies.
+
+         Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+
+         Licensed under the Apache License, Version 2.0 (the 'License');
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at:
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an 'AS IS' BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.";
+
+    revision 2018-05-14 {
+        description "initial revision";
+    }
+
+    typedef segment-routing-policy-behavior {
+        type enumeration {
+            enum SegmentRoutingHeaderInsert {
+                value 0;
+            }
+            enum Encapsulation {
+                value 1;
+            }
+        }
+    }
+
+    typedef segment-routing-policy-type {
+        type enumeration {
+            enum Default {
+                value 0;
+            }
+            enum Spray {
+                value 1;
+            }
+        }
+    }
+
+    grouping sr-interfaces-config {
+        leaf input-interface {
+           type if:interface-ref;
+           description "Incoming interface for L2 traffic";
+        }
+    }
+
+    grouping sr-interfaces {
+        list interface {
+            key "input-interface";
+
+            leaf input-interface {
+                type leafref {
+                    path "../config/input-interface";
+                }
+                description "Incoming interface for L2 traffic";
+            }
+
+            container config {
+                uses sr-interfaces-config;
+            }
+
+            container state {
+                config false;
+                uses sr-interfaces-config;
+            }
+        }
+    }
+
+    grouping sr-policy-config {
+        leaf policy-type {
+           type segment-routing-policy-type;
+           description "SR policy type definition. Either Spray (1) or Default (0)";
+        }
+
+        leaf policy-behavior {
+           type segment-routing-policy-behavior;
+           description "SR policy behavior definition. Either Encapsulation (1) or SegmentRoutingHeaderInsert (0)";
+        }
+
+        leaf table-id {
+            type fib-management:fib-table-list-ref;
+            description "VRF index reference.";
+        }
+        leaf address-family {
+            type fib-management:address-family-type;
+            description "Address family reference. For SRv6 has to be always Ipv6.";
+        }
+    }
+
+    grouping sr-policy {
+        container config {
+            uses sr-policy-config;
+        }
+
+        container state {
+            config false;
+            uses sr-policy-config;
+        }
+    }
+
+    augment "/oc-srte:segment-routing/oc-srte:traffic-engineering/oc-srte:policies/oc-srte:policy/oc-srte:autoroute-include/" {
+        description "This augments autoroute-include in policy configuration with L2 steering interfaces.";
+        ext:augment-identifier "vpp-l2-autoroute-include-augmentation";
+
+        container interfaces {
+        description "L2 steering policy configuration dataplane.";
+          uses sr-interfaces;
+        }
+    }
+
+    augment "/oc-srte:segment-routing/oc-srte:traffic-engineering/oc-srte:policies/oc-srte:policy/" {
+        description "This augments vpp specific configuration for srte policy.";
+        ext:augment-identifier "vpp-sr-policy-augmentation";
+
+        container vpp-sr-policy {
+        description "VPP SR policy configuration dataplane.";
+          uses sr-policy;
+        }
+    }
+}
index 73b6f1b..bf841a3 100644 (file)
 - encapsulation source write and delete requests and customizers,
   based on augmentation of routing model in: +
   `hc2vpp-ietf-routing:routing/hc2vpp-ietf-srv6-base:srv6/hc2vpp-ietf-srv6-base:encapsulation`
+- Srv6 policy read,write and delete requests and customizers based on [email protected] +
+  model, defined in: +
+  `hc2vpp-oc-srte-policy:segment-routing/traffic-engineering/policies` +
+  and +
+  `hc2vpp-oc-srte-policy:segment-routing/traffic-engineering/named-segment-lists`
+- Srv6 L3 steering read,write and delete requests and customizers based on [email protected] +
+  model, defined in: +
+  `hc2vpp-oc-srte-policy:segment-routing/traffic-engineering/policies/policy/autoroute-include/prefixes`
+- Srv6 L2 steering read,write and delete requests and customizers based on augmentation of +
+  [email protected] model in [email protected] model, defined in: +
+    `hc2vpp-oc-srte-policy:segment-routing/traffic-engineering/policies/policy/autoroute-include/vpp-oc-srte-policy:interfaces`
+
 
 == VPP mapping
 
   *IPv6 SR Set SRv6 encapsulation source params:* +
       *bsid* is the bindingSID of the SR Policy +
       *index* is the index of the SR policy
-
+- srv6 policy configuration maps to *sr_policy_add* in VPP API: +
+  *IPv6 SR policy add params:* +
+      *bsid* is the bindingSID of the SR Policy +
+      *weight* is the weight of the sid list. optional. +
+      *is_encap* is the behavior of the SR policy. (0.SRH insert // 1.Encapsulation) +
+      *type* is the type of the SR policy. (0.Default // 1.Spray) +
+      *fib_table* is the VRF where to install the FIB entry for the BSID +
+      *sids* is a srv6_sid_list object
+- srv6 steering configuration maps to *sr_steering_add_del* in VPP API: +
+  *IPv6 SR steering add/del params:* +
+      *is_del* +
+      *bsid* is the bindingSID of the SR Policy (alt to sr_policy_index) +
+      *sr_policy* is the index of the SR Policy (alt to bsid) +
+      *table_id* is the VRF where to install the FIB entry for the BSID +
+      *prefix* is the IPv4/v6 address for L3 traffic type +
+      *mask_width* is the mask for L3 traffic type +
+      *sw_if_index* is the incoming interface for L2 traffic +
+      *traffic_type* describes the type of traffic
 
 == Supported End function configurations:
 
index 08fed21..422cd16 100644 (file)
@@ -35,8 +35,7 @@
         <dependency>
             <groupId>io.fd.hc2vpp.routing</groupId>
             <artifactId>routing-impl</artifactId>
-            <version>1.18.07-SNAPSHOT</version>
-            <scope>compile</scope>
+            <version>${project.version}</version>
         </dependency>
         <!-- Honeycomb infrastructure -->
         <dependency>
index ec91b21..3e51a4b 100644 (file)
@@ -21,13 +21,19 @@ import static io.fd.hc2vpp.srv6.Srv6Configuration.DEFAULT_LOCATOR_LENGTH;
 import com.google.inject.AbstractModule;
 import com.google.inject.Singleton;
 import com.google.inject.multibindings.Multibinder;
+import io.fd.hc2vpp.srv6.read.Srv6PolicyReaderFactory;
 import io.fd.hc2vpp.srv6.read.Srv6ReaderFactory;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManagerImpl;
 import io.fd.hc2vpp.srv6.util.LocatorContextManager;
 import io.fd.hc2vpp.srv6.util.LocatorContextManagerImpl;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.hc2vpp.srv6.util.PolicyContextManagerImpl;
 import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistry;
 import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistryProvider;
 import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionWriteBindingRegistry;
 import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionWriteBindingRegistryProvider;
+import io.fd.hc2vpp.srv6.write.Srv6PolicyWriterFactory;
 import io.fd.hc2vpp.srv6.write.Srv6WriterFactory;
 import io.fd.honeycomb.translate.read.ReaderFactory;
 import io.fd.honeycomb.translate.write.WriterFactory;
@@ -35,7 +41,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class Srv6Module extends AbstractModule {
-
     private static final Logger LOG = LoggerFactory.getLogger(Srv6Module.class);
 
     @Override
@@ -45,20 +50,27 @@ public class Srv6Module extends AbstractModule {
         requestInjection(Srv6Configuration.class);
 
         bind(LocatorContextManager.class).toInstance(new LocatorContextManagerImpl(DEFAULT_LOCATOR_LENGTH));
+        bind(PolicyContextManager.class).toInstance(new PolicyContextManagerImpl());
+        bind(CandidatePathContextManager.class).toInstance(new CandidatePathContextManagerImpl());
 
         bind(LocalSidFunctionReadBindingRegistry.class).toProvider(LocalSidFunctionReadBindingRegistryProvider.class)
                 .in(Singleton.class);
 
         bind(LocalSidFunctionWriteBindingRegistry.class).toProvider(LocalSidFunctionWriteBindingRegistryProvider.class)
                 .in(Singleton.class);
+        LOG.info("Binding SrPolicy context");
 
         LOG.info("Injecting SRv6 writers");
         final Multibinder<WriterFactory> writeBinder = Multibinder.newSetBinder(binder(), WriterFactory.class);
         writeBinder.addBinding().to(Srv6WriterFactory.class);
+        LOG.info("Injecting SRv6 Policy writers");
+        writeBinder.addBinding().to(Srv6PolicyWriterFactory.class);
 
         LOG.info("Injecting SRv6 readers");
         final Multibinder<ReaderFactory> readerBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class);
         readerBinder.addBinding().to(Srv6ReaderFactory.class);
+        LOG.info("Injecting SRv6 Policy readers");
+        readerBinder.addBinding().to(Srv6PolicyReaderFactory.class);
 
         LOG.info("SRv6 module successfully configured");
     }
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java
new file mode 100644 (file)
index 0000000..19f6254
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6;
+
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentRouting;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.BindingSid;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.CandidatePaths;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentLists;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.Segments;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.Segment;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.SegmentLists;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.Policies;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.Config;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.routing.TrafficEngineering;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppL2AutorouteIncludeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.VppSrPolicy;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev180313.Routing;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.Locator1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.multi.paths.v6.Paths;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.multi.paths.v6.paths.Path;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.routing.srv6.locators.locator.Static;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.routing.srv6.locators.locator._static.LocalSids;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6._static.cfg.Sid;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.End;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndB6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndB6Encaps;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndBm;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDt4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDt46;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDt6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDx2;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDx4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDx6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndT;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndX;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.Routing1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.routing.Srv6;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.encap.Encapsulation;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.Locators;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.locators.Locator;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.locators.locator.Prefix;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Srv6PolicyIIds {
+    // SRV6 POLICIES
+    //segment-routing
+    public static final InstanceIdentifier<SegmentRouting> SR = InstanceIdentifier.create(SegmentRouting.class);
+    public static final InstanceIdentifier<TrafficEngineering> SR_TE = SR.child(TrafficEngineering.class);
+
+    //segment-routing/traffic-engineering/named-segment-lists
+    public static final InstanceIdentifier<NamedSegmentLists> SR_TE_NSLS = SR_TE.child(NamedSegmentLists.class);
+    public static final InstanceIdentifier<NamedSegmentList> SR_TE_NSLS_NSL_IID =
+            SR_TE_NSLS.child(NamedSegmentList.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.Config>
+            SR_TE_NSLS_NSL_CFG = SR_TE_NSLS_NSL_IID
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.Config.class);
+    public static final InstanceIdentifier<Segments> SR_TE_NSLS_NSL_SGS = SR_TE_NSLS_NSL_IID.child(Segments.class);
+    public static final InstanceIdentifier<Segment> SR_TE_NSLS_NSL_SGS_SG = SR_TE_NSLS_NSL_SGS.child(Segment.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.Config>
+            SR_TE_NSLS_NSL_SGS_SG_CFG = SR_TE_NSLS_NSL_SGS_SG
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.Config.class);
+    public static final InstanceIdentifier<NamedSegmentList> NSL = InstanceIdentifier.create(NamedSegmentList.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.State>
+            NSL_STATE = NSL
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.State.class);
+    public static final InstanceIdentifier<Segments> NSL_SGS = NSL.child(Segments.class);
+    public static final InstanceIdentifier<Segment> NSL_SGS_SG = NSL_SGS.child(Segment.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.State>
+            NSL_SGS_SG_STATE = NSL_SGS_SG
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.State.class);
+
+    // policies
+    public static final InstanceIdentifier<Policies> SR_TE_PLS = SR_TE.child(Policies.class);
+    public static final InstanceIdentifier<Policy> SR_TE_PLS_POL = SR_TE_PLS.child(Policy.class);
+    public static final InstanceIdentifier<BindingSid> SR_TE_PLS_POL_BSID = SR_TE_PLS_POL.child(BindingSid.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config>
+            SR_TE_PLS_POL_BSID_CFG = SR_TE_PLS_POL_BSID
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config.class);
+
+    // policy
+    public static final InstanceIdentifier<Policy> SR_POLICY = InstanceIdentifier.create(Policy.class);
+    public static final InstanceIdentifier<Config> SR_POLICY_CFG = SR_POLICY.child(Config.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.State>
+            SR_POLICY_STATE = SR_POLICY
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.State.class);
+
+    // policies/policy/autoroute-include
+    public static final InstanceIdentifier<AutorouteInclude> SR_TE_PLS_POL_AI =
+            SR_TE_PLS_POL.child(AutorouteInclude.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.autoroute.include.Config>
+            SR_TE_PLS_POL_AI_CFG = SR_TE_PLS_POL_AI
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.autoroute.include.Config.class);
+
+    // policies/policy/autoroute-include/prefixes
+    public static final InstanceIdentifier<Prefixes> SR_TE_PLS_POL_AI_PFS = SR_TE_PLS_POL_AI.child(Prefixes.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config>
+            SR_TE_PLS_POL_AI_PFS_CFG = SR_TE_PLS_POL_AI_PFS
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State>
+            SR_TE_PLS_POL_AI_PFS_STATE = SR_TE_PLS_POL_AI_PFS
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix>
+            SR_TE_PLS_POL_AI_PFS_PF_IID = SR_TE_PLS_POL_AI_PFS
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix>
+            SR_TE_PLS_POL_AI_PFS_PF = InstanceIdentifier
+            .create(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.Config>
+            SR_TE_PLS_POL_AI_PFS_PF_CFG = SR_TE_PLS_POL_AI_PFS_PF
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.Config.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.State>
+            SR_TE_PLS_POL_AI_PFS_PF_STATE = SR_TE_PLS_POL_AI_PFS_PF
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.State.class);
+
+    // policies/policy/autoroute-include/interfaces
+    public static final InstanceIdentifier<VppL2AutorouteIncludeAugmentation> SR_TE_PLS_POL_AI_IFAUG =
+            SR_TE_PLS_POL_AI.augmentation(VppL2AutorouteIncludeAugmentation.class);
+    public static final InstanceIdentifier<Interfaces> SR_TE_PLS_POL_AI_IFCS =
+            SR_TE_PLS_POL_AI_IFAUG.child(Interfaces.class);
+    public static final InstanceIdentifier<Interface> SR_TE_PLS_POL_AI_IFCS_IFC_IID =
+            SR_TE_PLS_POL_AI_IFCS.child(Interface.class);
+    public static final InstanceIdentifier<Interface> SR_TE_PLS_POL_AI_IFCS_IFC =
+            InstanceIdentifier.create(Interface.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config>
+            SR_TE_PLS_POL_AI_IFCS_IFC_CFG = SR_TE_PLS_POL_AI_IFCS_IFC
+            .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.State>
+            SR_TE_PLS_POL_AI_IFCS_IFC_STATE = SR_TE_PLS_POL_AI_IFCS_IFC
+            .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.State.class);
+
+    // policy/binding-sid
+    public static final InstanceIdentifier<BindingSid> SR_POLICY_BSID = SR_POLICY.child(BindingSid.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State>
+            SR_POLICY_BSID_STATE = SR_POLICY_BSID
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State>
+            SR_POLICY_BSID_CFG = SR_POLICY_BSID
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class);
+
+    // policy/vpp-sr-policy
+    public static final InstanceIdentifier<VppSrPolicyAugmentation> SR_POLICY_VPP =
+            SR_POLICY.augmentation(VppSrPolicyAugmentation.class);
+    public static final InstanceIdentifier<VppSrPolicy> SR_POLICY_VPP_SR =
+            SR_POLICY_VPP.child(VppSrPolicy.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config>
+            SR_POLICY_VPP_SR_CFG = SR_POLICY_VPP_SR
+            .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.State>
+            SR_POLICY_VPP_SR_STATE = SR_POLICY_VPP_SR
+            .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.State.class);
+
+    // policy/candidate-paths
+    public static final InstanceIdentifier<CandidatePaths> SR_POLICY_CPS = SR_POLICY.child(CandidatePaths.class);
+    public static final InstanceIdentifier<CandidatePath> SR_POLICY_CPS_CP = SR_POLICY_CPS.child(CandidatePath.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.Config>
+            SR_POLICY_CPS_CP_CFG = SR_POLICY_CPS_CP
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.Config.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.State>
+            SR_POLICY_CPS_CP_STATE = SR_POLICY_CPS_CP
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.State.class);
+
+    public static final InstanceIdentifier<SegmentLists> SR_POLICY_CPS_CP_SLS =
+            SR_POLICY_CPS_CP.child(SegmentLists.class);
+    public static final InstanceIdentifier<SegmentList> SR_POLICY_CPS_CP_SLS_SL =
+            SR_POLICY_CPS_CP_SLS.child(SegmentList.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.Config>
+            SR_POLICY_CPS_CP_SLS_SL_CFG = SR_POLICY_CPS_CP_SLS_SL
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.Config.class);
+    public static final InstanceIdentifier<BindingSid> SR_POLICY_CPS_CP_BSID = SR_POLICY_CPS_CP.child(BindingSid.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config>
+            SR_POLICY_CPS_CP_BSID_CFG = SR_POLICY_CPS_CP_BSID
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config.class);
+    public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State>
+            SR_POLICY_CPS_CP_BSID_STATE = SR_POLICY_CPS_CP_BSID
+            .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class);
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java
new file mode 100644 (file)
index 0000000..79b18d2
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.read.policy.NamedSegmentCustomizer;
+import io.fd.hc2vpp.srv6.read.policy.PolicyCustomizer;
+import io.fd.hc2vpp.srv6.read.steering.InterfaceCustomizer;
+import io.fd.hc2vpp.srv6.read.steering.PrefixCustomizer;
+import io.fd.hc2vpp.srv6.read.steering.PrefixesStateCustomizer;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.LocatorContextManager;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.honeycomb.translate.impl.read.GenericListReader;
+import io.fd.honeycomb.translate.impl.read.GenericReader;
+import io.fd.honeycomb.translate.read.ReaderFactory;
+import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentRoutingBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteIncludeBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentListsBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.PoliciesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.routing.TrafficEngineeringBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppL2AutorouteIncludeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.InterfacesBuilder;
+
+public class Srv6PolicyReaderFactory implements ReaderFactory {
+
+    @Inject
+    @Named("interface-context")
+    private NamingContext interfaceContext;
+
+    @Inject
+    private FutureJVppCore vppApi;
+
+    @Inject
+    private LocatorContextManager locatorContext;
+
+    @Inject
+    private PolicyContextManager policyContext;
+
+    @Inject
+    private CandidatePathContextManager candidateContext;
+
+    @Override
+    public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
+        registry.addStructuralReader(Srv6PolicyIIds.SR, SegmentRoutingBuilder.class);
+        registry.addStructuralReader(Srv6PolicyIIds.SR_TE, TrafficEngineeringBuilder.class);
+        registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS, PoliciesBuilder.class);
+        registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI, AutorouteIncludeBuilder.class);
+        registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS, PrefixesBuilder.class);
+        registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS, InterfacesBuilder.class);
+        registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFAUG,
+                VppL2AutorouteIncludeAugmentationBuilder.class);
+        registry.addStructuralReader(Srv6PolicyIIds.SR_TE_NSLS, NamedSegmentListsBuilder.class);
+
+        registry.subtreeAdd(ImmutableSet
+                        .of(Srv6PolicyIIds.SR_POLICY_BSID, Srv6PolicyIIds.SR_POLICY_BSID_STATE,
+                                Srv6PolicyIIds.SR_POLICY_VPP, Srv6PolicyIIds.SR_POLICY_VPP_SR,
+                                Srv6PolicyIIds.SR_POLICY_VPP_SR_STATE, Srv6PolicyIIds.SR_POLICY_STATE,
+                                Srv6PolicyIIds.SR_POLICY_CPS, Srv6PolicyIIds.SR_POLICY_CPS_CP,
+                                Srv6PolicyIIds.SR_POLICY_CPS_CP_STATE, Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID,
+                                Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID_STATE, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS,
+                                Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL_CFG),
+                new GenericListReader<>(Srv6PolicyIIds.SR_TE_PLS_POL,
+                        new PolicyCustomizer(vppApi, policyContext, candidateContext)));
+        registry.add(
+                new GenericReader<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_STATE,
+                        new PrefixesStateCustomizer(vppApi)));
+
+        registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_STATE),
+                new GenericListReader<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_IID,
+                        new PrefixCustomizer(vppApi)));
+        registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_STATE),
+                new GenericListReader<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_IID,
+                        new InterfaceCustomizer(vppApi, interfaceContext)));
+
+        registry.subtreeAdd(
+                ImmutableSet.of(Srv6PolicyIIds.NSL_STATE, Srv6PolicyIIds.NSL_SGS, Srv6PolicyIIds.NSL_SGS_SG,
+                        Srv6PolicyIIds.NSL_SGS_SG_STATE),
+                new GenericListReader<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_IID,
+                        new NamedSegmentCustomizer(vppApi, policyContext, candidateContext)));
+    }
+}
index 312280d..41c33f9 100644 (file)
@@ -43,7 +43,7 @@ public class Srv6ReaderFactory implements ReaderFactory {
     private LocalSidFunctionReadBindingRegistry bindingRegistry;
 
     @Inject
-    protected LocatorContextManager locatorContext;
+    private LocatorContextManager locatorContext;
 
     @Override
     public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) {
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java
new file mode 100644 (file)
index 0000000..9f9c0e2
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.read.policy;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.srv6.read.policy.request.PolicyReadRequest;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentListsBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class NamedSegmentCustomizer extends FutureJVppCustomizer
+        implements ListReaderCustomizer<NamedSegmentList, NamedSegmentListKey, NamedSegmentListBuilder> {
+    private final PolicyContextManager policyContext;
+    private final CandidatePathContextManager candidateContext;
+
+    public NamedSegmentCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                                  final PolicyContextManager policyContext,
+                                  final CandidatePathContextManager candidateContext) {
+        super(futureJVppCore);
+        this.policyContext = policyContext;
+        this.candidateContext = candidateContext;
+    }
+
+    @Nonnull
+    @Override
+    public List<NamedSegmentListKey> getAllIds(@Nonnull final InstanceIdentifier<NamedSegmentList> instanceIdentifier,
+                                               @Nonnull final ReadContext readContext) throws ReadFailedException {
+        PolicyReadRequest
+                policyReadRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext);
+        policyReadRequest.checkValid();
+        return policyReadRequest.readNamedSegmentListKeys(instanceIdentifier, readContext);
+    }
+
+    @Override
+    public void merge(@Nonnull final Builder<? extends DataObject> builder,
+                      @Nonnull final List<NamedSegmentList> list) {
+        ((NamedSegmentListsBuilder) builder).setNamedSegmentList(list);
+    }
+
+    @Nonnull
+    @Override
+    public NamedSegmentListBuilder getBuilder(@Nonnull final InstanceIdentifier<NamedSegmentList> instanceIdentifier) {
+        return new NamedSegmentListBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<NamedSegmentList> instanceIdentifier,
+                                      @Nonnull final NamedSegmentListBuilder builder,
+                                      @Nonnull final ReadContext readContext) throws ReadFailedException {
+        PolicyReadRequest readRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext);
+        readRequest.readNamedSegmentList(instanceIdentifier, builder, readContext);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java
new file mode 100644 (file)
index 0000000..c4c323b
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.policy;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.srv6.read.policy.request.PolicyReadRequest;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.PoliciesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PolicyCustomizer extends FutureJVppCustomizer
+        implements ListReaderCustomizer<Policy, PolicyKey, PolicyBuilder> {
+
+    private final PolicyContextManager policyContext;
+    private final CandidatePathContextManager candidateContext;
+
+    public PolicyCustomizer(@Nonnull final FutureJVppCore futureJVppCore, PolicyContextManager policyContext,
+                            final CandidatePathContextManager candidateContext) {
+        super(futureJVppCore);
+        this.policyContext = policyContext;
+        this.candidateContext = candidateContext;
+    }
+
+    @Nonnull
+    @Override
+    public List<PolicyKey> getAllIds(@Nonnull InstanceIdentifier<Policy> id, @Nonnull ReadContext context)
+            throws ReadFailedException {
+        PolicyReadRequest policyReadRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext);
+        return policyReadRequest.readAllKeys(id, context);
+    }
+
+    @Override
+    public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Policy> readData) {
+        ((PoliciesBuilder) builder).setPolicy(readData);
+    }
+
+    @Nonnull
+    @Override
+    public PolicyBuilder getBuilder(@Nonnull InstanceIdentifier<Policy> id) {
+        return new PolicyBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull InstanceIdentifier<Policy> id, @Nonnull PolicyBuilder builder,
+                                      @Nonnull ReadContext ctx) throws ReadFailedException {
+        PolicyReadRequest readRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext);
+        readRequest.readSpecific(id, ctx, builder);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java
new file mode 100644 (file)
index 0000000..8117d4d
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.policy.request;
+
+import com.google.common.base.Preconditions;
+import io.fd.hc2vpp.srv6.read.ReadRequest;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.JVppRequest;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.hc2vpp.srv6.util.Srv6Util;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.SrPoliciesDetails;
+import io.fd.vpp.jvpp.core.dto.SrPoliciesDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.SrPoliciesDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import io.fd.vpp.jvpp.core.types.Srv6Sid;
+import io.fd.vpp.jvpp.core.types.Srv6SidList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.BindingSidAllocMode;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.PathExplicitlyDefined;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.PolicyAdminState;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentListOperState;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentType;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SidValueType;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.BindingSidBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.StateBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.CandidatePathsBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePathBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.SegmentsBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.Segment;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.SegmentBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.SegmentKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.SegmentListsBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentListBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyBehavior;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyType;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.VppSrPolicyBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMapping;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMapping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PolicyReadRequest extends JVppRequest
+        implements ReadRequest<Policy, PolicyKey, PolicyBuilder> {
+
+    private static final String DASH_SEPARATOR = "-";
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyReadRequest.class);
+    private static final SrPoliciesDump STATIC_DUMP_REQUEST = new SrPoliciesDump();
+    private static final SrPoliciesDetailsReplyDump STATIC_EMPTY_REPLY = new SrPoliciesDetailsReplyDump();
+    private final PolicyContextManager policyCtx;
+    private final CandidatePathContextManager candidateCtx;
+    private final DumpCacheManager<SrPoliciesDetailsReplyDump, Void> dumpManager;
+
+    public PolicyReadRequest(FutureJVppCore futureJVpp, PolicyContextManager policyCtx,
+                             final CandidatePathContextManager candidateCtx) {
+        super(futureJVpp);
+        this.policyCtx = policyCtx;
+        this.candidateCtx = candidateCtx;
+        this.dumpManager = new DumpCacheManager.DumpCacheManagerBuilder<SrPoliciesDetailsReplyDump, Void>().acceptOnly(
+                SrPoliciesDetailsReplyDump.class)
+                .withExecutor((identifier, params) -> getReplyForRead(
+                        getApi().srPoliciesDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier))
+                .build();
+    }
+
+    @Nonnull
+    public List<PolicyKey> readAllKeys(@Nonnull InstanceIdentifier<Policy> id, @Nonnull ReadContext ctx)
+            throws ReadFailedException {
+        return dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream()
+                .map(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr))
+                .map(bsid -> parsePolicyKey(ctx, bsid))
+                .collect(Collectors.toList());
+    }
+
+    private PolicyKey parsePolicyKey(final @Nonnull ReadContext ctx, final Ipv6Address bsid) {
+        Srv6PolicyMapping policy = policyCtx.getPolicy(bsid, ctx.getMappingContext());
+        return new PolicyKey(policy.getColor(), new IpAddress(policy.getEndpoint()));
+    }
+
+    @Override
+    public void readSpecific(@Nonnull InstanceIdentifier<Policy> id, @Nonnull ReadContext ctx,
+                             @Nonnull PolicyBuilder builder) throws ReadFailedException {
+        PolicyKey key = id.firstKeyOf(Policy.class);
+        Ipv6Address bsid =
+                policyCtx.getPolicyBsid(key.getColor(), key.getEndpoint().getIpv6Address(), ctx.getMappingContext());
+
+        dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream()
+                .filter(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue()
+                        .equals(bsid.getValue()))
+                .findFirst()
+                .ifPresent((SrPoliciesDetails details) -> bindPolicy(details, ctx, builder));
+    }
+
+    private void bindPolicy(SrPoliciesDetails srPoliciesDetails, @Nonnull ReadContext ctx,
+                            final PolicyBuilder builder) {
+
+        Ipv6Address bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr);
+        Srv6PolicyMapping policy = policyCtx.getPolicy(bsid, ctx.getMappingContext());
+        IpAddress endpoint = new IpAddress(policy.getEndpoint());
+        builder.setName(policy.getName()).setEndpoint(endpoint).setColor(policy.getColor());
+        builder.setKey(new PolicyKey(policy.getColor(), endpoint));
+        builder.setBindingSid(new BindingSidBuilder().setState(
+                new StateBuilder().setType(DataplaneType.Srv6).setAllocMode(BindingSidAllocMode.Explicit)
+                        .setValue(new SidValueType(new IpAddress(bsid))).build()).build());
+        builder.addAugmentation(VppSrPolicyAugmentation.class, new VppSrPolicyAugmentationBuilder()
+                .setVppSrPolicy(new VppSrPolicyBuilder().setState(
+                        new org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.StateBuilder()
+                                .setPolicyBehavior(
+                                        SegmentRoutingPolicyBehavior.forValue((int) srPoliciesDetails.isEncap))
+                                .setPolicyType(SegmentRoutingPolicyType.forValue((int) srPoliciesDetails.type))
+                                .setTableId(new VniReference(Integer.toUnsignedLong(srPoliciesDetails.fibTable)))
+                                .setAddressFamily(Ipv6.class)
+                                .build()).build())
+                .build());
+
+        builder.setState(
+                new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.StateBuilder()
+                        .setName(policy.getName()).setEndpoint(endpoint)
+                        .setColor(policy.getColor()).setAdminState(PolicyAdminState.UP)
+                        .build());
+
+        builder.setCandidatePaths(
+                new CandidatePathsBuilder().setCandidatePath(resolveCandidatePaths(srPoliciesDetails, ctx)).build());
+    }
+
+    private List<CandidatePath> resolveCandidatePaths(final SrPoliciesDetails srPoliciesDetails,
+                                                      final ReadContext ctx) {
+        List<CandidatePath> candidatePaths = new ArrayList<>();
+        //only one candidate path can be selected and present on device at the same time
+        if (srPoliciesDetails.sidLists == null) {
+            LOG.debug("No policy segments found for BSID: {}", srPoliciesDetails.bsid);
+            return candidatePaths;
+        }
+        Ipv6Address bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr);
+        Srv6CandidatePathMapping candidatePath =
+                candidateCtx.getCandidatePath(bsid, ctx.getMappingContext());
+
+        CandidatePathBuilder candidatePathBuilder =
+                new CandidatePathBuilder()
+                        .setDistinguisher(candidatePath.getDistinguisher())
+                        .setPreference(candidatePath.getPreference())
+                        .setProvisioningMethod(candidatePath.getProvisioningMethod())
+                        .setName(candidatePath.getName());
+
+        candidatePathBuilder.setState(
+                new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.StateBuilder()
+                        .setDistinguisher(candidatePath.getDistinguisher())
+                        .setPreference(candidatePath.getPreference())
+                        .setProvisioningMethod(candidatePath.getProvisioningMethod())
+                        .setComputationMethod(PathExplicitlyDefined.class)
+                        .setName(candidatePath.getName())
+                        .build());
+        candidatePathBuilder.setBindingSid(new BindingSidBuilder().setState(
+                new StateBuilder().setAllocMode(BindingSidAllocMode.Explicit).setType(DataplaneType.Srv6)
+                        .setValue(new SidValueType(new IpAddress(bsid))).build()).build());
+
+        List<SegmentList> segments = new ArrayList<>();
+        for (Srv6SidList sidlist : srPoliciesDetails.sidLists) {
+            long weight = Integer.toUnsignedLong(sidlist.weight);
+            SegmentListBuilder segmentListBuilder =
+                    new SegmentListBuilder().setName(Srv6Util.getCandidatePathName(bsid, weight));
+            segmentListBuilder.setState(
+                    new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.StateBuilder()
+                            .setName(Srv6Util.getCandidatePathName(bsid, weight))
+                            .setWeight(weight)
+                            .setOperState(SegmentListOperState.ACTIVE)
+                            .build());
+            segments.add(segmentListBuilder.build());
+        }
+        candidatePathBuilder.setSegmentLists(new SegmentListsBuilder().setSegmentList(segments).build());
+        candidatePaths.add(candidatePathBuilder.build());
+        return candidatePaths;
+    }
+
+    public List<NamedSegmentListKey> readNamedSegmentListKeys(final InstanceIdentifier<NamedSegmentList> id,
+                                                              final ReadContext ctx) throws ReadFailedException {
+        return dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream()
+                .map(srPoliciesDetails -> {
+                    String bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue();
+                    return Arrays.stream(srPoliciesDetails.sidLists).map(srv6SidList -> srv6SidList.weight)
+                            .map(weight -> bsid + DASH_SEPARATOR + weight).collect(Collectors.toList());
+                }).flatMap(Collection::stream).map(NamedSegmentListKey::new).distinct().collect(Collectors.toList());
+    }
+
+    public void readNamedSegmentList(final InstanceIdentifier<NamedSegmentList> id,
+                                     final NamedSegmentListBuilder builder,
+                                     final ReadContext ctx)
+            throws ReadFailedException {
+        NamedSegmentListKey key = id.firstKeyOf(NamedSegmentList.class);
+        builder.setKey(key)
+                .setName(key.getName())
+                .setState(
+                        new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.StateBuilder()
+                                .setName(key.getName())
+                                .build());
+
+        Long weight = parseWeight(key);
+        String bsid = parseBsid(key);
+        Preconditions.checkNotNull(bsid, "Weight/Bsid not resolved for Iid: {}", id);
+
+        builder.setSegments(new SegmentsBuilder().build());
+        dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream()
+                .filter(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue()
+                        .equals(bsid))
+                .forEach(srPoliciesDetails -> Arrays.stream(srPoliciesDetails.sidLists)
+                        .forEach(srv6SidList -> {
+                            if (srv6SidList.weight == weight.intValue()) {
+                                List<Segment> segments = IntStream.range(0, srv6SidList.numSids)
+                                        .mapToObj(i -> parseSrv6Sid(i, srv6SidList.sids[i]))
+                                        .collect(Collectors.toList());
+                                builder.setSegments(new SegmentsBuilder().setSegment(segments).build());
+                            }
+                        }));
+    }
+
+    private Segment parseSrv6Sid(final int i, final Srv6Sid srv6Sid) {
+        // shifting index by 1 so it matches original indexing
+        long index = i + 1;
+        SegmentBuilder builder = new SegmentBuilder().setKey(new SegmentKey(index)).setState(
+                new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.StateBuilder()
+                        .setIndex(index)
+                        .setType(SegmentType.Type2)
+                        .setSidValue(new SidValueType(
+                                new IpAddress(new Ipv6Address(arrayToIpv6AddressNoZone(srv6Sid.addr)))))
+                        .build());
+        return builder.build();
+    }
+
+
+    private Long parseWeight(final NamedSegmentListKey key) {
+        String[] values = key.getName().split(DASH_SEPARATOR);
+
+        return values.length == 2
+                ? Long.parseLong(values[1])
+                : 0;
+    }
+
+    private String parseBsid(final NamedSegmentListKey key) {
+        String[] values = key.getName().split(DASH_SEPARATOR);
+        return values.length == 2 ? values[0] : null;
+    }
+
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java
new file mode 100644 (file)
index 0000000..9151a98
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.read.steering.request.L2SteeringRequest;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.InterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceCustomizer extends FutureJVppCustomizer
+        implements ListReaderCustomizer<Interface, InterfaceKey, InterfaceBuilder> {
+
+    private final NamingContext interfaceContext;
+
+    public InterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                               @Nonnull final NamingContext interfaceContext) {
+        super(futureJVppCore);
+        this.interfaceContext = interfaceContext;
+    }
+
+    @Nonnull
+    @Override
+    public List<InterfaceKey> getAllIds(@Nonnull InstanceIdentifier<Interface> id, @Nonnull ReadContext context)
+            throws ReadFailedException {
+        return
+                new L2SteeringRequest(getFutureJVpp(), interfaceContext).readAllKeys(id, context);
+    }
+
+    @Override
+    public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Interface> readData) {
+        ((InterfacesBuilder) builder).setInterface(readData);
+    }
+
+    @Nonnull
+    @Override
+    public InterfaceBuilder getBuilder(@Nonnull InstanceIdentifier<Interface> id) {
+        return new InterfaceBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull InstanceIdentifier<Interface> id, @Nonnull InterfaceBuilder builder,
+                                      @Nonnull ReadContext ctx) throws ReadFailedException {
+        L2SteeringRequest readRequest = new L2SteeringRequest(getFutureJVpp(), interfaceContext);
+        readRequest.readSpecific(id, ctx, builder);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java
new file mode 100644 (file)
index 0000000..b0ee7c3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.srv6.read.steering.request.L3SteeringRequest;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PrefixCustomizer extends FutureJVppCustomizer
+        implements ListReaderCustomizer<Prefix, PrefixKey, PrefixBuilder> {
+
+    public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) {
+        super(futureJVppCore);
+    }
+
+    @Nonnull
+    @Override
+    public List<PrefixKey> getAllIds(@Nonnull InstanceIdentifier<Prefix> id, @Nonnull ReadContext context)
+            throws ReadFailedException {
+        return
+                new L3SteeringRequest(getFutureJVpp()).readAllKeys(id, context);
+    }
+
+    @Override
+    public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Prefix> readData) {
+        ((PrefixesBuilder) builder).setPrefix(readData);
+    }
+
+    @Nonnull
+    @Override
+    public PrefixBuilder getBuilder(@Nonnull InstanceIdentifier<Prefix> id) {
+        return new PrefixBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull InstanceIdentifier<Prefix> id, @Nonnull PrefixBuilder builder,
+                                      @Nonnull ReadContext ctx) throws ReadFailedException {
+        L3SteeringRequest readRequest = new L3SteeringRequest(getFutureJVpp());
+        readRequest.readSpecific(id, ctx, builder);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java
new file mode 100644 (file)
index 0000000..b099939
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.read.steering;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.srv6.read.steering.request.L3SteeringRequest;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.StateBuilder;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PrefixesStateCustomizer extends FutureJVppCustomizer implements ReaderCustomizer<State, StateBuilder> {
+
+    public PrefixesStateCustomizer(@Nonnull final FutureJVppCore futureJVppCore) {
+        super(futureJVppCore);
+    }
+
+    @Nonnull
+    @Override
+    public StateBuilder getBuilder(@Nonnull final InstanceIdentifier<State> instanceIdentifier) {
+        return new StateBuilder();
+    }
+
+    @Override
+    public void readCurrentAttributes(@Nonnull final InstanceIdentifier<State> instanceIdentifier,
+                                      @Nonnull final StateBuilder stateBuilder, @Nonnull final ReadContext readContext)
+            throws ReadFailedException {
+        L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp());
+        List<IpPrefix> ipPrefixes =
+                request.readAllIpPrefixes(RWUtils.cutId(instanceIdentifier, Prefixes.class), readContext);
+        // checks whether L3 steering contains default routes to steer all traffic to SRv6 policy. If found sets
+        // allPrefixes flag to true in autoroute-include/prefixes/state
+        boolean allPrefixes = ipPrefixes.containsAll(
+                ImmutableSet.of(new IpPrefix(new Ipv4Prefix("0.0.0.0/0")), new IpPrefix(new Ipv6Prefix("::/0"))));
+
+        stateBuilder.setPrefixesAll(allPrefixes);
+    }
+
+    @Override
+    public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final State state) {
+        ((PrefixesBuilder) builder).setState(state);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java
new file mode 100644 (file)
index 0000000..eb93707
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering.request;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.read.ReadRequest;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetails;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.StateBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Request for steering of L2 traffic
+ */
+
+public class L2SteeringRequest extends SteeringRequest
+        implements ReadRequest<Interface, InterfaceKey, InterfaceBuilder> {
+
+    static final int L2_TRAFFIC_TYPE = 2;
+    private final NamingContext ifcNamingContext;
+
+    public L2SteeringRequest(FutureJVppCore api, NamingContext namingContext) {
+        super(api);
+        this.ifcNamingContext = namingContext;
+    }
+
+    @Override
+    @Nonnull
+    public List<InterfaceKey> readAllKeys(@Nonnull InstanceIdentifier<Interface> identifier, @Nonnull ReadContext ctx)
+            throws ReadFailedException {
+        return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY)
+                .srSteeringPolDetails.stream()
+                .filter(srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) == L2_TRAFFIC_TYPE)
+                .map(srSteeringPolDetails -> srSteeringPolDetails.swIfIndex)
+                .map(ifIndex -> new InterfaceKey(ifcNamingContext.getName(ifIndex, ctx.getMappingContext())))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public void readSpecific(@Nonnull InstanceIdentifier<Interface> identifier, @Nonnull ReadContext ctx,
+                             @Nonnull InterfaceBuilder builder) throws ReadFailedException {
+        int index =
+                ifcNamingContext.getIndex(identifier.firstKeyOf(Interface.class).getInputInterface(),
+                        ctx.getMappingContext());
+
+        dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY)
+                .srSteeringPolDetails.stream()
+                .filter(srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) == L2_TRAFFIC_TYPE)
+                .filter(srSteeringPolDetails -> srSteeringPolDetails.swIfIndex == index)
+                .findFirst()
+                .ifPresent(srSteeringPolDetails -> parseL2Steering(srSteeringPolDetails, builder, ctx));
+    }
+
+    private void parseL2Steering(SrSteeringPolDetails srSteeringPolDetails, final InterfaceBuilder builder,
+                                      ReadContext ctx) {
+        String name = ifcNamingContext.getName(srSteeringPolDetails.swIfIndex, ctx.getMappingContext());
+        builder.setInputInterface(name).setKey(new InterfaceKey(name))
+                .setState(new StateBuilder().setInputInterface(name).build());
+    }
+}
+
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java
new file mode 100644 (file)
index 0000000..1043746
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering.request;
+
+import com.google.common.base.Preconditions;
+import io.fd.hc2vpp.srv6.read.ReadRequest;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetails;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.StateBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Request for steering of L3 traffic
+ */
+
+public class L3SteeringRequest extends SteeringRequest
+        implements ReadRequest<Prefix, PrefixKey, PrefixBuilder> {
+
+    private static final int L3_TRAFFIC_TYPE_IPV6 = 6;
+    private static final int L3_TRAFFIC_TYPE_IPV4 = 4;
+
+    public L3SteeringRequest(final FutureJVppCore api) {
+        super(api);
+    }
+
+    @Override
+    public void checkValid() {
+        super.checkValid();
+    }
+
+    @Override
+    @Nonnull
+    public List<PrefixKey> readAllKeys(@Nonnull InstanceIdentifier<Prefix> identifier, @Nonnull ReadContext ctx)
+            throws ReadFailedException {
+        return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY)
+                .srSteeringPolDetails.stream()
+                .filter(
+                        srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) !=
+                                L2SteeringRequest.L2_TRAFFIC_TYPE)
+                .map(this::parseL3SteeringKey)
+                .collect(Collectors.toList());
+    }
+
+    public List<IpPrefix> readAllIpPrefixes(@Nonnull InstanceIdentifier<Prefixes> identifier, @Nonnull ReadContext ctx)
+            throws ReadFailedException {
+        return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY)
+                .srSteeringPolDetails.stream()
+                .filter(
+                        srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) !=
+                                L2SteeringRequest.L2_TRAFFIC_TYPE)
+                .map(this::parseIpPrefix)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public void readSpecific(@Nonnull InstanceIdentifier<Prefix> identifier, @Nonnull ReadContext ctx,
+                             @Nonnull PrefixBuilder builder) throws ReadFailedException {
+        checkValid();
+        PrefixKey key = identifier.firstKeyOf(Prefix.class);
+        dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY)
+                .srSteeringPolDetails.stream()
+                .filter(
+                        srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) !=
+                                L2SteeringRequest.L2_TRAFFIC_TYPE)
+                .filter(srSteeringPolDetails -> parseL3SteeringKey(srSteeringPolDetails).equals(key))
+                .findFirst()
+                .ifPresent(srSteeringPolDetails1 -> parseL3Steering(srSteeringPolDetails1, builder));
+    }
+
+    private void parseL3Steering(SrSteeringPolDetails srSteeringPolDetails, final PrefixBuilder builder) {
+        PrefixKey key = parseL3SteeringKey(srSteeringPolDetails);
+        builder.setKey(key).setIpPrefix(key.getIpPrefix())
+                .setState(new StateBuilder().setIpPrefix(key.getIpPrefix()).build());
+    }
+
+    private PrefixKey parseL3SteeringKey(SrSteeringPolDetails policyDetails) {
+        return new PrefixKey(parseIpPrefix(policyDetails));
+    }
+
+    private IpPrefix parseIpPrefix(final SrSteeringPolDetails policyDetails) {
+        boolean isIpv6 = isIpv6L3TrafficType(policyDetails.trafficType);
+        IpPrefix ipPrefix;
+        if (isIpv6) {
+            Ipv6Prefix ipv6Prefix = toIpv6Prefix(policyDetails.prefixAddr, policyDetails.maskWidth);
+            ipPrefix = new IpPrefix(ipv6Prefix);
+        } else {
+            Ipv4Prefix ipv4Prefix = toIpv4Prefix(policyDetails.prefixAddr, policyDetails.maskWidth);
+            ipPrefix = new IpPrefix(ipv4Prefix);
+        }
+        return ipPrefix;
+    }
+
+    private boolean isIpv6L3TrafficType(final byte trafficType) {
+        Preconditions.checkArgument(trafficType == L3_TRAFFIC_TYPE_IPV4 || trafficType == L3_TRAFFIC_TYPE_IPV6,
+                "Unsupported traffic type for L3 steering");
+
+        return trafficType == L3_TRAFFIC_TYPE_IPV6;
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java
new file mode 100644 (file)
index 0000000..04b67f6
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering.request;
+
+import io.fd.hc2vpp.srv6.util.JVppRequest;
+import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
+import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetailsReplyDump;
+import io.fd.vpp.jvpp.core.dto.SrSteeringPolDump;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+
+/**
+ * General template for steering requests
+ */
+abstract class SteeringRequest extends JVppRequest {
+
+    static final SrSteeringPolDetailsReplyDump STATIC_EMPTY_REPLY = new SrSteeringPolDetailsReplyDump();
+    private static final SrSteeringPolDump STATIC_DUMP_REQUEST = new SrSteeringPolDump();
+    final DumpCacheManager<SrSteeringPolDetailsReplyDump, Void> dumpManager;
+
+    SteeringRequest(final FutureJVppCore api) {
+        super(api);
+        this.dumpManager =
+                new DumpCacheManager.DumpCacheManagerBuilder<SrSteeringPolDetailsReplyDump, Void>().acceptOnly(
+                        SrSteeringPolDetailsReplyDump.class)
+                        .withExecutor((identifier, params) -> getReplyForRead(
+                                getApi().srSteeringPolDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier))
+                        .build();
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java
new file mode 100644 (file)
index 0000000..d0b6479
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.util;
+
+import io.fd.honeycomb.translate.MappingContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodType;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMapping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+
+/**
+ * Manages metadata for SRv6 policy plugin
+ */
+public interface CandidatePathContextManager {
+    /**
+     * Creates metadata for candidate path. Existing mapping is overwritten if exists.
+     *
+     * @param bsid               candidate path bsid
+     * @param name               candidate path name
+     * @param provisioningMethod candidate path provisioning method
+     * @param preference         candidate path preference
+     * @param distinguisher      candidate path distinguisher
+     * @param ctx                mapping context providing context data for current transaction
+     */
+    void addCandidatePath(@Nonnull Ipv6Address bsid, @Nonnull final String name,
+                          @Nonnull final Class<? extends ProvisioningMethodType> provisioningMethod,
+                          @Nonnull Long preference, @Nonnull Long distinguisher, @Nonnull final MappingContext ctx);
+
+    /**
+     * Retrieves candidate path for given name. If not present it will generate artificial mapping
+     *
+     * @param bsid candidate path BSID
+     * @param ctx  mapping context providing context data for current transaction
+     * @return candidate path matching supplied candidate path BSID if present, artificial mapping otherwise
+     */
+    @Nonnull
+    Srv6CandidatePathMapping getCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx);
+
+    /**
+     * Removes candidate path metadata from current context.
+     *
+     * @param bsid candidate path BSID
+     * @param ctx  mapping context providing context data for current transaction
+     */
+    void removeCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx);
+
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java
new file mode 100644 (file)
index 0000000..15fb5c0
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.util;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.MappingContext;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodConfig;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodType;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.Srv6PolicyContextAugmentation;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.Srv6CandidatePathMappings;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMapping;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMappingKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Facade on top of {@link MappingContext} that manages {@link Srv6CandidatePathMappings}.
+ */
+@ThreadSafe
+public class CandidatePathContextManagerImpl implements CandidatePathContextManager {
+
+    private static final long DEFAULT_PREFERENCE = 100L;
+    private AtomicLong distinguisher;
+
+    private final InstanceIdentifier<Srv6CandidatePathMappings> ctxIid;
+
+    public CandidatePathContextManagerImpl() {
+        this.ctxIid = InstanceIdentifier.create(Contexts.class)
+                .augmentation(Srv6PolicyContextAugmentation.class)
+                .child(Srv6CandidatePathMappings.class);
+        distinguisher = new AtomicLong(0L);
+    }
+
+    @Override
+    public void addCandidatePath(@Nonnull Ipv6Address bsid, @Nonnull final String name,
+                                 @Nonnull final Class<? extends ProvisioningMethodType> provisioningMethod,
+                                 @Nonnull Long preference, @Nonnull Long distinguisher,
+                                 @Nonnull final MappingContext ctx) {
+        final KeyedInstanceIdentifier<Srv6CandidatePathMapping, Srv6CandidatePathMappingKey> mappingIid =
+                getCandidatePathIid(bsid);
+        final Srv6CandidatePathMappingBuilder builder =
+                new Srv6CandidatePathMappingBuilder().setKey(new Srv6CandidatePathMappingKey(bsid))
+                        .setProvisioningMethod(provisioningMethod).setPreference(preference)
+                        .setDistinguisher(distinguisher).setBsid(bsid).setName(name);
+        ctx.put(mappingIid, builder.build());
+    }
+
+    private KeyedInstanceIdentifier<Srv6CandidatePathMapping, Srv6CandidatePathMappingKey> getCandidatePathIid(
+            final Ipv6Address bsid) {
+        return ctxIid.child(Srv6CandidatePathMapping.class, new Srv6CandidatePathMappingKey(bsid));
+    }
+
+    @Override
+    @Nonnull
+    public synchronized Srv6CandidatePathMapping getCandidatePath(@Nonnull final Ipv6Address bsid,
+                                                                  @Nonnull final MappingContext ctx) {
+        final Optional<Srv6CandidatePathMappings> read = ctx.read(ctxIid);
+        if (read.isPresent()) {
+            java.util.Optional<Srv6CandidatePathMapping> mappingOpt = read.get().getSrv6CandidatePathMapping().stream()
+                    .filter(srv6CandidatePathMapping -> srv6CandidatePathMapping.getBsid().getValue()
+                            .equals(bsid.getValue())).findAny();
+            if (mappingOpt.isPresent()) {
+                return mappingOpt.get();
+            }
+        }
+        return getArtificialMapping(bsid, ctx, bsid.getValue());
+    }
+
+    private Srv6CandidatePathMapping getArtificialMapping(final @Nonnull Ipv6Address bsid,
+                                                          final @Nonnull MappingContext ctx, final String name) {
+        // if not present we need to generate artificial mapping
+        // for given policy only one candidate path can be selected and be configured on the device.
+        Srv6CandidatePathMapping mapping =
+                new Srv6CandidatePathMappingBuilder()
+                        .setProvisioningMethod(ProvisioningMethodConfig.class)
+                        .setBsid(bsid) //when we read name from VPP it is always the BSID value
+                        .setPreference(DEFAULT_PREFERENCE)
+                        .setDistinguisher(distinguisher.incrementAndGet())
+                        .build();
+        addCandidatePath(mapping.getBsid(), name, mapping.getProvisioningMethod(), mapping.getPreference(),
+                mapping.getDistinguisher(), ctx);
+        return mapping;
+    }
+
+    @Override
+    public void removeCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) {
+        final KeyedInstanceIdentifier<Srv6CandidatePathMapping, Srv6CandidatePathMappingKey> mappingIid =
+                getCandidatePathIid(bsid);
+        ctx.delete(mappingIid);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java
new file mode 100644 (file)
index 0000000..dd0f261
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.util;
+
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NoopCustomizer<T extends DataObject> implements WriterCustomizer<T> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NoopCustomizer.class);
+
+    public NoopCustomizer() {
+        super();
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull InstanceIdentifier<T> instanceIdentifier, @Nonnull T data,
+                                       @Nonnull WriteContext writeContext) {
+        LOG.trace("Noop write called for IId: {}, data: {}", instanceIdentifier, data);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull InstanceIdentifier<T> instanceIdentifier, @Nonnull T data,
+                                        @Nonnull WriteContext writeContext) {
+        LOG.trace("Noop delete called for IId: {}, data: {}", instanceIdentifier, data);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java
new file mode 100644 (file)
index 0000000..3a07fe0
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.util;
+
+import io.fd.honeycomb.translate.MappingContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMapping;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+
+/**
+ * Manages metadata for SRv6 policy plugin
+ */
+public interface PolicyContextManager {
+    /**
+     * Creates metadata for policy. Existing mapping is overwritten if exists.
+     *
+     * @param name     policy name
+     * @param color    policy color
+     * @param endpoint policy endpoint
+     * @param bsid     policy bsid
+     * @param ctx      mapping context providing context data for current transaction
+     */
+    void addPolicy(@Nonnull final String name, @Nonnull Long color, @Nonnull Ipv6Address endpoint,
+                   @Nonnull Ipv6Address bsid, @Nonnull final MappingContext ctx);
+
+    /**
+     * Retrieves policy for given policy BSID. If not present it wil generate artificial mapping
+     *
+     * @param bsid policy BSID
+     * @param ctx  mapping context providing context data for current transaction
+     * @return policy matching supplied policy BSID if present, or artificial mapping if not
+     */
+    @Nonnull
+    Srv6PolicyMapping getPolicy(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx);
+
+    /**
+     * Retrieves policy BSID for given policy color and endpoint.
+     *
+     * @param color policy color
+     * @param endpoint policy endpoint
+     * @param ctx  mapping context providing context data for current transaction
+     * @return policy BSID matching supplied policy color and endpoint if present, null otherwise
+     */
+    Ipv6Address getPolicyBsid(@Nonnull Long color, @Nonnull Ipv6Address endpoint, @Nonnull final MappingContext ctx);
+
+    /**
+     * Removes policy metadata from current context.
+     *
+     * @param bsid policy BSID
+     * @param ctx  mapping context providing context data for current transaction
+     */
+    void removePolicy(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx);
+
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java
new file mode 100644 (file)
index 0000000..1997043
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.util;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.MappingContext;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.Srv6PolicyContextAugmentation;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.Srv6PolicyMappings;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMapping;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMappingKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+/**
+ * Facade on top of {@link MappingContext} that manages {@link Srv6PolicyMappings}.
+ */
+@ThreadSafe
+public class PolicyContextManagerImpl implements PolicyContextManager {
+
+    private final InstanceIdentifier<Srv6PolicyMappings> ctxIid;
+    // 2001:db8::/32 This address range is used for documentation and example source code. We can use it as dummy
+    // addresses for our artificial policies
+    private static final String DUMMY_EP = "2001:db8::";
+    private Long artificialColor;
+
+    public PolicyContextManagerImpl() {
+        this.ctxIid = InstanceIdentifier.create(Contexts.class)
+                .augmentation(Srv6PolicyContextAugmentation.class)
+                .child(Srv6PolicyMappings.class);
+        this.artificialColor = 0L;
+    }
+
+    @Override
+    public void addPolicy(@Nonnull final String name, @Nonnull final Long color, @Nonnull final Ipv6Address endpoint,
+                          @Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) {
+        final KeyedInstanceIdentifier<Srv6PolicyMapping, Srv6PolicyMappingKey> mappingIid = getPolicyIid(bsid);
+        final Srv6PolicyMappingBuilder builder =
+                new Srv6PolicyMappingBuilder().setKey(new Srv6PolicyMappingKey(bsid)).setColor(color)
+                        .setEndpoint(endpoint).setBsid(bsid).setName(name);
+        ctx.put(mappingIid, builder.build());
+    }
+
+    private KeyedInstanceIdentifier<Srv6PolicyMapping, Srv6PolicyMappingKey> getPolicyIid(final Ipv6Address bsid) {
+        return ctxIid.child(Srv6PolicyMapping.class, new Srv6PolicyMappingKey(bsid));
+    }
+
+    @Nonnull
+    public synchronized Srv6PolicyMapping getPolicy(@Nonnull final Ipv6Address bsid,
+                                                    @Nonnull final MappingContext ctx) {
+        final Optional<Srv6PolicyMapping> read = ctx.read(getPolicyIid(bsid));
+        if (read.isPresent()) {
+            return read.get();
+        }
+
+        //if not present we need to generate artificial mapping
+        Long nextArtificialColor = getNextArtificialColor();
+        Ipv6Address endpoint = new Ipv6Address(DUMMY_EP + nextArtificialColor);
+        Srv6PolicyMapping mapping =
+                new Srv6PolicyMappingBuilder().setBsid(bsid).setColor(nextArtificialColor).setEndpoint(endpoint)
+                        .setName(bsid.getValue()).build();
+        addPolicy(mapping.getName(), mapping.getColor(), mapping.getEndpoint(), mapping.getBsid(), ctx);
+        return mapping;
+    }
+
+    @Override
+    public Ipv6Address getPolicyBsid(@Nonnull Long color, @Nonnull Ipv6Address endpoint,
+                                     @Nonnull final MappingContext ctx) {
+        Optional<Srv6PolicyMappings> read = ctx.read(ctxIid);
+        if (read.isPresent()) {
+            return read.get().getSrv6PolicyMapping().stream()
+                    .filter(srv6PolicyMapping -> srv6PolicyMapping.getColor().equals(color) &&
+                            srv6PolicyMapping.getEndpoint().equals(endpoint))
+                    .map(Srv6PolicyMapping::getBsid).findFirst().orElse(null);
+        }
+        return null;
+    }
+
+    @Override
+    public void removePolicy(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) {
+        final KeyedInstanceIdentifier<Srv6PolicyMapping, Srv6PolicyMappingKey> mappingIid = getPolicyIid(bsid);
+        ctx.delete(mappingIid);
+    }
+
+    private synchronized Long getNextArtificialColor() {
+        artificialColor++;
+        return artificialColor;
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java
new file mode 100644 (file)
index 0000000..ea308ef
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.util;
+
+import com.google.common.base.Optional;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.VppSrPolicy;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public final class Srv6Util {
+
+    /**
+     * Constructs unique name for candidate path based on binding sid and weight
+     *
+     * @param bsid   binding sid associated with candidate path
+     * @param weight weight of actual sidList
+     * @return candidate path name
+     */
+    public static String getCandidatePathName(final Ipv6Address bsid, final long weight) {
+        return bsid.getValue() + "-" + weight;
+    }
+
+    /**
+     * Extracts BSID from policy, based on read/write operation it uses dataBefore/dataAfter while reading config
+     *
+     * @param instanceIdentifier identifier used to extract path of policy
+     * @param writeContext       used to store any useful information later utilized by customizers
+     * @param isWrite            condition whether this is a write or delete operation
+     * @return BSID in form of IPv6 address or null if not resolved
+     */
+    public static <T extends DataObject> Ipv6Address extractBsid(
+            final @Nonnull InstanceIdentifier<T> instanceIdentifier, final @Nonnull WriteContext writeContext,
+            boolean isWrite) {
+        Optional<Policy> policyOptional = isWrite
+                ? writeContext.readAfter(RWUtils.cutId(instanceIdentifier, Policy.class))
+                : writeContext.readBefore(RWUtils.cutId(instanceIdentifier, Policy.class));
+
+        if (policyOptional.isPresent() && policyOptional.get().getBindingSid() != null &&
+                policyOptional.get().getBindingSid().getConfig() != null) {
+            org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config
+                    config = policyOptional.get().getBindingSid().getConfig();
+            if (config.getType() == DataplaneType.Srv6 && config.getValue() != null &&
+                    config.getValue().getIpAddress() != null &&
+                    config.getValue().getIpAddress().getIpv6Address() != null) {
+                return config.getValue().getIpAddress().getIpv6Address();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Extracts VRF FIB from Policy.
+     *
+     * @param instanceIdentifier identifier used to extract path of policy
+     * @param writeContext       used to store any useful information later utilized by customizers
+     * @param isWrite            condition whether this is a write or delete operation
+     * @return VRF FIB id when resolved, default VRF FIB (0) otherwise
+     */
+    public static <T extends DataObject> int extractVrfFib(final @Nonnull InstanceIdentifier<T> instanceIdentifier,
+                                                           final @Nonnull WriteContext writeContext, boolean isWrite) {
+        Optional<Policy> policyOptional = isWrite
+                ? writeContext.readAfter(RWUtils.cutId(instanceIdentifier, Policy.class))
+                : writeContext.readBefore(RWUtils.cutId(instanceIdentifier, Policy.class));
+
+        if (policyOptional.isPresent() && policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class) != null &&
+                policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class).getVppSrPolicy() != null) {
+
+            VppSrPolicy vppSrPolicy =
+                    policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class).getVppSrPolicy();
+            if (vppSrPolicy.getConfig() != null && vppSrPolicy.getConfig().getTableId() != null) {
+                return vppSrPolicy.getConfig().getTableId().getValue().intValue();
+            }
+        }
+        // returning default Vrf Fib table
+        return 0;
+    }
+}
index 551a211..5321bff 100644 (file)
@@ -52,6 +52,8 @@ public class EndDX2FunctionBinder extends XConnectFunctionBinder {
                 "Failed to map data: {} for request: {}", data, request);
         request.setOutgoingInterfaceIndex(getInterfaceIndex(ctx.getMappingContext(), outInterface));
         request.setFunction(getBehaviourFunctionType());
+        // TODO (HC2VPP-357): check model for ENDDX2V support, when added we can set the VLAN index
+        // request.setVlanIndex(getVLanIndex(ctx.getMappingContext(), ));
         return request;
     }
 
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java
new file mode 100644 (file)
index 0000000..87e07d2
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.LocatorContextManager;
+import io.fd.hc2vpp.srv6.util.NoopCustomizer;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.hc2vpp.srv6.write.policy.PolicyCustomizer;
+import io.fd.hc2vpp.srv6.write.steering.InterfacesConfigCustomizer;
+import io.fd.hc2vpp.srv6.write.steering.PrefixCustomizer;
+import io.fd.hc2vpp.srv6.write.steering.PrefixesConfigCustomizer;
+import io.fd.honeycomb.translate.impl.write.GenericListWriter;
+import io.fd.honeycomb.translate.impl.write.GenericWriter;
+import io.fd.honeycomb.translate.write.WriterFactory;
+import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+
+public class Srv6PolicyWriterFactory implements WriterFactory {
+
+    @Inject
+    private FutureJVppCore futureJVppCore;
+    @Inject
+    @Named("interface-context")
+    private NamingContext interfaceContext;
+    @Inject
+    private LocatorContextManager locatorContext;
+    @Inject
+    private PolicyContextManager policyContext;
+    @Inject
+    private CandidatePathContextManager candidateContext;
+
+    @Override
+    public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_IID, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_CFG, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS_SG, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS_SG_CFG, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_BSID, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_BSID_CFG, new NoopCustomizer<>()));
+        registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_CFG, new NoopCustomizer<>()));
+
+        registry.subtreeAdd(ImmutableSet
+                        .of(Srv6PolicyIIds.SR_POLICY_BSID, Srv6PolicyIIds.SR_POLICY_BSID_CFG,
+                                Srv6PolicyIIds.SR_POLICY_VPP, Srv6PolicyIIds.SR_POLICY_VPP_SR,
+                                Srv6PolicyIIds.SR_POLICY_VPP_SR_CFG, Srv6PolicyIIds.SR_POLICY_CFG,
+                                Srv6PolicyIIds.SR_POLICY_CPS, Srv6PolicyIIds.SR_POLICY_CPS_CP,
+                                Srv6PolicyIIds.SR_POLICY_CPS_CP_CFG, Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID,
+                                Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID_CFG, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS,
+                                Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL_CFG),
+                new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL,
+                        new PolicyCustomizer(futureJVppCore, policyContext, candidateContext)));
+
+        registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_CFG),
+                new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_IID,
+                        new PrefixCustomizer(futureJVppCore)));
+        registry.add(
+                new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_CFG,
+                        new PrefixesConfigCustomizer(futureJVppCore)));
+        registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_CFG),
+                new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_IID,
+                        new InterfacesConfigCustomizer(futureJVppCore, interfaceContext)));
+    }
+}
index d9f0229..bb26197 100644 (file)
@@ -38,7 +38,7 @@ public class Srv6WriterFactory implements WriterFactory {
     @Inject
     private LocalSidFunctionWriteBindingRegistry bindingRegistry;
     @Inject
-    protected LocatorContextManager locatorContext;
+    private LocatorContextManager locatorContext;
 
     @Override
     public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java
new file mode 100644 (file)
index 0000000..d8e09e8
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.policy;
+
+import com.google.common.base.Preconditions;
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.fib.management.FibManagementIIds;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.hc2vpp.srv6.util.Srv6Util;
+import io.fd.hc2vpp.srv6.write.policy.request.PolicyDeleteRequest;
+import io.fd.hc2vpp.srv6.write.policy.request.PolicyWriteRequest;
+import io.fd.hc2vpp.srv6.write.policy.request.dto.SidList;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.BindingSidAllocMode;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodConfig;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.TableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class PolicyCustomizer extends FutureJVppCustomizer
+        implements ListWriterCustomizer<Policy, PolicyKey> {
+
+    private final PolicyContextManager policyContext;
+    private final CandidatePathContextManager candidateContext;
+
+    public PolicyCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                            @Nonnull final PolicyContextManager policyContext,
+                            @Nonnull final CandidatePathContextManager candidateContext) {
+        super(futureJVppCore);
+        this.policyContext = policyContext;
+        this.candidateContext = candidateContext;
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> instanceIdentifier,
+                                       @Nonnull final Policy policy,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        try {
+            // Fib table must be created beforehand. First we check if all data is present, then we verify the existence
+            // of FIB table in current configuration
+            VppSrPolicyAugmentation policyAugmentation = policy.getAugmentation(VppSrPolicyAugmentation.class);
+
+            if (policyAugmentation != null && policyAugmentation.getVppSrPolicy() != null &&
+                    policyAugmentation.getVppSrPolicy().getConfig() != null) {
+                Config config = policyAugmentation.getVppSrPolicy().getConfig();
+                TableKey tableKey = new TableKey(config.getAddressFamily(), new VniReference(config.getTableId()));
+                KeyedInstanceIdentifier<Table, TableKey> vrfIid =
+                        FibManagementIIds.FM_FIB_TABLES.child(Table.class, tableKey);
+                if (!writeContext.readAfter(vrfIid).isPresent()) {
+                    throw new IllegalArgumentException(
+                            String.format("VRF table: %s not found. Create table before writing policy.", tableKey));
+                }
+                if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) {
+                    bindWriteRequest(config, policy.getCandidatePaths().getCandidatePath(), writeContext)
+                            .write(instanceIdentifier);
+                    Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, true);
+                    policyContext.addPolicy(policy.getName(), policy.getColor(), policy.getEndpoint().getIpv6Address(),
+                            bsid, writeContext.getMappingContext());
+                }
+            } else {
+                throw new ReadFailedException(instanceIdentifier,
+                        new Throwable("VppSrPolicyAugmentation and/or VppSrPolicy missing."));
+            }
+        } catch (ReadFailedException e) {
+            throw new WriteFailedException.CreateFailedException(instanceIdentifier, policy, e);
+        }
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> instanceIdentifier,
+                                        @Nonnull final Policy policy, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) {
+            bindDeleteRequest(policy.getCandidatePaths().getCandidatePath(), writeContext).delete(instanceIdentifier);
+            Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, false);
+            Preconditions.checkNotNull(bsid, "BSID must not be null");
+            policyContext.removePolicy(bsid, writeContext.getMappingContext());
+        }
+    }
+
+    private PolicyDeleteRequest bindDeleteRequest(final @Nonnull List<CandidatePath> candidatePaths,
+                                                  final @Nonnull WriteContext writeContext) {
+        final PolicyDeleteRequest request = new PolicyDeleteRequest(getFutureJVpp());
+
+        Optional<CandidatePath> candidatePathOptional = parseBestCandidate(candidatePaths);
+        Preconditions.checkArgument(candidatePathOptional.isPresent(),
+                "Could not parse best Candidate path from list: {}", candidatePaths);
+
+        CandidatePath selectedPath = candidatePathOptional.get();
+        if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) {
+            org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config
+                    sidConfig = selectedPath.getBindingSid().getConfig();
+
+            if (sidConfig.getType() == DataplaneType.Srv6 &&
+                    sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null &&
+                    sidConfig.getValue().getIpAddress() != null &&
+                    sidConfig.getValue().getIpAddress().getIpv6Address() != null) {
+                Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address();
+                request.setBindingSidAddress(bsid);
+                candidateContext.removeCandidatePath(bsid, writeContext.getMappingContext());
+            }
+        }
+        return request;
+    }
+
+    private PolicyWriteRequest bindWriteRequest(@Nonnull final Config config,
+                                                final List<CandidatePath> candidatePaths,
+                                                final WriteContext writeContext) {
+        final PolicyWriteRequest request = new PolicyWriteRequest(getFutureJVpp());
+        request.setFibTableIndex(config.getTableId().getValue().intValue());
+        request.setPolicyBehavior(config.getPolicyBehavior());
+        request.setPolicyType(config.getPolicyType());
+
+        Optional<CandidatePath> candidatePathOptional = parseBestCandidate(candidatePaths);
+        Preconditions.checkArgument(candidatePathOptional.isPresent(),
+                "Could not parse best Candidate path from list: {}", candidatePaths);
+
+        CandidatePath selectedPath = candidatePathOptional.get();
+        if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) {
+            org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config
+                    sidConfig = selectedPath.getBindingSid().getConfig();
+
+            if (sidConfig.getType() == DataplaneType.Srv6 &&
+                    sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null &&
+                    sidConfig.getValue().getIpAddress() != null &&
+                    sidConfig.getValue().getIpAddress().getIpv6Address() != null) {
+                Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address();
+                request.setBindingSidAddress(bsid);
+                candidateContext.addCandidatePath(bsid, selectedPath.getName(), selectedPath.getProvisioningMethod(),
+                        selectedPath.getPreference(), selectedPath.getDistinguisher(),
+                        writeContext.getMappingContext());
+            }
+        }
+        if (selectedPath.getSegmentLists() != null && selectedPath.getSegmentLists().getSegmentList() != null) {
+            request.setSegments(readSegmentLists(selectedPath.getSegmentLists().getSegmentList(), writeContext));
+        }
+
+        return request;
+    }
+
+    private List<SidList> readSegmentLists(final List<SegmentList> segmentLists, final WriteContext writeContext) {
+        List<SidList> sidLists = new ArrayList<>();
+
+        segmentLists.forEach(segmentList -> {
+            com.google.common.base.Optional<NamedSegmentList> namedSegmentListOptional = writeContext.readAfter(
+                    Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class,
+                            new NamedSegmentListKey(segmentList.getName())));
+
+            if (namedSegmentListOptional.isPresent()) {
+                sidLists.add(SidList.builder()
+                        .setNamedSegmentList(namedSegmentListOptional.get())
+                        .setWeight(segmentList.getConfig().getWeight())
+                        .build());
+            }
+        });
+        return sidLists;
+    }
+
+    /**
+     * Selects best Candidate based on Preference value (the higher preference the better),
+     * only static configuration is supported for now (provisioning-method must be equal to provisioning-method-config).
+     *
+     * Based on Segment Routing Policy for Traffic Engineering
+     * https://tools.ietf.org/html/draft-filsfils-spring-segment-routing-policy-00
+     *
+     * @param candidatePaths List of available CandidatePaths
+     * @return Optional of CandidatePath
+     */
+    private Optional<CandidatePath> parseBestCandidate(final List<CandidatePath> candidatePaths) {
+        return candidatePaths.stream()
+                .filter(candidatePath -> candidatePath.getProvisioningMethod().equals(ProvisioningMethodConfig.class))
+                .max(Comparator.comparingLong(CandidatePath::getPreference));
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java
new file mode 100644 (file)
index 0000000..71b9d72
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.policy.request;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.srv6.util.JVppRequest;
+import io.fd.hc2vpp.srv6.write.DeleteRequest;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrPolicyDel;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import io.fd.vpp.jvpp.core.types.Srv6Sid;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PolicyDeleteRequest extends JVppRequest implements DeleteRequest {
+
+    /**
+     * Binding SID of the policy
+     */
+    private Ipv6Address bindingSidAddress;
+
+    public PolicyDeleteRequest(final FutureJVppCore api) {
+        super(api);
+    }
+
+    @Override
+    public void checkValid() {
+        checkNotNull(bindingSidAddress, "Binding sid address not set");
+    }
+
+    @Override
+    public void delete(final InstanceIdentifier<?> identifier) throws WriteFailedException {
+        checkValid();
+        final SrPolicyDel request = new SrPolicyDel();
+        Srv6Sid bsid = new Srv6Sid();
+        bsid.addr = ipv6AddressNoZoneToArray(bindingSidAddress);
+        request.bsidAddr = bsid;
+        getReplyForDelete(getApi().srPolicyDel(request).toCompletableFuture(), identifier);
+    }
+
+    public void setBindingSidAddress(
+            final Ipv6Address bindingSidAddress) {
+        this.bindingSidAddress = bindingSidAddress;
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java
new file mode 100644 (file)
index 0000000..6dc3e86
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.policy.request;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.srv6.util.JVppRequest;
+import io.fd.hc2vpp.srv6.write.WriteRequest;
+import io.fd.hc2vpp.srv6.write.policy.request.dto.SidList;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrPolicyAdd;
+import io.fd.vpp.jvpp.core.dto.SrPolicyMod;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import io.fd.vpp.jvpp.core.types.Srv6Sid;
+import io.fd.vpp.jvpp.core.types.Srv6SidList;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.Segments;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.Segment;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyBehavior;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PolicyWriteRequest extends JVppRequest implements WriteRequest {
+
+    /**
+     * Types of modification operations
+     */
+    private static final int ADD_NEW = 1;
+    private static final int DELETE_EXISTING = 2;
+    private static final int MODIFY_WEIGHT = 3;
+
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyWriteRequest.class);
+
+    /**
+     * Binding SID of the policy
+     */
+    private Ipv6Address bindingSidAddress;
+
+    /**
+     * Behavior used by this policy. Either inserts to existing header or encapsulate to new one
+     */
+    private SegmentRoutingPolicyBehavior policyBehavior;
+
+    /**
+     * Revelant if multiple segment lists are used. Default is load-balancing, spray will send traffic to every segment
+     */
+    private SegmentRoutingPolicyType policyType;
+
+    /**
+     * FIB table where entry should be installed
+     */
+    private int fibTableIndex;
+
+    /**
+     * List of SidList
+     */
+    private List<SidList> segments;
+
+    public PolicyWriteRequest(final FutureJVppCore api) {
+        super(api);
+    }
+
+    private static Srv6Sid[] convertSegmentsToByteArray(final Segments segments) {
+        List<Srv6Sid> sidList = new ArrayList<>();
+        segments.getSegment().stream().sorted(Comparator.comparingLong(Segment::getIndex))
+                .map(segment -> segment.getConfig().getSidValue().getIpAddress().getIpv6Address())
+                .forEach(ipv6Address -> {
+                    Srv6Sid sid = new Srv6Sid();
+                    sid.addr = AddressTranslator.INSTANCE.ipv6AddressNoZoneToArray(ipv6Address);
+                    sidList.add(sid);
+                });
+        return sidList.toArray(new Srv6Sid[0]);
+    }
+
+    @Override
+    public void write(final InstanceIdentifier<?> identifier) throws WriteFailedException {
+        checkValid();
+
+        final SrPolicyAdd createRequest = new SrPolicyAdd();
+        createRequest.bsidAddr = ipv6AddressNoZoneToArray(bindingSidAddress);
+        createRequest.isEncap = (byte) policyBehavior.getIntValue();
+        createRequest.type = (byte) policyType.getIntValue();
+        createRequest.fibTable = fibTableIndex;
+
+        SidList firstSidList = segments.get(0);
+
+        createRequest.sids = new Srv6SidList();
+        createRequest.sids.numSids = (byte) firstSidList.getNamedSegmentList().getSegments().getSegment().size();
+        createRequest.sids.sids = convertSegmentsToByteArray(firstSidList.getNamedSegmentList().getSegments());
+        createRequest.sids.weight = firstSidList.getWeight().intValue();
+
+        LOG.info("Writing policy {}", createRequest);
+        getReplyForWrite(getApi().srPolicyAdd(createRequest).toCompletableFuture(), identifier);
+
+        if (segments.size() > 1) {
+            LOG.info("Multiple segments detected for policy, modifying");
+            segments.stream()
+                    .skip(1)
+                    .map(policySegments -> {
+                        SrPolicyMod modifyRequest = new SrPolicyMod();
+                        modifyRequest.bsidAddr = createRequest.bsidAddr;
+                        modifyRequest.operation = ADD_NEW;// add new segment list
+                        modifyRequest.fibTable = fibTableIndex;
+                        modifyRequest.sids = new Srv6SidList();
+                        modifyRequest.sids.numSids =
+                                (byte) policySegments.getNamedSegmentList().getSegments().getSegment().size();
+                        modifyRequest.sids.sids =
+                                convertSegmentsToByteArray(policySegments.getNamedSegmentList().getSegments());
+                        modifyRequest.sids.weight = policySegments.getWeight().intValue();
+                        return modifyRequest;
+                    })
+                    .peek(modifyRequest -> LOG.info("Adding additional segment list for policy {} / request {}",
+                            bindingSidAddress.getValue(), modifyRequest))
+                    .forEach(modifyRequest -> {
+                        try {
+                            getReplyForWrite(getApi().srPolicyMod(modifyRequest).toCompletableFuture(), identifier);
+                        } catch (WriteFailedException e) {
+                            throw new IllegalStateException(e);
+                        }
+                    });
+        }
+    }
+
+    @Override
+    public void checkValid() {
+        checkNotNull(bindingSidAddress, "Binding sid address not set");
+        checkNotNull(policyBehavior, "Policy behavior not set");
+        checkNotNull(policyType, "Policy type not set");
+        if (policyBehavior != SegmentRoutingPolicyBehavior.Encapsulation) {
+            checkNotNull(segments, "Segments not set");
+            checkState(!segments.isEmpty(), "No segments set");
+        }
+    }
+
+    public void setBindingSidAddress(
+            final Ipv6Address bindingSidAddress) {
+        this.bindingSidAddress = bindingSidAddress;
+    }
+
+    public void setPolicyBehavior(
+            final SegmentRoutingPolicyBehavior policyBehavior) {
+        this.policyBehavior = policyBehavior;
+    }
+
+    public void setPolicyType(
+            final SegmentRoutingPolicyType policyType) {
+        this.policyType = policyType;
+    }
+
+    public void setFibTableIndex(final int fibTableIndex) {
+        this.fibTableIndex = fibTableIndex;
+    }
+
+    public void setSegments(final List<SidList> segments) {
+        this.segments = segments;
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java
new file mode 100644 (file)
index 0000000..129c20e
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.write.policy.request.dto;
+
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList;
+
+public class SidList {
+    private Long weight;
+    private NamedSegmentList namedSegmentList;
+
+    private SidList(final SidListBuilder builder) {
+        weight = builder.weight;
+        namedSegmentList = builder.namedSegmentList;
+    }
+
+    public static SidListBuilder builder() {
+        return new SidListBuilder();
+    }
+
+    public Long getWeight() {
+        return weight;
+    }
+
+    public NamedSegmentList getNamedSegmentList() {
+        return namedSegmentList;
+    }
+
+    public static final class SidListBuilder {
+        private Long weight;
+        private NamedSegmentList namedSegmentList;
+
+        private SidListBuilder() {
+        }
+
+        public SidListBuilder setWeight(final Long weight) {
+            this.weight = weight;
+            return this;
+        }
+
+        public SidListBuilder setNamedSegmentList(final NamedSegmentList namedSegmentList) {
+            this.namedSegmentList = namedSegmentList;
+            return this;
+        }
+
+        public SidList build() {
+            return new SidList(this);
+        }
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java
new file mode 100644 (file)
index 0000000..67ad9d5
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.write.steering;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.util.Srv6Util;
+import io.fd.hc2vpp.srv6.write.steering.request.L2SteeringRequest;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacesConfigCustomizer extends FutureJVppCustomizer implements
+        ListWriterCustomizer<Interface, InterfaceKey> {
+    private final NamingContext interfaceContext;
+
+    public InterfacesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                                      @Nonnull final NamingContext interfaceContext) {
+        super(futureJVppCore);
+        this.interfaceContext = interfaceContext;
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> instanceIdentifier,
+                                       @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        if (anInterface.getConfig() != null) {
+            writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, true);
+        }
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> instanceIdentifier,
+                                        @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
+        if (anInterface.getConfig() != null) {
+            writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, false);
+        }
+    }
+
+    private void writeInterfaces(final @Nonnull InstanceIdentifier<Interface> instanceIdentifier,
+                                 final @Nonnull Config config, final @Nonnull WriteContext writeContext,
+                                 final boolean isWrite)
+            throws WriteFailedException {
+        Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite);
+
+        if (bsid == null) {
+            throw new WriteFailedException.CreateFailedException(instanceIdentifier, config,
+                    new Throwable("Failed to extract BSID from policy for prefix"));
+        }
+        if (config.getInputInterface() != null) {
+            // forward all traffic to policy for current interface
+            int index = interfaceContext.getIndex(config.getInputInterface(), writeContext.getMappingContext());
+            sendL2Steering(instanceIdentifier, bsid, index, getFutureJVpp(), isWrite);
+        }
+    }
+
+    private void sendL2Steering(final InstanceIdentifier<Interface> instanceIdentifier, final Ipv6Address bsid,
+                                final int inputInterface, final FutureJVppCore api, final boolean isWrite)
+            throws WriteFailedException {
+        L2SteeringRequest request = new L2SteeringRequest(api);
+        request.setBindingSid(bsid);
+        request.setInputInterfaceIndex(inputInterface);
+        if (isWrite) {
+            request.write(instanceIdentifier);
+        } else {
+            request.delete(instanceIdentifier);
+        }
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java
new file mode 100644 (file)
index 0000000..7973c32
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.write.steering;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.srv6.util.Srv6Util;
+import io.fd.hc2vpp.srv6.write.steering.request.L3SteeringRequest;
+import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PrefixCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer<Prefix, PrefixKey> {
+
+    public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) {
+        super(futureJVppCore);
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> instanceIdentifier,
+                                       @Nonnull final Prefix prefix,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        writePrefixes(instanceIdentifier, prefix, writeContext, true).write(instanceIdentifier);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> instanceIdentifier,
+                                        @Nonnull final Prefix prefix,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        writePrefixes(instanceIdentifier, prefix, writeContext, false).delete(instanceIdentifier);
+    }
+
+    private L3SteeringRequest writePrefixes(final @Nonnull InstanceIdentifier<Prefix> instanceIdentifier,
+                                            final @Nonnull Prefix prefix, final @Nonnull WriteContext writeContext,
+                                            final boolean isWrite)
+            throws WriteFailedException {
+        Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite);
+        int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite);
+
+        if (bsid == null) {
+            throw new WriteFailedException.CreateFailedException(instanceIdentifier, prefix,
+                    new Throwable("Failed to extract BSID from policy for prefix"));
+        }
+        // forward only desired traffic to policy
+        L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp());
+        request.setBindingSid(bsid);
+        request.setPrefix(prefix.getIpPrefix());
+        request.setFibTableIndex(vrfFib);
+        return request;
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java
new file mode 100644 (file)
index 0000000..e366db3
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.write.steering;
+
+import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
+import io.fd.hc2vpp.srv6.util.Srv6Util;
+import io.fd.hc2vpp.srv6.write.steering.request.L3SteeringRequest;
+import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PrefixesConfigCustomizer extends FutureJVppCustomizer implements WriterCustomizer<Config> {
+
+    private static final IpPrefix
+            DEFAULT_IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("::/0"));
+    private static final IpPrefix
+            DEFAULT_IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("0.0.0.0/0"));
+
+    public PrefixesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore) {
+        super(futureJVppCore);
+    }
+
+    private void writePrefixes(final @Nonnull InstanceIdentifier<Config> instanceIdentifier,
+                               final @Nonnull Config config, final @Nonnull WriteContext writeContext,
+                               final boolean isWrite)
+            throws WriteFailedException {
+        Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite);
+        int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite);
+
+        if (bsid == null) {
+            throw new WriteFailedException.CreateFailedException(instanceIdentifier, config,
+                    new Throwable("Failed to extract BSID from policy for prefix"));
+        }
+        if (config.isPrefixesAll()) {
+            // forward all traffic to policy
+            writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV6_PREFIX, bsid, getFutureJVpp(), isWrite);
+            writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV4_PREFIX, bsid, getFutureJVpp(), isWrite);
+        }
+    }
+
+    private void writeL3Steering(int vrfFib, InstanceIdentifier instanceIdentifier, IpPrefix ipPrefix,
+                                 final Ipv6Address bsid, FutureJVppCore api, boolean isWrite)
+            throws WriteFailedException {
+        L3SteeringRequest request = new L3SteeringRequest(api);
+        request.setBindingSid(bsid);
+        request.setPrefix(ipPrefix);
+        request.setFibTableIndex(vrfFib);
+        if (isWrite) {
+            request.write(instanceIdentifier);
+        } else {
+            request.delete(instanceIdentifier);
+        }
+    }
+
+    @Override
+    public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Config> instanceIdentifier,
+                                       @Nonnull final Config config,
+                                       @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        writePrefixes(instanceIdentifier, config, writeContext, true);
+    }
+
+    @Override
+    public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Config> instanceIdentifier,
+                                        @Nonnull final Config config,
+                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
+        writePrefixes(instanceIdentifier, config, writeContext, false);
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java
new file mode 100644 (file)
index 0000000..960d17b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.steering.request;
+
+import io.fd.hc2vpp.srv6.write.DeleteRequest;
+import io.fd.hc2vpp.srv6.write.WriteRequest;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Request for steering of L2 traffic
+ */
+public class L2SteeringRequest extends SteeringRequest implements WriteRequest, DeleteRequest {
+
+    private static final int L2_TRAFFIC_TYPE = 2;
+
+    /**
+     * Incoming interface for traffic
+     */
+    private int inputInterfaceIndex;
+
+    public L2SteeringRequest(final FutureJVppCore api) {
+        super(api);
+    }
+
+
+    @Override
+    public void delete(final InstanceIdentifier<?> identifier) throws WriteFailedException {
+        getReplyForDelete(getApi().srSteeringAddDel(bindRequest(true)).toCompletableFuture(), identifier);
+    }
+
+    @Override
+    public void write(final InstanceIdentifier<?> identifier) throws WriteFailedException {
+        getReplyForWrite(getApi().srSteeringAddDel(bindRequest(false)).toCompletableFuture(), identifier);
+    }
+
+    private SrSteeringAddDel bindRequest(final boolean isDel) {
+        final SrSteeringAddDel request = new SrSteeringAddDel();
+        request.isDel = booleanToByte(isDel);
+        request.bsidAddr = ipv6AddressNoZoneToArray(getBindingSid());
+        request.swIfIndex = inputInterfaceIndex;
+        request.trafficType = L2_TRAFFIC_TYPE;
+        return request;
+    }
+
+    public void setInputInterfaceIndex(final int inputInterfaceIndex) {
+        this.inputInterfaceIndex = inputInterfaceIndex;
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java
new file mode 100644 (file)
index 0000000..850234c
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.steering.request;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.srv6.write.DeleteRequest;
+import io.fd.hc2vpp.srv6.write.WriteRequest;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Request for steering of L3 traffic
+ */
+public class L3SteeringRequest extends SteeringRequest implements WriteRequest, DeleteRequest {
+
+    public static final byte VPP_IPV4_TYPE = 4;
+    public static final byte VPP_IPV6_TYPE = 6;
+    public static final byte VPP_UNRESOLVED_TYPE = 0;
+    /**
+     * Where to install FIB entry for this steering
+     */
+    private int fibTableIndex;
+
+    /**
+     * V4/V6 address for traffic type
+     */
+    private IpPrefix prefix;
+
+    public L3SteeringRequest(final FutureJVppCore api) {
+        super(api);
+    }
+
+    @Override
+    public void checkValid() {
+        super.checkValid();
+        checkNotNull(prefix, "Prefix is null");
+        checkArgument(resolveTrafficType(prefix) == 4 || resolveTrafficType(prefix) == 6,
+                "IpPrefix format not recognized");
+    }
+
+    @Override
+    public void delete(final InstanceIdentifier<?> identifier) throws WriteFailedException {
+        checkValid();
+        getReplyForDelete(getApi().srSteeringAddDel(bindRequest(true)).toCompletableFuture(), identifier);
+    }
+
+    @Override
+    public void write(final InstanceIdentifier<?> identifier) throws WriteFailedException {
+        checkValid();
+        getReplyForWrite(getApi().srSteeringAddDel(bindRequest(false)).toCompletableFuture(), identifier);
+    }
+
+    private SrSteeringAddDel bindRequest(final boolean isDel) {
+        final SrSteeringAddDel request = new SrSteeringAddDel();
+        request.isDel = booleanToByte(isDel);
+        request.bsidAddr = ipv6AddressNoZoneToArray(getBindingSid());
+        request.tableId = fibTableIndex;
+        request.trafficType = resolveTrafficType(prefix);
+        request.prefixAddr = ipPrefixToArray(prefix);
+        request.maskWidth = extractPrefix(prefix);
+        return request;
+    }
+
+    public void setFibTableIndex(final int fibTableIndex) {
+        this.fibTableIndex = fibTableIndex;
+    }
+
+    private byte resolveTrafficType(IpPrefix prefix) {
+        if (prefix.getIpv4Prefix() != null) {
+            return VPP_IPV4_TYPE;
+        } else if (prefix.getIpv6Prefix() != null) {
+            return VPP_IPV6_TYPE;
+        }
+        return VPP_UNRESOLVED_TYPE;
+    }
+
+    public void setPrefix(final IpPrefix prefix) {
+        this.prefix = prefix;
+    }
+}
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java
new file mode 100644 (file)
index 0000000..2078ade
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.steering.request;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.srv6.util.JVppRequest;
+import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+
+/**
+ * General template for steering requests
+ */
+public abstract class SteeringRequest extends JVppRequest {
+
+    /**
+     * Binding SID of policy that should be applied for this traffic
+     */
+    private Ipv6Address bindingSid;
+
+    SteeringRequest(final FutureJVppCore api) {
+        super(api);
+    }
+
+    @Override
+    public void checkValid() {
+        checkNotNull(bindingSid, "Binding SID is null");
+    }
+
+    Ipv6Address getBindingSid() {
+        return bindingSid;
+    }
+
+    public void setBindingSid(
+            final Ipv6Address bindingSid) {
+        this.bindingSid = bindingSid;
+    }
+}
index 54e4cdd..068ea12 100644 (file)
@@ -31,7 +31,9 @@ import com.google.inject.name.Named;
 import com.google.inject.testing.fieldbinder.Bind;
 import com.google.inject.testing.fieldbinder.BoundFieldModule;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.read.Srv6PolicyReaderFactory;
 import io.fd.hc2vpp.srv6.read.Srv6ReaderFactory;
+import io.fd.hc2vpp.srv6.write.Srv6PolicyWriterFactory;
 import io.fd.hc2vpp.srv6.write.Srv6WriterFactory;
 import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
 import io.fd.honeycomb.translate.ModificationCache;
@@ -42,6 +44,7 @@ import io.fd.honeycomb.translate.util.YangDAG;
 import io.fd.honeycomb.translate.write.WriterFactory;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 import org.junit.Before;
 import org.junit.Test;
@@ -100,8 +103,10 @@ public class Srv6ModuleTest {
         readerFactories.forEach(factory -> factory.init(registryBuilder));
         registryBuilder.addStructuralReader(Srv6IIds.RT, RoutingBuilder.class);
         assertNotNull(registryBuilder.build());
-        assertEquals(1, readerFactories.size());
-        assertTrue(readerFactories.iterator().next() instanceof Srv6ReaderFactory);
+        assertEquals(2, readerFactories.size());
+        Iterator<ReaderFactory> readerFactoryIterator = readerFactories.iterator();
+        assertTrue(readerFactoryIterator.next() instanceof Srv6ReaderFactory);
+        assertTrue(readerFactoryIterator.next() instanceof Srv6PolicyReaderFactory);
     }
 
     @Test
@@ -112,7 +117,9 @@ public class Srv6ModuleTest {
         final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder(new YangDAG());
         writerFactories.forEach(factory -> factory.init(registryBuilder));
         assertNotNull(registryBuilder.build());
-        assertEquals(1, writerFactories.size());
-        assertTrue(writerFactories.iterator().next() instanceof Srv6WriterFactory);
+        assertEquals(2, writerFactories.size());
+        Iterator<WriterFactory> writerFactoryIterator = writerFactories.iterator();
+        assertTrue(writerFactoryIterator.next() instanceof Srv6WriterFactory);
+        assertTrue(writerFactoryIterator.next() instanceof Srv6PolicyWriterFactory);
     }
 }
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizerTest.java
new file mode 100644 (file)
index 0000000..6cc2f55
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.read.policy;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentListsBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class NamedSegmentCustomizerTest extends PoliciesTest {
+
+    private NamedSegmentListKey SEGMENT_KEY_1 = new NamedSegmentListKey("a::e-0");
+    private NamedSegmentListKey SEGMENT_KEY_2 = new NamedSegmentListKey("e::a-0");
+
+    @Test
+    public void getAllIdsTest() throws ReadFailedException {
+        NamedSegmentCustomizer customizer = new NamedSegmentCustomizer(api, policyCtx, candidatePathCtx);
+        List<NamedSegmentListKey> segmentListKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_NSLS_NSL_IID, readCtx);
+
+        Assert.assertNotNull(segmentListKeys);
+        Assert.assertFalse(segmentListKeys.isEmpty());
+        Assert.assertEquals(replyDump.srPoliciesDetails.size(), segmentListKeys.size());
+        Assert.assertTrue(segmentListKeys.containsAll(ImmutableSet.of(SEGMENT_KEY_1, SEGMENT_KEY_2)));
+    }
+
+    @Test
+    public void readCurrentAttributesTest() throws ReadFailedException {
+        NamedSegmentCustomizer customizer = new NamedSegmentCustomizer(api, policyCtx, candidatePathCtx);
+        NamedSegmentListBuilder segmentListBuilder = new NamedSegmentListBuilder();
+        KeyedInstanceIdentifier<NamedSegmentList, NamedSegmentListKey>
+                key = Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, SEGMENT_KEY_1);
+        customizer.readCurrentAttributes(key, segmentListBuilder, readCtx);
+
+        Assert.assertEquals(SEGMENT_KEY_1, segmentListBuilder.getKey());
+        Assert.assertEquals(SEGMENT_KEY_1.getName(), segmentListBuilder.getName());
+        Assert.assertNotNull(customizer.getBuilder(key));
+
+        //verify State container
+        Assert.assertNotNull(segmentListBuilder.getState());
+        Assert.assertEquals(SEGMENT_KEY_1.getName(), segmentListBuilder.getState().getName());
+
+        //verify State container
+        Assert.assertNotNull(segmentListBuilder.getSegments());
+        Assert.assertNotNull(segmentListBuilder.getSegments().getSegment());
+        Assert.assertEquals(3, segmentListBuilder.getSegments().getSegment().size());
+
+        Assert.assertEquals(B_ADDR.getValue(),
+                segmentListBuilder.getSegments().getSegment().get(0).getState().getSidValue().getIpAddress()
+                        .getIpv6Address().getValue());
+        Assert.assertEquals(C_ADDR.getValue(),
+                segmentListBuilder.getSegments().getSegment().get(1).getState().getSidValue().getIpAddress()
+                        .getIpv6Address().getValue());
+        Assert.assertEquals(A_ADDR.getValue(),
+                segmentListBuilder.getSegments().getSegment().get(2).getState().getSidValue().getIpAddress()
+                        .getIpv6Address().getValue());
+
+        //verify different path
+        key = Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, SEGMENT_KEY_2);
+        customizer.readCurrentAttributes(key, segmentListBuilder, readCtx);
+        Assert.assertEquals(SEGMENT_KEY_2.getName(), segmentListBuilder.getState().getName());
+        Assert.assertEquals(3, segmentListBuilder.getSegments().getSegment().size());
+
+        Assert.assertEquals(A_ADDR.getValue(),
+                segmentListBuilder.getSegments().getSegment().get(0).getState().getSidValue().getIpAddress()
+                        .getIpv6Address().getValue());
+        Assert.assertEquals(C_ADDR.getValue(),
+                segmentListBuilder.getSegments().getSegment().get(1).getState().getSidValue().getIpAddress()
+                        .getIpv6Address().getValue());
+        Assert.assertEquals(B_ADDR.getValue(),
+                segmentListBuilder.getSegments().getSegment().get(2).getState().getSidValue().getIpAddress()
+                        .getIpv6Address().getValue());
+
+        //verify merge
+        NamedSegmentList segmentList = segmentListBuilder.build();
+        NamedSegmentListsBuilder parentBuilder = new NamedSegmentListsBuilder();
+        customizer.merge(parentBuilder, segmentList);
+        Assert.assertEquals(segmentList, parentBuilder.getNamedSegmentList().get(0));
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PoliciesTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PoliciesTest.java
new file mode 100644 (file)
index 0000000..d1abd15
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.read.policy;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.hc2vpp.srv6.write.sid.request.LocalSidRequestTest;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.vpp.jvpp.core.dto.SrPoliciesDetails;
+import io.fd.vpp.jvpp.core.dto.SrPoliciesDetailsReplyDump;
+import io.fd.vpp.jvpp.core.types.Srv6Sid;
+import io.fd.vpp.jvpp.core.types.Srv6SidList;
+import java.util.Arrays;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodConfig;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+
+public abstract class PoliciesTest extends LocalSidRequestTest {
+    Ipv6AddressNoZone BSID_ADR = new Ipv6AddressNoZone("a::e");
+    Ipv6AddressNoZone BSID_2_ADR = new Ipv6AddressNoZone("e::a");
+    IpAddress ENDPOINT_1 = new IpAddress(new Ipv6Address("e::1"));
+    IpAddress ENDPOINT_2 = new IpAddress(new Ipv6Address("a::1"));
+    Long COLOR_1 = 1L;
+    Long COLOR_2 = 2L;
+    long DISTINGUISHER_1 = 1L;
+    long DISTINGUISHER_2 = 2L;
+    long PREFERENCE_1 = 100L;
+    long PREFERENCE_2 = 200L;
+    Class<? extends ProvisioningMethodType> PROVISIONING_METHOD = ProvisioningMethodConfig.class;
+    int WEIGHT = 0;
+    SrPoliciesDetailsReplyDump replyDump = new SrPoliciesDetailsReplyDump();
+
+    @Mock
+    ReadContext readCtx;
+    @Mock
+    PolicyContextManager policyCtx;
+    @Mock
+    CandidatePathContextManager candidatePathCtx;
+    Ipv6AddressNoZone A_ADDR = new Ipv6AddressNoZone("a::");
+    Ipv6AddressNoZone B_ADDR = new Ipv6AddressNoZone("b::");
+    Ipv6AddressNoZone C_ADDR = new Ipv6AddressNoZone("c::");
+
+    @Mock
+    private
+    ModificationCache modificationCache;
+    private Srv6Sid A = new Srv6Sid();
+    private Srv6Sid B = new Srv6Sid();
+    private Srv6Sid C = new Srv6Sid();
+    private SrPoliciesDetails srPoliciesDetails1 = new SrPoliciesDetails();
+    private SrPoliciesDetails srPoliciesDetails2 = new SrPoliciesDetails();
+
+    @Override
+    public void init() {
+        Srv6Sid bsid = new Srv6Sid();
+        bsid.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR));
+        srPoliciesDetails1.bsid = bsid;
+
+        srPoliciesDetails1.numSidLists = 1;
+        Srv6SidList[] srv6SidLists = new Srv6SidList[1];
+        Srv6SidList srv6SidList = new Srv6SidList();
+        srv6SidList.weight = WEIGHT;
+        srv6SidList.numSids = 3;
+        A.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(A_ADDR));
+        B.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(B_ADDR));
+        C.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(C_ADDR));
+
+        srv6SidList.sids = ImmutableSet.of(B, C, A).toArray(new Srv6Sid[3]);
+
+        srv6SidLists[0] = srv6SidList;
+        srPoliciesDetails1.sidLists = srv6SidLists;
+        // is_encap - behavior of SR policy.(0.SRH insert // 1.Encapsulation)
+        srPoliciesDetails1.isEncap = ByteDataTranslator.BYTE_TRUE;
+        // type is the type of the SR policy. (0.Default // 1.Spray)
+        srPoliciesDetails1.type = 0;
+
+        Srv6Sid bsid2 = new Srv6Sid();
+        bsid2.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_2_ADR));
+        srPoliciesDetails2.bsid = bsid2;
+        srPoliciesDetails2.numSidLists = 1;
+        Srv6SidList[] srv6SidLists2 = new Srv6SidList[1];
+        Srv6SidList srv6SidList2 = new Srv6SidList();
+        srv6SidList2.weight = WEIGHT;
+        srv6SidList2.numSids = 3;
+
+        srv6SidList2.sids = ImmutableSet.of(A, C, B).toArray(new Srv6Sid[3]);
+        srv6SidLists2[0] = srv6SidList2;
+        srPoliciesDetails2.sidLists = srv6SidLists2;
+        srPoliciesDetails2.isEncap = ByteDataTranslator.BYTE_TRUE;
+        srPoliciesDetails2.type = 0;
+
+        replyDump.srPoliciesDetails = Arrays.asList(srPoliciesDetails1, srPoliciesDetails2);
+
+        when(readCtx.getModificationCache()).thenReturn(modificationCache);
+        when(readCtx.getMappingContext()).thenReturn(mappingContext);
+        when(modificationCache.get(any())).thenReturn(replyDump);
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizerTest.java
new file mode 100644 (file)
index 0000000..49c3942
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.policy;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.util.Srv6Util;
+import io.fd.honeycomb.translate.MappingContext;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.PathExplicitlyDefined;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodConfig;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentListOperState;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.PoliciesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMappingBuilder;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class PolicyCustomizerTest extends PoliciesTest {
+
+    private PolicyKey POLICY_KEY = new PolicyKey(COLOR_1, ENDPOINT_1);
+    private PolicyKey POLICY_KEY_2 = new PolicyKey(COLOR_2, ENDPOINT_2);
+
+    @Override
+    public void init() {
+        super.init();
+        when(policyCtx.getPolicy(eq(BSID_ADR), any(MappingContext.class))).thenReturn(
+                new Srv6PolicyMappingBuilder().setBsid(BSID_ADR).setColor(COLOR_1)
+                        .setEndpoint(ENDPOINT_1.getIpv6Address()).setName(BSID_ADR.getValue()).build());
+        when(policyCtx.getPolicy(eq(BSID_2_ADR), any(MappingContext.class))).thenReturn(
+                new Srv6PolicyMappingBuilder().setBsid(BSID_2_ADR).setColor(COLOR_2)
+                        .setEndpoint(ENDPOINT_2.getIpv6Address()).setName(BSID_2_ADR.getValue()).build());
+        when(policyCtx.getPolicyBsid(COLOR_1, ENDPOINT_1.getIpv6Address(), mappingContext)).thenReturn(BSID_ADR);
+        when(policyCtx.getPolicyBsid(COLOR_2, ENDPOINT_2.getIpv6Address(), mappingContext)).thenReturn(BSID_2_ADR);
+
+        when(candidatePathCtx.getCandidatePath(BSID_ADR, mappingContext)).thenReturn(
+                new Srv6CandidatePathMappingBuilder().setBsid(BSID_ADR).setDistinguisher(DISTINGUISHER_1)
+                        .setPreference(PREFERENCE_1).setName(BSID_ADR.getValue())
+                        .setProvisioningMethod(PROVISIONING_METHOD).build());
+        when(candidatePathCtx.getCandidatePath(BSID_2_ADR, mappingContext)).thenReturn(
+                new Srv6CandidatePathMappingBuilder().setBsid(BSID_2_ADR).setDistinguisher(DISTINGUISHER_2)
+                        .setPreference(PREFERENCE_2).setName(BSID_2_ADR.getValue())
+                        .setProvisioningMethod(PROVISIONING_METHOD).build());
+    }
+
+    @Test
+    public void getAllIdsTest() throws ReadFailedException {
+        PolicyCustomizer customizer = new PolicyCustomizer(api, policyCtx, candidatePathCtx);
+        List<PolicyKey> policyKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_PLS_POL, readCtx);
+
+        Assert.assertNotNull(policyKeys);
+        Assert.assertFalse(policyKeys.isEmpty());
+        Assert.assertEquals(replyDump.srPoliciesDetails.size(), policyKeys.size());
+        Assert.assertTrue(policyKeys.containsAll(ImmutableSet.of(POLICY_KEY, POLICY_KEY_2)));
+    }
+
+    @Test
+    public void readCurrentAttributesTest() throws ReadFailedException {
+        PolicyCustomizer customizer = new PolicyCustomizer(api, policyCtx, candidatePathCtx);
+        PolicyBuilder policyBuilder = new PolicyBuilder();
+        KeyedInstanceIdentifier<Policy, PolicyKey> key = Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY);
+        customizer.readCurrentAttributes(key, policyBuilder, readCtx);
+
+        Assert.assertEquals(POLICY_KEY, policyBuilder.getKey());
+        Assert.assertEquals(BSID_ADR.getValue(), policyBuilder.getName());
+        Assert.assertNotNull(customizer.getBuilder(key));
+
+        //verify BSID container
+        Assert.assertNotNull(policyBuilder.getBindingSid());
+        Assert.assertNotNull(policyBuilder.getBindingSid().getState());
+        Assert.assertEquals(DataplaneType.Srv6, policyBuilder.getBindingSid().getState().getType());
+        Assert.assertEquals(BSID_ADR,
+                policyBuilder.getBindingSid().getState().getValue().getIpAddress().getIpv6Address());
+
+        //verify state container
+        Assert.assertNotNull(policyBuilder.getState());
+        Assert.assertEquals(COLOR_1, policyBuilder.getState().getColor());
+        Assert.assertEquals(ENDPOINT_1, policyBuilder.getState().getEndpoint());
+        Assert.assertEquals(BSID_ADR.getValue(), policyBuilder.getState().getName());
+
+        //verify candidate-paths container
+        Assert.assertNotNull(policyBuilder.getCandidatePaths());
+        Assert.assertNotNull(policyBuilder.getCandidatePaths().getCandidatePath());
+        Assert.assertEquals(1, policyBuilder.getCandidatePaths().getCandidatePath().size());
+        CandidatePath candidatePath = policyBuilder.getCandidatePaths().getCandidatePath().get(0);
+        Assert.assertEquals(DISTINGUISHER_1, candidatePath.getDistinguisher().longValue());
+        Assert.assertEquals(PREFERENCE_1, candidatePath.getPreference().longValue());
+        Assert.assertEquals(ProvisioningMethodConfig.class, candidatePath.getProvisioningMethod());
+
+        //verify candidate-paths/state container
+        Assert.assertNotNull(candidatePath.getState());
+        Assert.assertEquals(DISTINGUISHER_1, candidatePath.getState().getDistinguisher().longValue());
+        Assert.assertEquals(PREFERENCE_1, candidatePath.getState().getPreference().longValue());
+        Assert.assertEquals(ProvisioningMethodConfig.class, candidatePath.getState().getProvisioningMethod());
+        Assert.assertEquals(PathExplicitlyDefined.class, candidatePath.getState().getComputationMethod());
+        Assert.assertNotNull(candidatePath.getBindingSid());
+        Assert.assertNotNull(candidatePath.getBindingSid().getState());
+        Assert.assertEquals(BSID_ADR.getValue(),
+                candidatePath.getBindingSid().getState().getValue().getIpAddress().getIpv6Address().getValue());
+
+        //verify candidate-paths/segment-lists container
+        Assert.assertNotNull(candidatePath.getSegmentLists());
+        Assert.assertNotNull(candidatePath.getSegmentLists().getSegmentList());
+        Assert.assertEquals(1, candidatePath.getSegmentLists().getSegmentList().size());
+        SegmentList segmentList = candidatePath.getSegmentLists().getSegmentList().get(0);
+        Assert.assertEquals(Srv6Util.getCandidatePathName(BSID_ADR, WEIGHT), segmentList.getName());
+        Assert.assertNotNull(segmentList.getState());
+        Assert.assertEquals(WEIGHT, segmentList.getState().getWeight().intValue());
+        Assert.assertEquals(SegmentListOperState.ACTIVE, segmentList.getState().getOperState());
+
+        //verify merge
+        PoliciesBuilder policiesBuilder = new PoliciesBuilder();
+        Policy policy = policyBuilder.build();
+        customizer.merge(policiesBuilder, policy);
+        Assert.assertEquals(policy, policiesBuilder.getPolicy().get(0));
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizerTest.java
new file mode 100644 (file)
index 0000000..bc5ad68
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering;
+
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppL2AutorouteIncludeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.InterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceCustomizerTest extends SteeringTest {
+
+    private static final String LOCAL_0 = "local0";
+    private static final InterfaceKey L2_KEY = new InterfaceKey(LOCAL_0);
+
+    private NamingContext interfaceContext;
+
+    @Override
+    protected void init() {
+        super.init();
+        defineMapping(mappingContext, LOCAL_0, 1, "interface-context");
+        defineMapping(mappingContext, "vlan0", 2, "interface-context");
+        when(ctx.getMappingContext()).thenReturn(mappingContext);
+        when(readCtx.getMappingContext()).thenReturn(mappingContext);
+        interfaceContext = new NamingContext("iface", "interface-context");
+    }
+
+    @Test
+    public void readCurrentAttributesTest() throws ReadFailedException {
+        InstanceIdentifier<Interface> key =
+                Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, new PolicyKey(0L, new IpAddress(new Ipv6Address("e::1"))))
+                        .child(AutorouteInclude.class)
+                        .augmentation(VppL2AutorouteIncludeAugmentation.class).child(Interfaces.class)
+                        .child(Interface.class, L2_KEY);
+
+        InterfaceCustomizer customizer = new InterfaceCustomizer(api, interfaceContext);
+        InterfaceBuilder builder = customizer.getBuilder(key);
+        customizer.readCurrentAttributes(key, builder, readCtx);
+
+        Assert.assertEquals(L2_KEY, builder.getKey());
+        Assert.assertEquals(LOCAL_0, builder.getInputInterface());
+
+        InterfacesBuilder policyBuilder = new InterfacesBuilder();
+        customizer.merge(policyBuilder, builder.build());
+
+        Assert.assertNotNull(policyBuilder.getInterface());
+        Assert.assertEquals(1, policyBuilder.getInterface().size());
+    }
+
+    @Test
+    public void getAllIdsTest() throws ReadFailedException {
+        InterfaceCustomizer customizer = new InterfaceCustomizer(api, interfaceContext);
+        List<InterfaceKey> l2SteeringKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC, readCtx);
+
+        Assert.assertNotNull(l2SteeringKeys);
+        Assert.assertFalse(l2SteeringKeys.isEmpty());
+        Assert.assertEquals(1, l2SteeringKeys.size());
+        Assert.assertTrue(l2SteeringKeys.containsAll(ImmutableSet.of(L2_KEY)));
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizerTest.java
new file mode 100644 (file)
index 0000000..5685007
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering;
+
+import com.google.common.collect.ImmutableSet;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class PrefixCustomizerTest extends SteeringTest {
+
+    private static final IpPrefix IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("a::/64"));
+    private static final PrefixKey L3_KEY = new PrefixKey(IPV6_PREFIX);
+    private static final IpPrefix IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("10.0.0.1/24"));
+    private static final PrefixKey L3_KEY_2 = new PrefixKey(IPV4_PREFIX);
+
+    @Test
+    public void readCurrentAttributesTest() throws ReadFailedException {
+        KeyedInstanceIdentifier<Prefix, PrefixKey> key =
+                Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, new PolicyKey(0L, new IpAddress(new Ipv6Address("e::1"))))
+                        .child(AutorouteInclude.class).child(Prefixes.class).child(Prefix.class, L3_KEY);
+
+        PrefixCustomizer customizer = new PrefixCustomizer(api);
+        PrefixBuilder builder = customizer.getBuilder(key);
+
+        customizer.readCurrentAttributes(key, builder, readCtx);
+
+        Assert.assertEquals(L3_KEY, builder.getKey());
+        Assert.assertEquals(IPV6_PREFIX, builder.getIpPrefix());
+
+        PrefixesBuilder policyBuilder = new PrefixesBuilder();
+        customizer.merge(policyBuilder, builder.build());
+
+        Assert.assertNotNull(policyBuilder.getPrefix());
+        Assert.assertEquals(1, policyBuilder.getPrefix().size());
+    }
+
+    @Test
+    public void getAllIdsTest() throws ReadFailedException {
+        PrefixCustomizer customizer = new PrefixCustomizer(api);
+        List<PrefixKey> l3SteeringKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_IID, readCtx);
+
+        Assert.assertNotNull(l3SteeringKeys);
+        Assert.assertFalse(l3SteeringKeys.isEmpty());
+        Assert.assertEquals(2, l3SteeringKeys.size());
+        Assert.assertTrue(l3SteeringKeys.containsAll(ImmutableSet.of(L3_KEY, L3_KEY_2)));
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizerTest.java
new file mode 100644 (file)
index 0000000..951f94d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.read.steering;
+
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.StateBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PrefixesStateCustomizerTest extends SteeringTest {
+
+    @Test
+    public void readCurrentAttributesTest() throws ReadFailedException {
+        InstanceIdentifier<State> iId =
+                Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, new PolicyKey(0L, new IpAddress(new Ipv6Address("e::1"))))
+                        .child(AutorouteInclude.class).child(Prefixes.class).child(State.class);
+
+        PrefixesStateCustomizer customizer = new PrefixesStateCustomizer(api);
+        StateBuilder builder = customizer.getBuilder(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_STATE);
+
+        customizer.readCurrentAttributes(iId, builder, readCtx);
+        Assert.assertEquals(false, builder.isPrefixesAll());
+
+        PrefixesBuilder parentBuilder = new PrefixesBuilder();
+        customizer.merge(parentBuilder, builder.build());
+
+        Assert.assertNotNull(parentBuilder.getState());
+        Assert.assertEquals(false, parentBuilder.getState().isPrefixesAll());
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/SteeringTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/SteeringTest.java
new file mode 100644 (file)
index 0000000..57f4fe8
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.read.steering;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.srv6.write.sid.request.LocalSidRequestTest;
+import io.fd.honeycomb.translate.ModificationCache;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetails;
+import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetailsReplyDump;
+import io.fd.vpp.jvpp.core.types.Srv6Sid;
+import java.util.ArrayList;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+
+public abstract class SteeringTest extends LocalSidRequestTest {
+    private static final Ipv6Address A = new Ipv6Address("a::");
+    private static final Ipv4Address B = new Ipv4Address("10.0.0.1");
+    static final Ipv6Address BSID_ADR = new Ipv6Address("a::e");
+
+    @Mock
+    ReadContext readCtx;
+
+    @Mock
+    ModificationCache modificationCache;
+
+    SrSteeringPolDetailsReplyDump replyDump = new SrSteeringPolDetailsReplyDump();
+
+    @Override
+    protected void init() {
+        when(readCtx.getModificationCache()).thenReturn(modificationCache);
+        when(modificationCache.get(any())).thenReturn(replyDump);
+        replyDump.srSteeringPolDetails = new ArrayList<>();
+        SrSteeringPolDetails polDetailsA = new SrSteeringPolDetails();
+        polDetailsA.trafficType = 6;
+        polDetailsA.fibTable = 1;
+        polDetailsA.prefixAddr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(A));
+        Srv6Sid bsidA = new Srv6Sid();
+        bsidA.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR));
+        polDetailsA.bsid = bsidA;
+        polDetailsA.maskWidth = 64;
+
+        SrSteeringPolDetails polDetailsB = new SrSteeringPolDetails();
+        polDetailsB.trafficType = 4;
+        polDetailsB.fibTable = 0;
+        polDetailsB.prefixAddr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(B));
+        Srv6Sid bsidB = new Srv6Sid();
+        bsidB.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR));
+        polDetailsB.bsid = bsidB;
+        polDetailsB.maskWidth = 24;
+
+        SrSteeringPolDetails polDetailsC = new SrSteeringPolDetails();
+        polDetailsC.trafficType = 2;
+        polDetailsC.swIfIndex = 1;
+        bsidA.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR));
+        polDetailsA.bsid = bsidA;
+
+        replyDump.srSteeringPolDetails.add(polDetailsA);
+        replyDump.srSteeringPolDetails.add(polDetailsB);
+        replyDump.srSteeringPolDetails.add(polDetailsC);
+    }
+}
index cd33699..f241716 100644 (file)
@@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableSet;
 import com.google.inject.Inject;
 import io.fd.hc2vpp.common.test.util.FutureProducer;
 import io.fd.hc2vpp.common.test.util.NamingContextHelper;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistry;
 import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionWriteBindingRegistry;
@@ -35,12 +36,18 @@ import io.fd.honeycomb.test.tools.HoneycombTestRunner;
 import io.fd.honeycomb.test.tools.annotations.SchemaContextProvider;
 import io.fd.honeycomb.translate.MappingContext;
 import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel;
 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.Ipv6Address;
+
 
 @RunWith(HoneycombTestRunner.class)
 public abstract class JvppRequestTest implements FutureProducer, NamingContextHelper {
@@ -49,6 +56,14 @@ public abstract class JvppRequestTest implements FutureProducer, NamingContextHe
     protected static final LocalSidFunctionWriteBindingRegistry WRITE_REGISTRY =
             new LocalSidFunctionWriteBindingRegistry();
 
+    protected static final String NAMED_SEG_LISTS_PATH = "/hc2vpp-oc-srte-policy:segment-routing" +
+            "/hc2vpp-oc-srte-policy:traffic-engineering" +
+            "/hc2vpp-oc-srte-policy:named-segment-lists";
+
+    protected static final String POLICIES_LISTS_PATH = "/hc2vpp-oc-srte-policy:segment-routing" +
+            "/hc2vpp-oc-srte-policy:traffic-engineering" +
+            "/hc2vpp-oc-srte-policy:policies";
+
     @Inject
     @Mock
     protected static FutureJVppCore api;
@@ -104,9 +119,35 @@ public abstract class JvppRequestTest implements FutureProducer, NamingContextHe
                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.$YangModuleInfoImpl
                         .getInstance(),
                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.$YangModuleInfoImpl
+                        .getInstance(),
+                org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.$YangModuleInfoImpl
+                        .getInstance(),
+                org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.$YangModuleInfoImpl
                         .getInstance()));
         return mibContext;
     }
 
     protected abstract void init();
+
+    protected void testSrSteeringAddDelValidity(SrSteeringAddDel srSteering, byte isDel, byte trafficType, boolean ipV6,
+                                                Ipv6Address bsidAdr, IpPrefix prefix) {
+        Assert.assertEquals((long) 0, srSteering.tableId);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(bsidAdr)),
+                srSteering.bsidAddr);
+        Assert.assertEquals(isDel, srSteering.isDel);
+        Assert.assertEquals(trafficType, srSteering.trafficType);
+
+        if (ipV6) {
+            Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipv6AddressPrefixToArray(prefix.getIpv6Prefix()),
+                    srSteering.prefixAddr);
+            Assert.assertEquals(AddressTranslator.INSTANCE.extractPrefix(prefix.getIpv6Prefix()),
+                    srSteering.maskWidth);
+        } else {
+            Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipv4AddressPrefixToArray(prefix.getIpv4Prefix()),
+                    srSteering.prefixAddr);
+            Assert.assertEquals(AddressTranslator.INSTANCE.extractPrefix(prefix.getIpv4Prefix()),
+                    srSteering.maskWidth);
+        }
+
+    }
 }
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/Srv6UtilTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/Srv6UtilTest.java
new file mode 100644 (file)
index 0000000..89d97be
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package io.fd.hc2vpp.srv6.util;
+
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.Policies;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class Srv6UtilTest extends JvppRequestTest{
+    private static final Ipv6Address BSID = new Ipv6Address("a::e");
+    private static final String CANDIDATE_PATH_NAME = BSID.getValue() + "-0";
+    private static final PolicyKey POLICY_KEY = new PolicyKey(1L, new IpAddress(new Ipv6Address("e::1")));
+    private static final InstanceIdentifier<Policy> POLICY_IID =
+            Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY);
+
+    @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH)
+    private Policies policies;
+
+    @Override
+    protected void init() {
+        when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+    }
+
+    @Test
+    public void getCandidatePathNameTest() {
+        Assert.assertEquals(CANDIDATE_PATH_NAME, Srv6Util.getCandidatePathName(BSID, 0L));
+    }
+
+    @Test
+    public void extractBsidTest() {
+        Assert.assertEquals(BSID.getValue(), Srv6Util.extractBsid(POLICY_IID, ctx, true).getValue());
+    }
+
+    @Test
+    public void extractVrfFibTest() {
+        Assert.assertEquals(0, Srv6Util.extractVrfFib(POLICY_IID, ctx, true));
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizerTest.java
new file mode 100644 (file)
index 0000000..80a3149
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.policy;
+
+import static io.fd.hc2vpp.srv6.util.Srv6Util.getCandidatePathName;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.fib.management.FibManagementIIds;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.util.CandidatePathContextManager;
+import io.fd.hc2vpp.srv6.util.JvppRequestTest;
+import io.fd.hc2vpp.srv6.util.PolicyContextManager;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrPolicyAdd;
+import io.fd.vpp.jvpp.core.dto.SrPolicyAddReply;
+import io.fd.vpp.jvpp.core.dto.SrPolicyDel;
+import io.fd.vpp.jvpp.core.dto.SrPolicyDelReply;
+import io.fd.vpp.jvpp.core.dto.SrPolicyMod;
+import io.fd.vpp.jvpp.core.dto.SrPolicyModReply;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentLists;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.Policies;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.Ipv6;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.TableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.TableKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+
+public class PolicyCustomizerTest extends JvppRequestTest {
+
+    private static final VniReference TABLE_ID = new VniReference(0L);
+    private static final Ipv6Address BSID_ADR = new Ipv6Address("a::e");
+    private static final String PATH_NAME = getCandidatePathName(BSID_ADR, 0L);
+    private static final String PATH_NAME_2 = getCandidatePathName(BSID_ADR, 1L);
+    private static final Ipv6AddressNoZone A_ADDR = new Ipv6AddressNoZone("a::");
+    private static final Ipv6AddressNoZone B_ADDR = new Ipv6AddressNoZone("b::");
+    private static final Ipv6AddressNoZone C_ADDR = new Ipv6AddressNoZone("c::");
+    private static final PolicyKey POLICY_KEY = new PolicyKey(1L, new IpAddress(new Ipv6Address("e::1")));
+    private static final KeyedInstanceIdentifier<Table, TableKey> VRF_IID =
+            FibManagementIIds.FM_FIB_TABLES.child(Table.class, new TableKey(Ipv6.class, TABLE_ID));
+    private static final Table VRF_TABLE = new TableBuilder().setKey(VRF_IID.getKey()).setAddressFamily(Ipv6.class)
+            .setTableId(TABLE_ID).setName("VRF-0").build();
+
+    @InjectTestData(resourcePath = "/named-segments.json", id = NAMED_SEG_LISTS_PATH)
+    private NamedSegmentLists namedSegmentLists;
+    @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH)
+    private Policies policies;
+
+    @Mock
+    private PolicyContextManager policyCtx;
+    @Mock
+    private CandidatePathContextManager candidatePathCtx;
+
+    @Captor
+    private ArgumentCaptor<SrPolicyAdd> requestcaptorAdd;
+    @Captor
+    private ArgumentCaptor<SrPolicyDel> requestcaptorDel;
+    @Captor
+    private ArgumentCaptor<SrPolicyMod> requestcaptorMod;
+
+    @Override
+    protected void init() {
+        when(api.srPolicyAdd(any())).thenReturn(future(new SrPolicyAddReply()));
+        when(api.srPolicyDel(any())).thenReturn(future(new SrPolicyDelReply()));
+        when(api.srPolicyMod(any())).thenReturn(future(new SrPolicyModReply()));
+        when(ctx.readAfter(
+                Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, new NamedSegmentListKey(PATH_NAME))))
+                .thenReturn(Optional.of(namedSegmentLists.getNamedSegmentList().get(0)));
+        when(ctx.readAfter(
+                Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, new NamedSegmentListKey(PATH_NAME_2))))
+                .thenReturn(Optional.of(namedSegmentLists.getNamedSegmentList().get(1)));
+        when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+        when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+        when(ctx.readAfter(VRF_IID)).thenReturn(Optional.of(VRF_TABLE));
+    }
+
+    @Test
+    public void writeCurrentAttributesTest() throws WriteFailedException {
+        PolicyCustomizer customizer = new PolicyCustomizer(api, policyCtx, candidatePathCtx);
+        customizer.writeCurrentAttributes(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY),
+                policies.getPolicy().get(0), ctx);
+
+        verify(api, times(1)).srPolicyAdd(requestcaptorAdd.capture());
+        SrPolicyAdd srPolicy = requestcaptorAdd.getValue();
+
+        verify(api, times(1)).srPolicyMod(requestcaptorMod.capture());
+        SrPolicyMod srPolicyMod = requestcaptorMod.getValue();
+
+        Assert.assertEquals(0L, srPolicy.fibTable);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)),
+                srPolicy.bsidAddr);
+        Assert.assertEquals(ByteDataTranslator.BYTE_TRUE, srPolicy.isEncap);
+        Assert.assertEquals(0, srPolicy.type);
+        Assert.assertNotNull(srPolicy.sids);
+        Assert.assertEquals(3, srPolicy.sids.numSids);
+        Assert.assertEquals(0, srPolicy.sids.weight);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(B_ADDR)),
+                srPolicy.sids.sids[0].addr);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(C_ADDR)),
+                srPolicy.sids.sids[1].addr);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(A_ADDR)),
+                srPolicy.sids.sids[2].addr);
+
+        Assert.assertEquals(0L, srPolicyMod.fibTable);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)),
+                srPolicyMod.bsidAddr);
+        Assert.assertNotNull(srPolicy.sids);
+        Assert.assertEquals(3, srPolicyMod.sids.numSids);
+        Assert.assertEquals(1, srPolicyMod.sids.weight);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(C_ADDR)),
+                srPolicyMod.sids.sids[0].addr);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(B_ADDR)),
+                srPolicyMod.sids.sids[1].addr);
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(A_ADDR)),
+                srPolicyMod.sids.sids[2].addr);
+    }
+
+    @Test
+    public void deleteCurrentAttributesTest() throws WriteFailedException {
+        PolicyCustomizer customizer = new PolicyCustomizer(api, policyCtx, candidatePathCtx);
+        customizer.deleteCurrentAttributes(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY),
+                policies.getPolicy().get(0), ctx);
+
+        verify(api, times(1)).srPolicyDel(requestcaptorDel.capture());
+        SrPolicyDel srPolicy = requestcaptorDel.getValue();
+
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)),
+                srPolicy.bsidAddr.addr);
+    }
+
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizerTest.java
new file mode 100644 (file)
index 0000000..fa47870
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.steering;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.AddressTranslator;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.util.JvppRequestTest;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDelReply;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.Policies;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppL2AutorouteIncludeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacesConfigCustomizerTest extends JvppRequestTest {
+
+    private static final PolicyKey POLICY_KEY = new PolicyKey(1L, new IpAddress(new Ipv6Address("e::1")));
+    private static final Ipv6Address BSID_ADR = new Ipv6Address("a::e");
+    private static final String LOCAL_0 = "local0";
+    private static final InterfaceKey L2_KEY = new InterfaceKey(LOCAL_0);
+    private static final Interface L2_STEERING = new InterfaceBuilder().setInputInterface(LOCAL_0)
+            .setConfig(new ConfigBuilder().setInputInterface(LOCAL_0).build()).build();
+
+    private InstanceIdentifier<Interface> L2_STEER_IID =
+            Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)
+                    .child(AutorouteInclude.class)
+                    .augmentation(VppL2AutorouteIncludeAugmentation.class).child(Interfaces.class)
+                    .child(Interface.class, L2_KEY);
+
+    private NamingContext interfaceContext;
+
+    @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH)
+    private Policies policies;
+
+    @Captor
+    private ArgumentCaptor<SrSteeringAddDel> requestcaptor;
+
+    @Override
+    protected void init() {
+        when(api.srSteeringAddDel(any())).thenReturn(future(new SrSteeringAddDelReply()));
+        defineMapping(mappingContext, LOCAL_0, 1, "interface-context");
+        defineMapping(mappingContext, "vlan0", 2, "interface-context");
+        when(ctx.getMappingContext()).thenReturn(mappingContext);
+        interfaceContext = new NamingContext("iface", "interface-context");
+        when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+        when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+    }
+
+    @Test
+    public void writeCurrentAttributesTest() throws WriteFailedException {
+        InterfacesConfigCustomizer customizer = new InterfacesConfigCustomizer(api, interfaceContext);
+        customizer.writeCurrentAttributes(L2_STEER_IID, L2_STEERING, ctx);
+
+        verify(api, times(1)).srSteeringAddDel(requestcaptor.capture());
+        SrSteeringAddDel srSteering = requestcaptor.getValue();
+
+        testRequestValidity(srSteering, ByteDataTranslator.BYTE_FALSE);
+    }
+
+    @Test
+    public void deleteCurrentAttributesV6Test() throws WriteFailedException {
+        InterfacesConfigCustomizer customizer = new InterfacesConfigCustomizer(api, interfaceContext);
+        customizer.deleteCurrentAttributes(L2_STEER_IID, L2_STEERING, ctx);
+
+        verify(api, times(1)).srSteeringAddDel(requestcaptor.capture());
+        SrSteeringAddDel srSteering = requestcaptor.getValue();
+
+        testRequestValidity(srSteering, ByteDataTranslator.BYTE_TRUE);
+    }
+
+    private void testRequestValidity(SrSteeringAddDel srSteering, byte byteTrue) {
+        Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)),
+                                 srSteering.bsidAddr);
+        Assert.assertEquals(byteTrue, srSteering.isDel);
+        Assert.assertEquals((byte) 2, srSteering.trafficType);
+        Assert.assertEquals(1, srSteering.swIfIndex);
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizerTest.java
new file mode 100644 (file)
index 0000000..9335ab6
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.steering;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.util.JvppRequestTest;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDelReply;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.Policies;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixBuilder;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PrefixCustomizerTest extends JvppRequestTest {
+
+    private static final PolicyKey POLICY_KEY = new PolicyKey(1L, new IpAddress(new Ipv6Address("e::1")));
+    private static final InstanceIdentifier<Prefixes>
+            PREFIXES_IID = Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY).child(AutorouteInclude.class)
+            .child(Prefixes.class);
+    private static final Ipv6Address BSID_ADR = new Ipv6Address("a::e");
+    private static final IpPrefix IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("a::/64"));
+    private static final PrefixKey L3_STEER_KEY = new PrefixKey(IPV6_PREFIX);
+    private static final IpPrefix IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("10.0.0.1/24"));
+    private static final PrefixKey L3_STEER_KEY_2 = new PrefixKey(IPV4_PREFIX);
+
+    private static final Prefix L3_STEERING_V6 = new PrefixBuilder()
+            .setIpPrefix(IPV6_PREFIX)
+            .setConfig(new ConfigBuilder().setIpPrefix(IPV6_PREFIX).build())
+            .build();
+
+    private static final Prefix L3_STEERING_V4 = new PrefixBuilder()
+            .setIpPrefix(IPV4_PREFIX)
+            .setConfig(new ConfigBuilder().setIpPrefix(IPV4_PREFIX).build())
+            .build();
+
+    private InstanceIdentifier<Prefix> L3_STEER_V6_IID = PREFIXES_IID.child(Prefix.class, L3_STEER_KEY);
+    private InstanceIdentifier<Prefix> L3_STEER_V4_IID = PREFIXES_IID.child(Prefix.class, L3_STEER_KEY_2);
+
+    @Captor
+    private ArgumentCaptor<SrSteeringAddDel> requestcaptor;
+
+    @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH)
+    private Policies policies;
+
+    @Override
+    protected void init() {
+        when(api.srSteeringAddDel(any())).thenReturn(future(new SrSteeringAddDelReply()));
+        when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+        when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+    }
+
+    @Test
+    public void writeCurrentAttributesV6Test() throws WriteFailedException {
+        PrefixCustomizer customizer = new PrefixCustomizer(api);
+        customizer.writeCurrentAttributes(L3_STEER_V6_IID, L3_STEERING_V6, ctx);
+
+        verify(api, times(1)).srSteeringAddDel(requestcaptor.capture());
+        SrSteeringAddDel srSteering = requestcaptor.getValue();
+
+        testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_FALSE, (byte) 6, true, BSID_ADR, IPV6_PREFIX);
+    }
+
+    @Test
+    public void writeCurrentAttributesV4Test() throws WriteFailedException {
+        PrefixCustomizer customizer = new PrefixCustomizer(api);
+        customizer.writeCurrentAttributes(L3_STEER_V4_IID, L3_STEERING_V4, ctx);
+
+        verify(api, times(1)).srSteeringAddDel(requestcaptor.capture());
+        SrSteeringAddDel srSteering = requestcaptor.getValue();
+
+        testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_FALSE, (byte) 4, false, BSID_ADR, IPV4_PREFIX);
+    }
+
+    @Test
+    public void deleteCurrentAttributesV6Test() throws WriteFailedException {
+        PrefixCustomizer customizer = new PrefixCustomizer(api);
+        customizer.deleteCurrentAttributes(L3_STEER_V6_IID, L3_STEERING_V6, ctx);
+
+        verify(api, times(1)).srSteeringAddDel(requestcaptor.capture());
+        SrSteeringAddDel srSteering = requestcaptor.getValue();
+
+        testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_TRUE, (byte) 6, true, BSID_ADR, IPV6_PREFIX);
+    }
+
+    @Test
+    public void deleteCurrentAttributesV4Test() throws WriteFailedException {
+        PrefixCustomizer customizer = new PrefixCustomizer(api);
+        customizer.deleteCurrentAttributes(L3_STEER_V4_IID, L3_STEERING_V4, ctx);
+
+        verify(api, times(1)).srSteeringAddDel(requestcaptor.capture());
+        SrSteeringAddDel srSteering = requestcaptor.getValue();
+
+        testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_TRUE, (byte) 4, false, BSID_ADR, IPV4_PREFIX);
+    }
+}
diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizerTest.java
new file mode 100644 (file)
index 0000000..64e0032
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.hc2vpp.srv6.write.steering;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.base.Optional;
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.hc2vpp.srv6.Srv6PolicyIIds;
+import io.fd.hc2vpp.srv6.util.JvppRequestTest;
+import io.fd.hc2vpp.srv6.write.steering.request.L3SteeringRequest;
+import io.fd.honeycomb.test.tools.annotations.InjectTestData;
+import io.fd.honeycomb.translate.write.WriteFailedException;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel;
+import io.fd.vpp.jvpp.core.dto.SrSteeringAddDelReply;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.Policies;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config;
+import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PrefixesConfigCustomizerTest extends JvppRequestTest {
+    private static final Ipv6Address BSID_ADR = new Ipv6Address("a::e");
+    private static final IpPrefix DEFAULT_IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("::/0"));
+    private static final IpPrefix DEFAULT_IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("0.0.0.0/0"));
+    private static final PolicyKey POLICY_KEY = new PolicyKey(1L, new IpAddress(new Ipv6Address("e::1")));
+    private static final Config CONFIG = new ConfigBuilder().setPrefixesAll(true).build();
+    private InstanceIdentifier<Config> PREFIXES_CFG_IID =
+            Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY).child(AutorouteInclude.class).child(Prefixes.class)
+                    .child(Config.class);
+    @Captor
+    private ArgumentCaptor<SrSteeringAddDel> requestcaptor;
+
+    @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH)
+    private Policies policies;
+
+    @Override
+    protected void init() {
+        when(api.srSteeringAddDel(any())).thenReturn(future(new SrSteeringAddDelReply()));
+        when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+        when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY)))
+                .thenReturn(Optional.of(policies.getPolicy().get(0)));
+    }
+
+    @Test
+    public void writeCurrentAttributes() throws WriteFailedException {
+        PrefixesConfigCustomizer customizer = new PrefixesConfigCustomizer(api);
+        customizer.writeCurrentAttributes(PREFIXES_CFG_IID, CONFIG, ctx);
+
+        verify(api, times(2)).srSteeringAddDel(requestcaptor.capture());
+        List<SrSteeringAddDel> srSteerings = requestcaptor.getAllValues();
+
+        testSrSteeringAddDelValidity(srSteerings.get(0), ByteDataTranslator.BYTE_FALSE, L3SteeringRequest.VPP_IPV6_TYPE,
+                true, BSID_ADR, DEFAULT_IPV6_PREFIX);
+        testSrSteeringAddDelValidity(srSteerings.get(1), ByteDataTranslator.BYTE_FALSE,
+                L3SteeringRequest.VPP_IPV4_TYPE, false, BSID_ADR, DEFAULT_IPV4_PREFIX);
+    }
+
+    @Test
+    public void deleteCurrentAttributes() throws WriteFailedException {
+        PrefixesConfigCustomizer customizer = new PrefixesConfigCustomizer(api);
+        customizer.deleteCurrentAttributes(PREFIXES_CFG_IID, CONFIG, ctx);
+
+        verify(api, times(2)).srSteeringAddDel(requestcaptor.capture());
+        List<SrSteeringAddDel> srSteerings = requestcaptor.getAllValues();
+
+        testSrSteeringAddDelValidity(srSteerings.get(0), ByteDataTranslator.BYTE_TRUE, L3SteeringRequest.VPP_IPV6_TYPE,
+                true, BSID_ADR, DEFAULT_IPV6_PREFIX);
+        testSrSteeringAddDelValidity(srSteerings.get(1), ByteDataTranslator.BYTE_TRUE, L3SteeringRequest.VPP_IPV4_TYPE,
+                false, BSID_ADR, DEFAULT_IPV4_PREFIX);
+    }
+
+}
diff --git a/srv6/srv6-impl/src/test/resources/named-segments.json b/srv6/srv6-impl/src/test/resources/named-segments.json
new file mode 100644 (file)
index 0000000..039db0b
--- /dev/null
@@ -0,0 +1,74 @@
+{
+  "named-segment-lists": {
+    "named-segment-list": [
+      {
+        "name": "a::e-0",
+        "config": {
+          "name": "a::e-0"
+        },
+        "segments": {
+          "segment": [
+            {
+              "index": 1,
+              "config": {
+                "index": 1,
+                "type": "type-2",
+                "sid-value": "c::"
+              }
+            },
+            {
+              "index": 2,
+              "config": {
+                "index": 2,
+                "type": "type-2",
+                "sid-value": "b::"
+              }
+            },
+            {
+              "index": 3,
+              "config": {
+                "index": 3,
+                "type": "type-2",
+                "sid-value": "a::"
+              }
+            }
+          ]
+        }
+      },
+      {
+        "name": "a::e-1",
+        "config": {
+          "name": "a::e-1"
+        },
+        "segments": {
+          "segment": [
+            {
+              "index": 1,
+              "config": {
+                "index": 1,
+                "type": "type-2",
+                "sid-value": "b::"
+              }
+            },
+            {
+              "index": 2,
+              "config": {
+                "index": 2,
+                "type": "type-2",
+                "sid-value": "c::"
+              }
+            },
+            {
+              "index": 3,
+              "config": {
+                "index": 3,
+                "type": "type-2",
+                "sid-value": "a::"
+              }
+            }
+          ]
+        }
+      }
+    ]
+  }
+}
diff --git a/srv6/srv6-impl/src/test/resources/policy.json b/srv6/srv6-impl/src/test/resources/policy.json
new file mode 100644 (file)
index 0000000..5c1e256
--- /dev/null
@@ -0,0 +1,94 @@
+{
+  "policies": {
+    "policy": [{
+      "name": "a::e",
+      "config": {
+        "name": "a::e",
+        "color": 1,
+        "endpoint": "e::1",
+        "admin-state": "UP"
+      },
+      "color": 1,
+      "endpoint": "e::1",
+      "candidate-paths": {
+        "candidate-path": [{
+          "name": "candidatePath1",
+          "provisioning-method": "provisioning-method-config",
+          "preference": 100,
+          "distinguisher": 0,
+          "config": {
+            "name": "candidatePath1",
+            "provisioning-method": "provisioning-method-config",
+            "computation-method": "path-explicitly-defined",
+            "preference": 100,
+            "distinguisher": 0
+          },
+          "binding-sid": {
+            "config": {
+              "alloc-mode": "explicit",
+              "type": "srv6",
+              "value": "a::e"
+            }
+          },
+          "segment-lists": {
+            "segment-list": [{
+              "name": "a::e-0",
+              "config": {
+                "name": "a::e-0",
+                "weight": 0
+              }
+            },
+              {
+                "name": "a::e-1",
+                "config": {
+                  "name": "a::e-1",
+                  "weight": 1
+                }
+              }
+            ]
+          }
+        }]
+      },
+      "autoroute-include": {
+        "config": {
+          "metric-type": "constant",
+          "metric-constant": 0
+        },
+        "prefixes": {
+          "config": {
+            "prefixes-all": false
+          },
+          "prefix": [{
+            "ip-prefix": "e::/64",
+            "config": {
+              "ip-prefix": "e::/64"
+            }
+          }]
+        },
+        "interfaces": {
+          "interface": [{
+            "input-interface": "loop0",
+            "config": {
+              "input-interface": "loop0"
+            }
+          }]
+        }
+      },
+      "binding-sid": {
+        "config": {
+          "alloc-mode": "explicit",
+          "type": "srv6",
+          "value": "a::e"
+        }
+      },
+      "vpp-oc-srte-policy:vpp-sr-policy": {
+        "config": {
+          "policy-type": "Default",
+          "policy-behavior": "Encapsulation",
+          "table-id": 0,
+          "address-family": "vpp-fib-table-management:ipv6"
+        }
+      }
+    }]
+  }
+}
diff --git a/srv6/srv6_policy_postman_collection.json b/srv6/srv6_policy_postman_collection.json
new file mode 100755 (executable)
index 0000000..1d9ca4e
--- /dev/null
@@ -0,0 +1,282 @@
+{
+       "info": {
+               "_postman_id": "9c24a300-8374-4574-b179-650a3c836439",
+               "name": "SRv6 Policy",
+               "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+       },
+       "item": [
+               {
+                       "name": "1. Write IPv6 FIB 0 (to store SRv6 policies)",
+                       "request": {
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       },
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n    \"vpp-fib-table-management:table\": [\n        {\n            \"table-id\": 0,\n            \"address-family\": \"vpp-fib-table-management:ipv6\",\n            \"name\": \"ipv6-VRF:0\"\n        }\n    ]\n}"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/vpp-fib-table-management:fib-table-management/vpp-fib-table-management:fib-tables/table/0/vpp-fib-table-management:ipv6",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "vpp-fib-table-management:fib-table-management",
+                                               "vpp-fib-table-management:fib-tables",
+                                               "table",
+                                               "0",
+                                               "vpp-fib-table-management:ipv6"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "2. SRv6 policy",
+                       "request": {
+                               "auth": {
+                                       "type": "basic",
+                                       "basic": [
+                                               {
+                                                       "key": "password",
+                                                       "value": "admin",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "key": "username",
+                                                       "value": "admin",
+                                                       "type": "string"
+                                               }
+                                       ]
+                               },
+                               "method": "PUT",
+                               "header": [
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": "{\n\t\"hc2vpp-oc-srte-policy:segment-routing\": {\n\t\t\"traffic-engineering\": {\n\t\t\t\"named-segment-lists\": {\n\t\t\t\t\"named-segment-list\": [{\n\t\t\t\t\t\"name\": \"a::e-1\",\n\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\"name\": \"a::e-1\"\n\t\t\t\t\t},\n\t\t\t\t\t\"segments\": {\n\t\t\t\t\t\t\"segment\": [{\n\t\t\t\t\t\t\t\"index\": 1,\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"index\": 1,\n\t\t\t\t\t\t\t\t\"type\": \"type-2\",\n\t\t\t\t\t\t\t\t\"sid-value\": \"a::\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"index\": 2,\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"index\": 2,\n\t\t\t\t\t\t\t\t\"type\": \"type-2\",\n\t\t\t\t\t\t\t\t\"sid-value\": \"d::\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"index\": 3,\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"index\": 3,\n\t\t\t\t\t\t\t\t\"type\": \"type-2\",\n\t\t\t\t\t\t\t\t\"sid-value\": \"e::\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"name\": \"a::e-2\",\n\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\"name\": \"a::e-2\"\n\t\t\t\t\t},\n\t\t\t\t\t\"segments\": {\n\t\t\t\t\t\t\"segment\": [{\n\t\t\t\t\t\t\t\"index\": 1,\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"index\": 1,\n\t\t\t\t\t\t\t\t\"type\": \"type-2\",\n\t\t\t\t\t\t\t\t\"sid-value\": \"d::\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"index\": 2,\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"index\": 2,\n\t\t\t\t\t\t\t\t\"type\": \"type-2\",\n\t\t\t\t\t\t\t\t\"sid-value\": \"e::\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"index\": 3,\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"index\": 3,\n\t\t\t\t\t\t\t\t\"type\": \"type-2\",\n\t\t\t\t\t\t\t\t\"sid-value\": \"a::\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}]\n\t\t\t\t\t}\n\t\t\t\t}]\n\t\t\t},\n\t\t\t\"policies\": {\n\t\t\t\t\"policy\": [{\n\t\t\t\t\t\"name\": \"a::e\",\n\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\"name\": \"a::e\",\n\t\t\t\t\t\t\"color\": 1,\n\t\t\t\t\t\t\"endpoint\": \"e::1\",\n\t\t\t\t\t\t\"admin-state\": \"UP\"\n\t\t\t\t\t},\n\t\t\t\t\t\"color\": 1,\n\t\t\t\t\t\"endpoint\": \"e::1\",\n\t\t\t\t\t\"candidate-paths\": {\n\t\t\t\t\t\t\"candidate-path\": [{\n\t\t\t\t\t\t\t\"name\": \"candidatePath1\",\n\t\t\t\t\t\t\t\"provisioning-method\": \"provisioning-method-config\",\n\t\t\t\t\t\t\t\"preference\": 100,\n\t\t\t\t\t\t\t\"distinguisher\": 0,\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"name\": \"candidatePath1\",\n\t\t\t\t\t\t\t\t\"provisioning-method\": \"provisioning-method-config\",\n\t\t\t\t\t\t\t\t\"computation-method\": \"path-explicitly-defined\",\n\t\t\t\t\t\t\t\t\"preference\": 100,\n\t\t\t\t\t\t\t\t\"distinguisher\": 0\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"binding-sid\": {\n\t\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\t\"alloc-mode\": \"explicit\",\n\t\t\t\t\t\t\t\t\t\"type\": \"srv6\",\n\t\t\t\t\t\t\t\t\t\"value\": \"a::e\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"segment-lists\": {\n\t\t\t\t\t\t\t\t\"segment-list\": [{\n\t\t\t\t\t\t\t\t\t\"name\": \"a::e-1\",\n\t\t\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\t\t\"name\": \"a::e-1\",\n\t\t\t\t\t\t\t\t\t\t\"weight\": 1\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"name\": \"a::e-2\",\n\t\t\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\t\t\"name\": \"a::e-2\",\n\t\t\t\t\t\t\t\t\t\t\"weight\": 2\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}]\n\t\t\t\t\t},\n\t\t\t\t\t\"autoroute-include\": {\n\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\"metric-type\": \"constant\",\n\t\t\t\t\t\t\t\"metric-constant\": 0\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"prefixes\": {\n\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\"prefixes-all\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"prefix\": [{\n\t\t\t\t\t\t\t\t\"ip-prefix\": \"e::/64\",\n\t\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\t\"ip-prefix\": \"e::/64\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"interfaces\": {\n\t\t\t\t\t\t\t\"interface\": [{\n\t\t\t\t\t\t\t\t\"input-interface\": \"loop0\",\n\t\t\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\t\t\"input-interface\": \"loop0\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"binding-sid\": {\n\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\"alloc-mode\": \"explicit\",\n\t\t\t\t\t\t\t\"type\": \"srv6\",\n\t\t\t\t\t\t\t\"value\": \"a::e\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"vpp-oc-srte-policy:vpp-sr-policy\": {\n\t\t\t\t\t\t\"config\": {\n\t\t\t\t\t\t\t\"policy-type\": \"Default\",\n\t\t\t\t\t\t\t\"policy-behavior\": \"Encapsulation\",\n\t\t\t\t\t\t\t\"table-id\": 0,\n        \t\t\t\t\t\"address-family\": \"vpp-fib-table-management:ipv6\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}]\n\t\t\t}\n\t\t}\n\t}\n}"
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-oc-srte-policy:segment-routing",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-oc-srte-policy:segment-routing"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "CandidatePathContext Read",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": ""
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/operational/naming-context:contexts\\srv6-candidate-path-mappings",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "operational",
+                                               "naming-context:contexts\\srv6-candidate-path-mappings"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "PolicyContext Read",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": ""
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/operational/naming-context:contexts\\srv6-policy-mappings",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "operational",
+                                               "naming-context:contexts\\srv6-policy-mappings"
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "Segment routing - traffic engineering read oper",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": ""
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/operational/hc2vpp-oc-srte-policy:segment-routing/traffic-engineering/",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "operational",
+                                               "hc2vpp-oc-srte-policy:segment-routing",
+                                               "traffic-engineering",
+                                               ""
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "autoroute include for policy (color 1, ep e::1)",
+                       "request": {
+                               "method": "GET",
+                               "header": [
+                                       {
+                                               "key": "Authorization",
+                                               "value": "Basic YWRtaW46YWRtaW4="
+                                       },
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": ""
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/operational/hc2vpp-oc-srte-policy:segment-routing/traffic-engineering/policies/policy/1/e::1/autoroute-include/",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "operational",
+                                               "hc2vpp-oc-srte-policy:segment-routing",
+                                               "traffic-engineering",
+                                               "policies",
+                                               "policy",
+                                               "1",
+                                               "e::1",
+                                               "autoroute-include",
+                                               ""
+                                       ]
+                               }
+                       },
+                       "response": []
+               },
+               {
+                       "name": "SRv6 policy delete",
+                       "request": {
+                               "auth": {
+                                       "type": "basic",
+                                       "basic": [
+                                               {
+                                                       "key": "password",
+                                                       "value": "admin",
+                                                       "type": "string"
+                                               },
+                                               {
+                                                       "key": "username",
+                                                       "value": "admin",
+                                                       "type": "string"
+                                               }
+                                       ]
+                               },
+                               "method": "DELETE",
+                               "header": [
+                                       {
+                                               "key": "Content-Type",
+                                               "value": "application/json"
+                                       }
+                               ],
+                               "body": {
+                                       "mode": "raw",
+                                       "raw": ""
+                               },
+                               "url": {
+                                       "raw": "http://localhost:8183/restconf/config/hc2vpp-oc-srte-policy:segment-routing",
+                                       "protocol": "http",
+                                       "host": [
+                                               "localhost"
+                                       ],
+                                       "port": "8183",
+                                       "path": [
+                                               "restconf",
+                                               "config",
+                                               "hc2vpp-oc-srte-policy:segment-routing"
+                                       ]
+                               }
+                       },
+                       "response": []
+               }
+       ]
+}
\ No newline at end of file