From b77a5725338dc700873b36c98af85d70acd7bbe4 Mon Sep 17 00:00:00 2001 From: Michal Cmarada Date: Fri, 15 Jun 2018 13:12:53 +0200 Subject: HC2VPP-304 - add SRv6 policy module new models: - hc2vpp-oc-srte-policy@2017-09-18.yang (ietf draft for srte-policies) - vpp-oc-srte-policy@2018-05-14.yang (augments oc-srte-policy model with VPP specific configuration) - policy-context@2018-06-07.yang 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 --- .../oc/srte/policy/rev170918/MplsLabelBuilder.java | 20 + .../srte/policy/rev170918/SidValueTypeBuilder.java | 20 + .../yang/hc2vpp-oc-srte-policy@2017-09-18.yang | 1507 ++++++++++++++++++++ .../src/main/yang/policy-context@2018-06-07.yang | 126 ++ .../main/yang/vpp-oc-srte-policy@2018-05-14.yang | 151 ++ srv6/srv6-impl/asciidoc/Readme.adoc | 31 +- srv6/srv6-impl/pom.xml | 3 +- .../main/java/io/fd/hc2vpp/srv6/Srv6Module.java | 14 +- .../java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java | 200 +++ .../hc2vpp/srv6/read/Srv6PolicyReaderFactory.java | 104 ++ .../io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java | 2 +- .../srv6/read/policy/NamedSegmentCustomizer.java | 80 ++ .../hc2vpp/srv6/read/policy/PolicyCustomizer.java | 75 + .../read/policy/request/PolicyReadRequest.java | 281 ++++ .../srv6/read/steering/InterfaceCustomizer.java | 72 + .../srv6/read/steering/PrefixCustomizer.java | 67 + .../read/steering/PrefixesStateCustomizer.java | 72 + .../read/steering/request/L2SteeringRequest.java | 83 ++ .../read/steering/request/L3SteeringRequest.java | 125 ++ .../read/steering/request/SteeringRequest.java | 43 + .../srv6/util/CandidatePathContextManager.java | 61 + .../srv6/util/CandidatePathContextManagerImpl.java | 112 ++ .../io/fd/hc2vpp/srv6/util/NoopCustomizer.java | 46 + .../fd/hc2vpp/srv6/util/PolicyContextManager.java | 68 + .../hc2vpp/srv6/util/PolicyContextManagerImpl.java | 108 ++ .../main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java | 99 ++ .../function/xconnect/EndDX2FunctionBinder.java | 2 + .../hc2vpp/srv6/write/Srv6PolicyWriterFactory.java | 88 ++ .../io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java | 2 +- .../hc2vpp/srv6/write/policy/PolicyCustomizer.java | 211 +++ .../write/policy/request/PolicyDeleteRequest.java | 60 + .../write/policy/request/PolicyWriteRequest.java | 178 +++ .../srv6/write/policy/request/dto/SidList.java | 64 + .../write/steering/InterfacesConfigCustomizer.java | 92 ++ .../srv6/write/steering/PrefixCustomizer.java | 71 + .../write/steering/PrefixesConfigCustomizer.java | 91 ++ .../write/steering/request/L2SteeringRequest.java | 65 + .../write/steering/request/L3SteeringRequest.java | 99 ++ .../write/steering/request/SteeringRequest.java | 52 + .../java/io/fd/hc2vpp/srv6/Srv6ModuleTest.java | 15 +- .../read/policy/NamedSegmentCustomizerTest.java | 101 ++ .../fd/hc2vpp/srv6/read/policy/PoliciesTest.java | 122 ++ .../srv6/read/policy/PolicyCustomizerTest.java | 143 ++ .../read/steering/InterfaceCustomizerTest.java | 90 ++ .../srv6/read/steering/PrefixCustomizerTest.java | 78 + .../read/steering/PrefixesStateCustomizerTest.java | 54 + .../fd/hc2vpp/srv6/read/steering/SteeringTest.java | 82 ++ .../io/fd/hc2vpp/srv6/util/JvppRequestTest.java | 41 + .../java/io/fd/hc2vpp/srv6/util/Srv6UtilTest.java | 64 + .../srv6/write/policy/PolicyCustomizerTest.java | 166 +++ .../steering/InterfacesConfigCustomizerTest.java | 117 ++ .../srv6/write/steering/PrefixCustomizerTest.java | 134 ++ .../steering/PrefixesConfigCustomizerTest.java | 103 ++ .../src/test/resources/named-segments.json | 74 + srv6/srv6-impl/src/test/resources/policy.json | 94 ++ srv6/srv6_policy_postman_collection.json | 282 ++++ 56 files changed, 6395 insertions(+), 10 deletions(-) create mode 100644 srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/MplsLabelBuilder.java create mode 100644 srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/SidValueTypeBuilder.java create mode 100755 srv6/srv6-api/src/main/yang/hc2vpp-oc-srte-policy@2017-09-18.yang create mode 100644 srv6/srv6-api/src/main/yang/policy-context@2018-06-07.yang create mode 100644 srv6/srv6-api/src/main/yang/vpp-oc-srte-policy@2018-05-14.yang create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PoliciesTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/SteeringTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/Srv6UtilTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizerTest.java create mode 100644 srv6/srv6-impl/src/test/resources/named-segments.json create mode 100644 srv6/srv6-impl/src/test/resources/policy.json create mode 100755 srv6/srv6_policy_postman_collection.json 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 index 000000000..1afeaea9b --- /dev/null +++ b/srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/MplsLabelBuilder.java @@ -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 index 000000000..4bcbf5dbf --- /dev/null +++ b/srv6/srv6-api/src/main/java/org/opendaylight/yang/gen/v1/http/cisco/com/ns/yang/oc/srte/policy/rev170918/SidValueTypeBuilder.java @@ -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"); + } + +} diff --git a/srv6/srv6-api/src/main/yang/hc2vpp-oc-srte-policy@2017-09-18.yang b/srv6/srv6-api/src/main/yang/hc2vpp-oc-srte-policy@2017-09-18.yang new file mode 100755 index 000000000..bdb8c8a63 --- /dev/null +++ b/srv6/srv6-api/src/main/yang/hc2vpp-oc-srte-policy@2017-09-18.yang @@ -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; + } + } +} diff --git a/srv6/srv6-api/src/main/yang/policy-context@2018-06-07.yang b/srv6/srv6-api/src/main/yang/policy-context@2018-06-07.yang new file mode 100644 index 000000000..2820d627f --- /dev/null +++ b/srv6/srv6-api/src/main/yang/policy-context@2018-06-07.yang @@ -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 + Mailing List "; + + 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; + } +} diff --git a/srv6/srv6-api/src/main/yang/vpp-oc-srte-policy@2018-05-14.yang b/srv6/srv6-api/src/main/yang/vpp-oc-srte-policy@2018-05-14.yang new file mode 100644 index 000000000..3aafe8a61 --- /dev/null +++ b/srv6/srv6-api/src/main/yang/vpp-oc-srte-policy@2018-05-14.yang @@ -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 + Mailing List "; + + 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; + } + } +} diff --git a/srv6/srv6-impl/asciidoc/Readme.adoc b/srv6/srv6-impl/asciidoc/Readme.adoc index 73b6f1b82..bf841a33e 100644 --- a/srv6/srv6-impl/asciidoc/Readme.adoc +++ b/srv6/srv6-impl/asciidoc/Readme.adoc @@ -11,6 +11,18 @@ - 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 hc2vpp-oc-srte@2017-09-18.yang + + 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 hc2vpp-oc-srte@2017-09-18.yang + + 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 + + hc2vpp-oc-srte@2017-09-18.yang model in vpp-oc-srte-policy@2018-05-14.yang model, defined in: + + `hc2vpp-oc-srte-policy:segment-routing/traffic-engineering/policies/policy/autoroute-include/vpp-oc-srte-policy:interfaces` + == VPP mapping @@ -29,7 +41,24 @@ *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: diff --git a/srv6/srv6-impl/pom.xml b/srv6/srv6-impl/pom.xml index 08fed218b..422cd161d 100644 --- a/srv6/srv6-impl/pom.xml +++ b/srv6/srv6-impl/pom.xml @@ -35,8 +35,7 @@ io.fd.hc2vpp.routing routing-impl - 1.18.07-SNAPSHOT - compile + ${project.version} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java index ec91b2133..3e51a4b01 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java @@ -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 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 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 index 000000000..19f62542e --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java @@ -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 SR = InstanceIdentifier.create(SegmentRouting.class); + public static final InstanceIdentifier SR_TE = SR.child(TrafficEngineering.class); + + //segment-routing/traffic-engineering/named-segment-lists + public static final InstanceIdentifier SR_TE_NSLS = SR_TE.child(NamedSegmentLists.class); + public static final InstanceIdentifier SR_TE_NSLS_NSL_IID = + SR_TE_NSLS.child(NamedSegmentList.class); + public static final InstanceIdentifier + 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 SR_TE_NSLS_NSL_SGS = SR_TE_NSLS_NSL_IID.child(Segments.class); + public static final InstanceIdentifier SR_TE_NSLS_NSL_SGS_SG = SR_TE_NSLS_NSL_SGS.child(Segment.class); + public static final InstanceIdentifier + 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 NSL = InstanceIdentifier.create(NamedSegmentList.class); + public static final InstanceIdentifier + 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 NSL_SGS = NSL.child(Segments.class); + public static final InstanceIdentifier NSL_SGS_SG = NSL_SGS.child(Segment.class); + public static final InstanceIdentifier + 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 SR_TE_PLS = SR_TE.child(Policies.class); + public static final InstanceIdentifier SR_TE_PLS_POL = SR_TE_PLS.child(Policy.class); + public static final InstanceIdentifier SR_TE_PLS_POL_BSID = SR_TE_PLS_POL.child(BindingSid.class); + public static final InstanceIdentifier + 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 SR_POLICY = InstanceIdentifier.create(Policy.class); + public static final InstanceIdentifier SR_POLICY_CFG = SR_POLICY.child(Config.class); + public static final InstanceIdentifier + 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 SR_TE_PLS_POL_AI = + SR_TE_PLS_POL.child(AutorouteInclude.class); + public static final InstanceIdentifier + 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 SR_TE_PLS_POL_AI_PFS = SR_TE_PLS_POL_AI.child(Prefixes.class); + public static final InstanceIdentifier + 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 + 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 + 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 + 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 + 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 + 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 SR_TE_PLS_POL_AI_IFAUG = + SR_TE_PLS_POL_AI.augmentation(VppL2AutorouteIncludeAugmentation.class); + public static final InstanceIdentifier SR_TE_PLS_POL_AI_IFCS = + SR_TE_PLS_POL_AI_IFAUG.child(Interfaces.class); + public static final InstanceIdentifier SR_TE_PLS_POL_AI_IFCS_IFC_IID = + SR_TE_PLS_POL_AI_IFCS.child(Interface.class); + public static final InstanceIdentifier SR_TE_PLS_POL_AI_IFCS_IFC = + InstanceIdentifier.create(Interface.class); + public static final InstanceIdentifier + 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 + 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 SR_POLICY_BSID = SR_POLICY.child(BindingSid.class); + public static final InstanceIdentifier + 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 + 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 SR_POLICY_VPP = + SR_POLICY.augmentation(VppSrPolicyAugmentation.class); + public static final InstanceIdentifier SR_POLICY_VPP_SR = + SR_POLICY_VPP.child(VppSrPolicy.class); + public static final InstanceIdentifier + 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 + 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 SR_POLICY_CPS = SR_POLICY.child(CandidatePaths.class); + public static final InstanceIdentifier SR_POLICY_CPS_CP = SR_POLICY_CPS.child(CandidatePath.class); + public static final InstanceIdentifier + 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 + 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 SR_POLICY_CPS_CP_SLS = + SR_POLICY_CPS_CP.child(SegmentLists.class); + public static final InstanceIdentifier SR_POLICY_CPS_CP_SLS_SL = + SR_POLICY_CPS_CP_SLS.child(SegmentList.class); + public static final InstanceIdentifier + 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 SR_POLICY_CPS_CP_BSID = SR_POLICY_CPS_CP.child(BindingSid.class); + public static final InstanceIdentifier + 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 + 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 index 000000000..79b18d235 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java @@ -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))); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java index 312280dce..41c33f98b 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java @@ -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 index 000000000..9f9c0e2ab --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java @@ -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 { + 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 getAllIds(@Nonnull final InstanceIdentifier 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 builder, + @Nonnull final List list) { + ((NamedSegmentListsBuilder) builder).setNamedSegmentList(list); + } + + @Nonnull + @Override + public NamedSegmentListBuilder getBuilder(@Nonnull final InstanceIdentifier instanceIdentifier) { + return new NamedSegmentListBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier 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 index 000000000..c4c323b52 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java @@ -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 { + + 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 getAllIds(@Nonnull InstanceIdentifier id, @Nonnull ReadContext context) + throws ReadFailedException { + PolicyReadRequest policyReadRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + return policyReadRequest.readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder builder, @Nonnull List readData) { + ((PoliciesBuilder) builder).setPolicy(readData); + } + + @Nonnull + @Override + public PolicyBuilder getBuilder(@Nonnull InstanceIdentifier id) { + return new PolicyBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier 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 index 000000000..8117d4d91 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java @@ -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 { + + 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 dumpManager; + + public PolicyReadRequest(FutureJVppCore futureJVpp, PolicyContextManager policyCtx, + final CandidatePathContextManager candidateCtx) { + super(futureJVpp); + this.policyCtx = policyCtx; + this.candidateCtx = candidateCtx; + this.dumpManager = new DumpCacheManager.DumpCacheManagerBuilder().acceptOnly( + SrPoliciesDetailsReplyDump.class) + .withExecutor((identifier, params) -> getReplyForRead( + getApi().srPoliciesDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier)) + .build(); + } + + @Nonnull + public List readAllKeys(@Nonnull InstanceIdentifier 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 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 resolveCandidatePaths(final SrPoliciesDetails srPoliciesDetails, + final ReadContext ctx) { + List 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 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 readNamedSegmentListKeys(final InstanceIdentifier 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 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 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 index 000000000..9151a9822 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java @@ -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 { + + private final NamingContext interfaceContext; + + public InterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore); + this.interfaceContext = interfaceContext; + } + + @Nonnull + @Override + public List getAllIds(@Nonnull InstanceIdentifier id, @Nonnull ReadContext context) + throws ReadFailedException { + return + new L2SteeringRequest(getFutureJVpp(), interfaceContext).readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder builder, @Nonnull List readData) { + ((InterfacesBuilder) builder).setInterface(readData); + } + + @Nonnull + @Override + public InterfaceBuilder getBuilder(@Nonnull InstanceIdentifier id) { + return new InterfaceBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier 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 index 000000000..b0ee7c3f8 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java @@ -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 { + + public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Nonnull + @Override + public List getAllIds(@Nonnull InstanceIdentifier id, @Nonnull ReadContext context) + throws ReadFailedException { + return + new L3SteeringRequest(getFutureJVpp()).readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder builder, @Nonnull List readData) { + ((PrefixesBuilder) builder).setPrefix(readData); + } + + @Nonnull + @Override + public PrefixBuilder getBuilder(@Nonnull InstanceIdentifier id) { + return new PrefixBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier 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 index 000000000..b099939eb --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java @@ -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 { + + public PrefixesStateCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Nonnull + @Override + public StateBuilder getBuilder(@Nonnull final InstanceIdentifier instanceIdentifier) { + return new StateBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final StateBuilder stateBuilder, @Nonnull final ReadContext readContext) + throws ReadFailedException { + L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp()); + List 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 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 index 000000000..eb9370787 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java @@ -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 { + + 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 readAllKeys(@Nonnull InstanceIdentifier 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 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 index 000000000..1043746e9 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java @@ -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 { + + 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 readAllKeys(@Nonnull InstanceIdentifier 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 readAllIpPrefixes(@Nonnull InstanceIdentifier 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 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 index 000000000..04b67f67e --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java @@ -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 dumpManager; + + SteeringRequest(final FutureJVppCore api) { + super(api); + this.dumpManager = + new DumpCacheManager.DumpCacheManagerBuilder().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 index 000000000..d0b6479be --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java @@ -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 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 index 000000000..15fb5c0ff --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java @@ -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 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 provisioningMethod, + @Nonnull Long preference, @Nonnull Long distinguisher, + @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier 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 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 read = ctx.read(ctxIid); + if (read.isPresent()) { + java.util.Optional 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 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 index 000000000..dd0f2615e --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java @@ -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 implements WriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(NoopCustomizer.class); + + public NoopCustomizer() { + super(); + } + + @Override + public void writeCurrentAttributes(@Nonnull InstanceIdentifier instanceIdentifier, @Nonnull T data, + @Nonnull WriteContext writeContext) { + LOG.trace("Noop write called for IId: {}, data: {}", instanceIdentifier, data); + } + + @Override + public void deleteCurrentAttributes(@Nonnull InstanceIdentifier 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 index 000000000..3a07fe024 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java @@ -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 index 000000000..1997043e2 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java @@ -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 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 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 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 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 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 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 index 000000000..ea308efcf --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java @@ -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 Ipv6Address extractBsid( + final @Nonnull InstanceIdentifier instanceIdentifier, final @Nonnull WriteContext writeContext, + boolean isWrite) { + Optional 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 int extractVrfFib(final @Nonnull InstanceIdentifier instanceIdentifier, + final @Nonnull WriteContext writeContext, boolean isWrite) { + Optional 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; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java index 551a211dd..5321bffcf 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java @@ -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 index 000000000..87e07d216 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java @@ -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))); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java index d9f022970..bb2619755 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java @@ -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 index 000000000..d8e09e84d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java @@ -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 { + + 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 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 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 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 candidatePaths, + final @Nonnull WriteContext writeContext) { + final PolicyDeleteRequest request = new PolicyDeleteRequest(getFutureJVpp()); + + Optional 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 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 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 readSegmentLists(final List segmentLists, final WriteContext writeContext) { + List sidLists = new ArrayList<>(); + + segmentLists.forEach(segmentList -> { + com.google.common.base.Optional 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 parseBestCandidate(final List 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 index 000000000..71b9d72e8 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java @@ -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 index 000000000..6dc3e867d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java @@ -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 segments; + + public PolicyWriteRequest(final FutureJVppCore api) { + super(api); + } + + private static Srv6Sid[] convertSegmentsToByteArray(final Segments segments) { + List 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 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 index 000000000..129c20e2d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java @@ -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 index 000000000..67ad9d56c --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java @@ -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 { + 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 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 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 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 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 index 000000000..7973c3203 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java @@ -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 { + + public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier 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 instanceIdentifier, + @Nonnull final Prefix prefix, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, prefix, writeContext, false).delete(instanceIdentifier); + } + + private L3SteeringRequest writePrefixes(final @Nonnull InstanceIdentifier 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 index 000000000..e366db3a3 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java @@ -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 { + + 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 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 instanceIdentifier, + @Nonnull final Config config, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, config, writeContext, true); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier 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 index 000000000..960d17bb9 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java @@ -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 index 000000000..850234c41 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java @@ -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 index 000000000..2078ade5b --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java @@ -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; + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/Srv6ModuleTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/Srv6ModuleTest.java index 54e4cdd26..068ea128a 100644 --- a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/Srv6ModuleTest.java +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/Srv6ModuleTest.java @@ -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 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 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 index 000000000..6cc2f555d --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizerTest.java @@ -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 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 + 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 index 000000000..d1abd15e8 --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PoliciesTest.java @@ -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 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 index 000000000..49c3942c5 --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizerTest.java @@ -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 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 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 index 000000000..bc5ad681f --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizerTest.java @@ -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 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 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 index 000000000..56850078f --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizerTest.java @@ -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 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 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 index 000000000..951f94d1d --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizerTest.java @@ -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 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 index 000000000..57f4fe806 --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/SteeringTest.java @@ -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); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/JvppRequestTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/JvppRequestTest.java index cd3369956..f241716d5 100644 --- a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/JvppRequestTest.java +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/JvppRequestTest.java @@ -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 index 000000000..89d97be31 --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/util/Srv6UtilTest.java @@ -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_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 index 000000000..80a3149e2 --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizerTest.java @@ -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 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 requestcaptorAdd; + @Captor + private ArgumentCaptor requestcaptorDel; + @Captor + private ArgumentCaptor 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 index 000000000..fa4787022 --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizerTest.java @@ -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 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 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 index 000000000..9335ab61c --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizerTest.java @@ -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_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 L3_STEER_V6_IID = PREFIXES_IID.child(Prefix.class, L3_STEER_KEY); + private InstanceIdentifier L3_STEER_V4_IID = PREFIXES_IID.child(Prefix.class, L3_STEER_KEY_2); + + @Captor + private ArgumentCaptor 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 index 000000000..64e0032e9 --- /dev/null +++ b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizerTest.java @@ -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 PREFIXES_CFG_IID = + Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY).child(AutorouteInclude.class).child(Prefixes.class) + .child(Config.class); + @Captor + private ArgumentCaptor 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 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 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 index 000000000..039db0b81 --- /dev/null +++ b/srv6/srv6-impl/src/test/resources/named-segments.json @@ -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 index 000000000..5c1e256f6 --- /dev/null +++ b/srv6/srv6-impl/src/test/resources/policy.json @@ -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 index 000000000..1d9ca4ebb --- /dev/null +++ b/srv6/srv6_policy_postman_collection.json @@ -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 -- cgit 1.2.3-korg