diff options
author | Michal Cmarada <michal.cmarada@pantheon.tech> | 2018-06-15 13:12:53 +0200 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2018-06-19 18:56:53 +0000 |
commit | b77a5725338dc700873b36c98af85d70acd7bbe4 (patch) | |
tree | 6006938757b2f3ac28eabc90eff821b3290f50af /srv6/srv6-impl | |
parent | a0884f2792c31a3a93fb1654ceea754b6c612920 (diff) |
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 <michal.cmarada@pantheon.tech>
Diffstat (limited to 'srv6/srv6-impl')
50 files changed, 4289 insertions, 10 deletions
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 @@ <dependency> <groupId>io.fd.hc2vpp.routing</groupId> <artifactId>routing-impl</artifactId> - <version>1.18.07-SNAPSHOT</version> - <scope>compile</scope> + <version>${project.version}</version> </dependency> <!-- Honeycomb infrastructure --> <dependency> 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<WriterFactory> writeBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); writeBinder.addBinding().to(Srv6WriterFactory.class); + LOG.info("Injecting SRv6 Policy writers"); + writeBinder.addBinding().to(Srv6PolicyWriterFactory.class); LOG.info("Injecting SRv6 readers"); final Multibinder<ReaderFactory> readerBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class); readerBinder.addBinding().to(Srv6ReaderFactory.class); + LOG.info("Injecting SRv6 Policy readers"); + readerBinder.addBinding().to(Srv6PolicyReaderFactory.class); LOG.info("SRv6 module successfully configured"); } diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java new file mode 100644 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<SegmentRouting> SR = InstanceIdentifier.create(SegmentRouting.class); + public static final InstanceIdentifier<TrafficEngineering> SR_TE = SR.child(TrafficEngineering.class); + + //segment-routing/traffic-engineering/named-segment-lists + public static final InstanceIdentifier<NamedSegmentLists> SR_TE_NSLS = SR_TE.child(NamedSegmentLists.class); + public static final InstanceIdentifier<NamedSegmentList> SR_TE_NSLS_NSL_IID = + SR_TE_NSLS.child(NamedSegmentList.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.Config> + SR_TE_NSLS_NSL_CFG = SR_TE_NSLS_NSL_IID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.Config.class); + public static final InstanceIdentifier<Segments> SR_TE_NSLS_NSL_SGS = SR_TE_NSLS_NSL_IID.child(Segments.class); + public static final InstanceIdentifier<Segment> SR_TE_NSLS_NSL_SGS_SG = SR_TE_NSLS_NSL_SGS.child(Segment.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.Config> + SR_TE_NSLS_NSL_SGS_SG_CFG = SR_TE_NSLS_NSL_SGS_SG + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.Config.class); + public static final InstanceIdentifier<NamedSegmentList> NSL = InstanceIdentifier.create(NamedSegmentList.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.State> + NSL_STATE = NSL + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.State.class); + public static final InstanceIdentifier<Segments> NSL_SGS = NSL.child(Segments.class); + public static final InstanceIdentifier<Segment> NSL_SGS_SG = NSL_SGS.child(Segment.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.State> + NSL_SGS_SG_STATE = NSL_SGS_SG + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.State.class); + + // policies + public static final InstanceIdentifier<Policies> SR_TE_PLS = SR_TE.child(Policies.class); + public static final InstanceIdentifier<Policy> SR_TE_PLS_POL = SR_TE_PLS.child(Policy.class); + public static final InstanceIdentifier<BindingSid> SR_TE_PLS_POL_BSID = SR_TE_PLS_POL.child(BindingSid.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config> + SR_TE_PLS_POL_BSID_CFG = SR_TE_PLS_POL_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config.class); + + // policy + public static final InstanceIdentifier<Policy> SR_POLICY = InstanceIdentifier.create(Policy.class); + public static final InstanceIdentifier<Config> SR_POLICY_CFG = SR_POLICY.child(Config.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.State> + SR_POLICY_STATE = SR_POLICY + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.State.class); + + // policies/policy/autoroute-include + public static final InstanceIdentifier<AutorouteInclude> SR_TE_PLS_POL_AI = + SR_TE_PLS_POL.child(AutorouteInclude.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.autoroute.include.Config> + SR_TE_PLS_POL_AI_CFG = SR_TE_PLS_POL_AI + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.autoroute.include.Config.class); + + // policies/policy/autoroute-include/prefixes + public static final InstanceIdentifier<Prefixes> SR_TE_PLS_POL_AI_PFS = SR_TE_PLS_POL_AI.child(Prefixes.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config> + SR_TE_PLS_POL_AI_PFS_CFG = SR_TE_PLS_POL_AI_PFS + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State> + SR_TE_PLS_POL_AI_PFS_STATE = SR_TE_PLS_POL_AI_PFS + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix> + SR_TE_PLS_POL_AI_PFS_PF_IID = SR_TE_PLS_POL_AI_PFS + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix> + SR_TE_PLS_POL_AI_PFS_PF = InstanceIdentifier + .create(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.Config> + SR_TE_PLS_POL_AI_PFS_PF_CFG = SR_TE_PLS_POL_AI_PFS_PF + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.Config.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.State> + SR_TE_PLS_POL_AI_PFS_PF_STATE = SR_TE_PLS_POL_AI_PFS_PF + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.State.class); + + // policies/policy/autoroute-include/interfaces + public static final InstanceIdentifier<VppL2AutorouteIncludeAugmentation> SR_TE_PLS_POL_AI_IFAUG = + SR_TE_PLS_POL_AI.augmentation(VppL2AutorouteIncludeAugmentation.class); + public static final InstanceIdentifier<Interfaces> SR_TE_PLS_POL_AI_IFCS = + SR_TE_PLS_POL_AI_IFAUG.child(Interfaces.class); + public static final InstanceIdentifier<Interface> SR_TE_PLS_POL_AI_IFCS_IFC_IID = + SR_TE_PLS_POL_AI_IFCS.child(Interface.class); + public static final InstanceIdentifier<Interface> SR_TE_PLS_POL_AI_IFCS_IFC = + InstanceIdentifier.create(Interface.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config> + SR_TE_PLS_POL_AI_IFCS_IFC_CFG = SR_TE_PLS_POL_AI_IFCS_IFC + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.State> + SR_TE_PLS_POL_AI_IFCS_IFC_STATE = SR_TE_PLS_POL_AI_IFCS_IFC + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.State.class); + + // policy/binding-sid + public static final InstanceIdentifier<BindingSid> SR_POLICY_BSID = SR_POLICY.child(BindingSid.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State> + SR_POLICY_BSID_STATE = SR_POLICY_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State> + SR_POLICY_BSID_CFG = SR_POLICY_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class); + + // policy/vpp-sr-policy + public static final InstanceIdentifier<VppSrPolicyAugmentation> SR_POLICY_VPP = + SR_POLICY.augmentation(VppSrPolicyAugmentation.class); + public static final InstanceIdentifier<VppSrPolicy> SR_POLICY_VPP_SR = + SR_POLICY_VPP.child(VppSrPolicy.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config> + SR_POLICY_VPP_SR_CFG = SR_POLICY_VPP_SR + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.State> + SR_POLICY_VPP_SR_STATE = SR_POLICY_VPP_SR + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.State.class); + + // policy/candidate-paths + public static final InstanceIdentifier<CandidatePaths> SR_POLICY_CPS = SR_POLICY.child(CandidatePaths.class); + public static final InstanceIdentifier<CandidatePath> SR_POLICY_CPS_CP = SR_POLICY_CPS.child(CandidatePath.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.Config> + SR_POLICY_CPS_CP_CFG = SR_POLICY_CPS_CP + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.Config.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.State> + SR_POLICY_CPS_CP_STATE = SR_POLICY_CPS_CP + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.State.class); + + public static final InstanceIdentifier<SegmentLists> SR_POLICY_CPS_CP_SLS = + SR_POLICY_CPS_CP.child(SegmentLists.class); + public static final InstanceIdentifier<SegmentList> SR_POLICY_CPS_CP_SLS_SL = + SR_POLICY_CPS_CP_SLS.child(SegmentList.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.Config> + SR_POLICY_CPS_CP_SLS_SL_CFG = SR_POLICY_CPS_CP_SLS_SL + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.Config.class); + public static final InstanceIdentifier<BindingSid> SR_POLICY_CPS_CP_BSID = SR_POLICY_CPS_CP.child(BindingSid.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config> + SR_POLICY_CPS_CP_BSID_CFG = SR_POLICY_CPS_CP_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config.class); + public static final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State> + SR_POLICY_CPS_CP_BSID_STATE = SR_POLICY_CPS_CP_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class); +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java new file mode 100644 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<NamedSegmentList, NamedSegmentListKey, NamedSegmentListBuilder> { + private final PolicyContextManager policyContext; + private final CandidatePathContextManager candidateContext; + + public NamedSegmentCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + final PolicyContextManager policyContext, + final CandidatePathContextManager candidateContext) { + super(futureJVppCore); + this.policyContext = policyContext; + this.candidateContext = candidateContext; + } + + @Nonnull + @Override + public List<NamedSegmentListKey> getAllIds(@Nonnull final InstanceIdentifier<NamedSegmentList> instanceIdentifier, + @Nonnull final ReadContext readContext) throws ReadFailedException { + PolicyReadRequest + policyReadRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + policyReadRequest.checkValid(); + return policyReadRequest.readNamedSegmentListKeys(instanceIdentifier, readContext); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> builder, + @Nonnull final List<NamedSegmentList> list) { + ((NamedSegmentListsBuilder) builder).setNamedSegmentList(list); + } + + @Nonnull + @Override + public NamedSegmentListBuilder getBuilder(@Nonnull final InstanceIdentifier<NamedSegmentList> instanceIdentifier) { + return new NamedSegmentListBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<NamedSegmentList> instanceIdentifier, + @Nonnull final NamedSegmentListBuilder builder, + @Nonnull final ReadContext readContext) throws ReadFailedException { + PolicyReadRequest readRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + readRequest.readNamedSegmentList(instanceIdentifier, builder, readContext); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java new file mode 100644 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<Policy, PolicyKey, PolicyBuilder> { + + private final PolicyContextManager policyContext; + private final CandidatePathContextManager candidateContext; + + public PolicyCustomizer(@Nonnull final FutureJVppCore futureJVppCore, PolicyContextManager policyContext, + final CandidatePathContextManager candidateContext) { + super(futureJVppCore); + this.policyContext = policyContext; + this.candidateContext = candidateContext; + } + + @Nonnull + @Override + public List<PolicyKey> getAllIds(@Nonnull InstanceIdentifier<Policy> id, @Nonnull ReadContext context) + throws ReadFailedException { + PolicyReadRequest policyReadRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + return policyReadRequest.readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Policy> readData) { + ((PoliciesBuilder) builder).setPolicy(readData); + } + + @Nonnull + @Override + public PolicyBuilder getBuilder(@Nonnull InstanceIdentifier<Policy> id) { + return new PolicyBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier<Policy> id, @Nonnull PolicyBuilder builder, + @Nonnull ReadContext ctx) throws ReadFailedException { + PolicyReadRequest readRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + readRequest.readSpecific(id, ctx, builder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java new file mode 100644 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<Policy, PolicyKey, PolicyBuilder> { + + private static final String DASH_SEPARATOR = "-"; + private static final Logger LOG = LoggerFactory.getLogger(PolicyReadRequest.class); + private static final SrPoliciesDump STATIC_DUMP_REQUEST = new SrPoliciesDump(); + private static final SrPoliciesDetailsReplyDump STATIC_EMPTY_REPLY = new SrPoliciesDetailsReplyDump(); + private final PolicyContextManager policyCtx; + private final CandidatePathContextManager candidateCtx; + private final DumpCacheManager<SrPoliciesDetailsReplyDump, Void> dumpManager; + + public PolicyReadRequest(FutureJVppCore futureJVpp, PolicyContextManager policyCtx, + final CandidatePathContextManager candidateCtx) { + super(futureJVpp); + this.policyCtx = policyCtx; + this.candidateCtx = candidateCtx; + this.dumpManager = new DumpCacheManager.DumpCacheManagerBuilder<SrPoliciesDetailsReplyDump, Void>().acceptOnly( + SrPoliciesDetailsReplyDump.class) + .withExecutor((identifier, params) -> getReplyForRead( + getApi().srPoliciesDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier)) + .build(); + } + + @Nonnull + public List<PolicyKey> readAllKeys(@Nonnull InstanceIdentifier<Policy> id, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .map(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr)) + .map(bsid -> parsePolicyKey(ctx, bsid)) + .collect(Collectors.toList()); + } + + private PolicyKey parsePolicyKey(final @Nonnull ReadContext ctx, final Ipv6Address bsid) { + Srv6PolicyMapping policy = policyCtx.getPolicy(bsid, ctx.getMappingContext()); + return new PolicyKey(policy.getColor(), new IpAddress(policy.getEndpoint())); + } + + @Override + public void readSpecific(@Nonnull InstanceIdentifier<Policy> id, @Nonnull ReadContext ctx, + @Nonnull PolicyBuilder builder) throws ReadFailedException { + PolicyKey key = id.firstKeyOf(Policy.class); + Ipv6Address bsid = + policyCtx.getPolicyBsid(key.getColor(), key.getEndpoint().getIpv6Address(), ctx.getMappingContext()); + + dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .filter(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue() + .equals(bsid.getValue())) + .findFirst() + .ifPresent((SrPoliciesDetails details) -> bindPolicy(details, ctx, builder)); + } + + private void bindPolicy(SrPoliciesDetails srPoliciesDetails, @Nonnull ReadContext ctx, + final PolicyBuilder builder) { + + Ipv6Address bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr); + Srv6PolicyMapping policy = policyCtx.getPolicy(bsid, ctx.getMappingContext()); + IpAddress endpoint = new IpAddress(policy.getEndpoint()); + builder.setName(policy.getName()).setEndpoint(endpoint).setColor(policy.getColor()); + builder.setKey(new PolicyKey(policy.getColor(), endpoint)); + builder.setBindingSid(new BindingSidBuilder().setState( + new StateBuilder().setType(DataplaneType.Srv6).setAllocMode(BindingSidAllocMode.Explicit) + .setValue(new SidValueType(new IpAddress(bsid))).build()).build()); + builder.addAugmentation(VppSrPolicyAugmentation.class, new VppSrPolicyAugmentationBuilder() + .setVppSrPolicy(new VppSrPolicyBuilder().setState( + new org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.StateBuilder() + .setPolicyBehavior( + SegmentRoutingPolicyBehavior.forValue((int) srPoliciesDetails.isEncap)) + .setPolicyType(SegmentRoutingPolicyType.forValue((int) srPoliciesDetails.type)) + .setTableId(new VniReference(Integer.toUnsignedLong(srPoliciesDetails.fibTable))) + .setAddressFamily(Ipv6.class) + .build()).build()) + .build()); + + builder.setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.StateBuilder() + .setName(policy.getName()).setEndpoint(endpoint) + .setColor(policy.getColor()).setAdminState(PolicyAdminState.UP) + .build()); + + builder.setCandidatePaths( + new CandidatePathsBuilder().setCandidatePath(resolveCandidatePaths(srPoliciesDetails, ctx)).build()); + } + + private List<CandidatePath> resolveCandidatePaths(final SrPoliciesDetails srPoliciesDetails, + final ReadContext ctx) { + List<CandidatePath> candidatePaths = new ArrayList<>(); + //only one candidate path can be selected and present on device at the same time + if (srPoliciesDetails.sidLists == null) { + LOG.debug("No policy segments found for BSID: {}", srPoliciesDetails.bsid); + return candidatePaths; + } + Ipv6Address bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr); + Srv6CandidatePathMapping candidatePath = + candidateCtx.getCandidatePath(bsid, ctx.getMappingContext()); + + CandidatePathBuilder candidatePathBuilder = + new CandidatePathBuilder() + .setDistinguisher(candidatePath.getDistinguisher()) + .setPreference(candidatePath.getPreference()) + .setProvisioningMethod(candidatePath.getProvisioningMethod()) + .setName(candidatePath.getName()); + + candidatePathBuilder.setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.StateBuilder() + .setDistinguisher(candidatePath.getDistinguisher()) + .setPreference(candidatePath.getPreference()) + .setProvisioningMethod(candidatePath.getProvisioningMethod()) + .setComputationMethod(PathExplicitlyDefined.class) + .setName(candidatePath.getName()) + .build()); + candidatePathBuilder.setBindingSid(new BindingSidBuilder().setState( + new StateBuilder().setAllocMode(BindingSidAllocMode.Explicit).setType(DataplaneType.Srv6) + .setValue(new SidValueType(new IpAddress(bsid))).build()).build()); + + List<SegmentList> segments = new ArrayList<>(); + for (Srv6SidList sidlist : srPoliciesDetails.sidLists) { + long weight = Integer.toUnsignedLong(sidlist.weight); + SegmentListBuilder segmentListBuilder = + new SegmentListBuilder().setName(Srv6Util.getCandidatePathName(bsid, weight)); + segmentListBuilder.setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.StateBuilder() + .setName(Srv6Util.getCandidatePathName(bsid, weight)) + .setWeight(weight) + .setOperState(SegmentListOperState.ACTIVE) + .build()); + segments.add(segmentListBuilder.build()); + } + candidatePathBuilder.setSegmentLists(new SegmentListsBuilder().setSegmentList(segments).build()); + candidatePaths.add(candidatePathBuilder.build()); + return candidatePaths; + } + + public List<NamedSegmentListKey> readNamedSegmentListKeys(final InstanceIdentifier<NamedSegmentList> id, + final ReadContext ctx) throws ReadFailedException { + return dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .map(srPoliciesDetails -> { + String bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue(); + return Arrays.stream(srPoliciesDetails.sidLists).map(srv6SidList -> srv6SidList.weight) + .map(weight -> bsid + DASH_SEPARATOR + weight).collect(Collectors.toList()); + }).flatMap(Collection::stream).map(NamedSegmentListKey::new).distinct().collect(Collectors.toList()); + } + + public void readNamedSegmentList(final InstanceIdentifier<NamedSegmentList> id, + final NamedSegmentListBuilder builder, + final ReadContext ctx) + throws ReadFailedException { + NamedSegmentListKey key = id.firstKeyOf(NamedSegmentList.class); + builder.setKey(key) + .setName(key.getName()) + .setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.StateBuilder() + .setName(key.getName()) + .build()); + + Long weight = parseWeight(key); + String bsid = parseBsid(key); + Preconditions.checkNotNull(bsid, "Weight/Bsid not resolved for Iid: {}", id); + + builder.setSegments(new SegmentsBuilder().build()); + dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .filter(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue() + .equals(bsid)) + .forEach(srPoliciesDetails -> Arrays.stream(srPoliciesDetails.sidLists) + .forEach(srv6SidList -> { + if (srv6SidList.weight == weight.intValue()) { + List<Segment> segments = IntStream.range(0, srv6SidList.numSids) + .mapToObj(i -> parseSrv6Sid(i, srv6SidList.sids[i])) + .collect(Collectors.toList()); + builder.setSegments(new SegmentsBuilder().setSegment(segments).build()); + } + })); + } + + private Segment parseSrv6Sid(final int i, final Srv6Sid srv6Sid) { + // shifting index by 1 so it matches original indexing + long index = i + 1; + SegmentBuilder builder = new SegmentBuilder().setKey(new SegmentKey(index)).setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.StateBuilder() + .setIndex(index) + .setType(SegmentType.Type2) + .setSidValue(new SidValueType( + new IpAddress(new Ipv6Address(arrayToIpv6AddressNoZone(srv6Sid.addr))))) + .build()); + return builder.build(); + } + + + private Long parseWeight(final NamedSegmentListKey key) { + String[] values = key.getName().split(DASH_SEPARATOR); + + return values.length == 2 + ? Long.parseLong(values[1]) + : 0; + } + + private String parseBsid(final NamedSegmentListKey key) { + String[] values = key.getName().split(DASH_SEPARATOR); + return values.length == 2 ? values[0] : null; + } + +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java new file mode 100644 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<Interface, InterfaceKey, InterfaceBuilder> { + + private final NamingContext interfaceContext; + + public InterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore); + this.interfaceContext = interfaceContext; + } + + @Nonnull + @Override + public List<InterfaceKey> getAllIds(@Nonnull InstanceIdentifier<Interface> id, @Nonnull ReadContext context) + throws ReadFailedException { + return + new L2SteeringRequest(getFutureJVpp(), interfaceContext).readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Interface> readData) { + ((InterfacesBuilder) builder).setInterface(readData); + } + + @Nonnull + @Override + public InterfaceBuilder getBuilder(@Nonnull InstanceIdentifier<Interface> id) { + return new InterfaceBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier<Interface> id, @Nonnull InterfaceBuilder builder, + @Nonnull ReadContext ctx) throws ReadFailedException { + L2SteeringRequest readRequest = new L2SteeringRequest(getFutureJVpp(), interfaceContext); + readRequest.readSpecific(id, ctx, builder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java new file mode 100644 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<Prefix, PrefixKey, PrefixBuilder> { + + public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Nonnull + @Override + public List<PrefixKey> getAllIds(@Nonnull InstanceIdentifier<Prefix> id, @Nonnull ReadContext context) + throws ReadFailedException { + return + new L3SteeringRequest(getFutureJVpp()).readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Prefix> readData) { + ((PrefixesBuilder) builder).setPrefix(readData); + } + + @Nonnull + @Override + public PrefixBuilder getBuilder(@Nonnull InstanceIdentifier<Prefix> id) { + return new PrefixBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier<Prefix> id, @Nonnull PrefixBuilder builder, + @Nonnull ReadContext ctx) throws ReadFailedException { + L3SteeringRequest readRequest = new L3SteeringRequest(getFutureJVpp()); + readRequest.readSpecific(id, ctx, builder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java new file mode 100644 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<State, StateBuilder> { + + public PrefixesStateCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Nonnull + @Override + public StateBuilder getBuilder(@Nonnull final InstanceIdentifier<State> instanceIdentifier) { + return new StateBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<State> instanceIdentifier, + @Nonnull final StateBuilder stateBuilder, @Nonnull final ReadContext readContext) + throws ReadFailedException { + L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp()); + List<IpPrefix> ipPrefixes = + request.readAllIpPrefixes(RWUtils.cutId(instanceIdentifier, Prefixes.class), readContext); + // checks whether L3 steering contains default routes to steer all traffic to SRv6 policy. If found sets + // allPrefixes flag to true in autoroute-include/prefixes/state + boolean allPrefixes = ipPrefixes.containsAll( + ImmutableSet.of(new IpPrefix(new Ipv4Prefix("0.0.0.0/0")), new IpPrefix(new Ipv6Prefix("::/0")))); + + stateBuilder.setPrefixesAll(allPrefixes); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final State state) { + ((PrefixesBuilder) builder).setState(state); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java new file mode 100644 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<Interface, InterfaceKey, InterfaceBuilder> { + + static final int L2_TRAFFIC_TYPE = 2; + private final NamingContext ifcNamingContext; + + public L2SteeringRequest(FutureJVppCore api, NamingContext namingContext) { + super(api); + this.ifcNamingContext = namingContext; + } + + @Override + @Nonnull + public List<InterfaceKey> readAllKeys(@Nonnull InstanceIdentifier<Interface> identifier, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter(srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) == L2_TRAFFIC_TYPE) + .map(srSteeringPolDetails -> srSteeringPolDetails.swIfIndex) + .map(ifIndex -> new InterfaceKey(ifcNamingContext.getName(ifIndex, ctx.getMappingContext()))) + .collect(Collectors.toList()); + } + + @Override + public void readSpecific(@Nonnull InstanceIdentifier<Interface> identifier, @Nonnull ReadContext ctx, + @Nonnull InterfaceBuilder builder) throws ReadFailedException { + int index = + ifcNamingContext.getIndex(identifier.firstKeyOf(Interface.class).getInputInterface(), + ctx.getMappingContext()); + + dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter(srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) == L2_TRAFFIC_TYPE) + .filter(srSteeringPolDetails -> srSteeringPolDetails.swIfIndex == index) + .findFirst() + .ifPresent(srSteeringPolDetails -> parseL2Steering(srSteeringPolDetails, builder, ctx)); + } + + private void parseL2Steering(SrSteeringPolDetails srSteeringPolDetails, final InterfaceBuilder builder, + ReadContext ctx) { + String name = ifcNamingContext.getName(srSteeringPolDetails.swIfIndex, ctx.getMappingContext()); + builder.setInputInterface(name).setKey(new InterfaceKey(name)) + .setState(new StateBuilder().setInputInterface(name).build()); + } +} + diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java new file mode 100644 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<Prefix, PrefixKey, PrefixBuilder> { + + private static final int L3_TRAFFIC_TYPE_IPV6 = 6; + private static final int L3_TRAFFIC_TYPE_IPV4 = 4; + + public L3SteeringRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + super.checkValid(); + } + + @Override + @Nonnull + public List<PrefixKey> readAllKeys(@Nonnull InstanceIdentifier<Prefix> identifier, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter( + srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) != + L2SteeringRequest.L2_TRAFFIC_TYPE) + .map(this::parseL3SteeringKey) + .collect(Collectors.toList()); + } + + public List<IpPrefix> readAllIpPrefixes(@Nonnull InstanceIdentifier<Prefixes> identifier, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter( + srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) != + L2SteeringRequest.L2_TRAFFIC_TYPE) + .map(this::parseIpPrefix) + .collect(Collectors.toList()); + } + + @Override + public void readSpecific(@Nonnull InstanceIdentifier<Prefix> identifier, @Nonnull ReadContext ctx, + @Nonnull PrefixBuilder builder) throws ReadFailedException { + checkValid(); + PrefixKey key = identifier.firstKeyOf(Prefix.class); + dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter( + srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) != + L2SteeringRequest.L2_TRAFFIC_TYPE) + .filter(srSteeringPolDetails -> parseL3SteeringKey(srSteeringPolDetails).equals(key)) + .findFirst() + .ifPresent(srSteeringPolDetails1 -> parseL3Steering(srSteeringPolDetails1, builder)); + } + + private void parseL3Steering(SrSteeringPolDetails srSteeringPolDetails, final PrefixBuilder builder) { + PrefixKey key = parseL3SteeringKey(srSteeringPolDetails); + builder.setKey(key).setIpPrefix(key.getIpPrefix()) + .setState(new StateBuilder().setIpPrefix(key.getIpPrefix()).build()); + } + + private PrefixKey parseL3SteeringKey(SrSteeringPolDetails policyDetails) { + return new PrefixKey(parseIpPrefix(policyDetails)); + } + + private IpPrefix parseIpPrefix(final SrSteeringPolDetails policyDetails) { + boolean isIpv6 = isIpv6L3TrafficType(policyDetails.trafficType); + IpPrefix ipPrefix; + if (isIpv6) { + Ipv6Prefix ipv6Prefix = toIpv6Prefix(policyDetails.prefixAddr, policyDetails.maskWidth); + ipPrefix = new IpPrefix(ipv6Prefix); + } else { + Ipv4Prefix ipv4Prefix = toIpv4Prefix(policyDetails.prefixAddr, policyDetails.maskWidth); + ipPrefix = new IpPrefix(ipv4Prefix); + } + return ipPrefix; + } + + private boolean isIpv6L3TrafficType(final byte trafficType) { + Preconditions.checkArgument(trafficType == L3_TRAFFIC_TYPE_IPV4 || trafficType == L3_TRAFFIC_TYPE_IPV6, + "Unsupported traffic type for L3 steering"); + + return trafficType == L3_TRAFFIC_TYPE_IPV6; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java new file mode 100644 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<SrSteeringPolDetailsReplyDump, Void> dumpManager; + + SteeringRequest(final FutureJVppCore api) { + super(api); + this.dumpManager = + new DumpCacheManager.DumpCacheManagerBuilder<SrSteeringPolDetailsReplyDump, Void>().acceptOnly( + SrSteeringPolDetailsReplyDump.class) + .withExecutor((identifier, params) -> getReplyForRead( + getApi().srSteeringPolDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier)) + .build(); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java new file mode 100644 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<? extends ProvisioningMethodType> provisioningMethod, + @Nonnull Long preference, @Nonnull Long distinguisher, @Nonnull final MappingContext ctx); + + /** + * Retrieves candidate path for given name. If not present it will generate artificial mapping + * + * @param bsid candidate path BSID + * @param ctx mapping context providing context data for current transaction + * @return candidate path matching supplied candidate path BSID if present, artificial mapping otherwise + */ + @Nonnull + Srv6CandidatePathMapping getCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx); + + /** + * Removes candidate path metadata from current context. + * + * @param bsid candidate path BSID + * @param ctx mapping context providing context data for current transaction + */ + void removeCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx); + +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java new file mode 100644 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<Srv6CandidatePathMappings> ctxIid; + + public CandidatePathContextManagerImpl() { + this.ctxIid = InstanceIdentifier.create(Contexts.class) + .augmentation(Srv6PolicyContextAugmentation.class) + .child(Srv6CandidatePathMappings.class); + distinguisher = new AtomicLong(0L); + } + + @Override + public void addCandidatePath(@Nonnull Ipv6Address bsid, @Nonnull final String name, + @Nonnull final Class<? extends ProvisioningMethodType> provisioningMethod, + @Nonnull Long preference, @Nonnull Long distinguisher, + @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier<Srv6CandidatePathMapping, Srv6CandidatePathMappingKey> mappingIid = + getCandidatePathIid(bsid); + final Srv6CandidatePathMappingBuilder builder = + new Srv6CandidatePathMappingBuilder().setKey(new Srv6CandidatePathMappingKey(bsid)) + .setProvisioningMethod(provisioningMethod).setPreference(preference) + .setDistinguisher(distinguisher).setBsid(bsid).setName(name); + ctx.put(mappingIid, builder.build()); + } + + private KeyedInstanceIdentifier<Srv6CandidatePathMapping, Srv6CandidatePathMappingKey> getCandidatePathIid( + final Ipv6Address bsid) { + return ctxIid.child(Srv6CandidatePathMapping.class, new Srv6CandidatePathMappingKey(bsid)); + } + + @Override + @Nonnull + public synchronized Srv6CandidatePathMapping getCandidatePath(@Nonnull final Ipv6Address bsid, + @Nonnull final MappingContext ctx) { + final Optional<Srv6CandidatePathMappings> read = ctx.read(ctxIid); + if (read.isPresent()) { + java.util.Optional<Srv6CandidatePathMapping> mappingOpt = read.get().getSrv6CandidatePathMapping().stream() + .filter(srv6CandidatePathMapping -> srv6CandidatePathMapping.getBsid().getValue() + .equals(bsid.getValue())).findAny(); + if (mappingOpt.isPresent()) { + return mappingOpt.get(); + } + } + return getArtificialMapping(bsid, ctx, bsid.getValue()); + } + + private Srv6CandidatePathMapping getArtificialMapping(final @Nonnull Ipv6Address bsid, + final @Nonnull MappingContext ctx, final String name) { + // if not present we need to generate artificial mapping + // for given policy only one candidate path can be selected and be configured on the device. + Srv6CandidatePathMapping mapping = + new Srv6CandidatePathMappingBuilder() + .setProvisioningMethod(ProvisioningMethodConfig.class) + .setBsid(bsid) //when we read name from VPP it is always the BSID value + .setPreference(DEFAULT_PREFERENCE) + .setDistinguisher(distinguisher.incrementAndGet()) + .build(); + addCandidatePath(mapping.getBsid(), name, mapping.getProvisioningMethod(), mapping.getPreference(), + mapping.getDistinguisher(), ctx); + return mapping; + } + + @Override + public void removeCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier<Srv6CandidatePathMapping, Srv6CandidatePathMappingKey> mappingIid = + getCandidatePathIid(bsid); + ctx.delete(mappingIid); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java new file mode 100644 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<T extends DataObject> implements WriterCustomizer<T> { + + private static final Logger LOG = LoggerFactory.getLogger(NoopCustomizer.class); + + public NoopCustomizer() { + super(); + } + + @Override + public void writeCurrentAttributes(@Nonnull InstanceIdentifier<T> instanceIdentifier, @Nonnull T data, + @Nonnull WriteContext writeContext) { + LOG.trace("Noop write called for IId: {}, data: {}", instanceIdentifier, data); + } + + @Override + public void deleteCurrentAttributes(@Nonnull InstanceIdentifier<T> instanceIdentifier, @Nonnull T data, + @Nonnull WriteContext writeContext) { + LOG.trace("Noop delete called for IId: {}, data: {}", instanceIdentifier, data); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java new file mode 100644 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<Srv6PolicyMappings> ctxIid; + // 2001:db8::/32 This address range is used for documentation and example source code. We can use it as dummy + // addresses for our artificial policies + private static final String DUMMY_EP = "2001:db8::"; + private Long artificialColor; + + public PolicyContextManagerImpl() { + this.ctxIid = InstanceIdentifier.create(Contexts.class) + .augmentation(Srv6PolicyContextAugmentation.class) + .child(Srv6PolicyMappings.class); + this.artificialColor = 0L; + } + + @Override + public void addPolicy(@Nonnull final String name, @Nonnull final Long color, @Nonnull final Ipv6Address endpoint, + @Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier<Srv6PolicyMapping, Srv6PolicyMappingKey> mappingIid = getPolicyIid(bsid); + final Srv6PolicyMappingBuilder builder = + new Srv6PolicyMappingBuilder().setKey(new Srv6PolicyMappingKey(bsid)).setColor(color) + .setEndpoint(endpoint).setBsid(bsid).setName(name); + ctx.put(mappingIid, builder.build()); + } + + private KeyedInstanceIdentifier<Srv6PolicyMapping, Srv6PolicyMappingKey> getPolicyIid(final Ipv6Address bsid) { + return ctxIid.child(Srv6PolicyMapping.class, new Srv6PolicyMappingKey(bsid)); + } + + @Nonnull + public synchronized Srv6PolicyMapping getPolicy(@Nonnull final Ipv6Address bsid, + @Nonnull final MappingContext ctx) { + final Optional<Srv6PolicyMapping> read = ctx.read(getPolicyIid(bsid)); + if (read.isPresent()) { + return read.get(); + } + + //if not present we need to generate artificial mapping + Long nextArtificialColor = getNextArtificialColor(); + Ipv6Address endpoint = new Ipv6Address(DUMMY_EP + nextArtificialColor); + Srv6PolicyMapping mapping = + new Srv6PolicyMappingBuilder().setBsid(bsid).setColor(nextArtificialColor).setEndpoint(endpoint) + .setName(bsid.getValue()).build(); + addPolicy(mapping.getName(), mapping.getColor(), mapping.getEndpoint(), mapping.getBsid(), ctx); + return mapping; + } + + @Override + public Ipv6Address getPolicyBsid(@Nonnull Long color, @Nonnull Ipv6Address endpoint, + @Nonnull final MappingContext ctx) { + Optional<Srv6PolicyMappings> read = ctx.read(ctxIid); + if (read.isPresent()) { + return read.get().getSrv6PolicyMapping().stream() + .filter(srv6PolicyMapping -> srv6PolicyMapping.getColor().equals(color) && + srv6PolicyMapping.getEndpoint().equals(endpoint)) + .map(Srv6PolicyMapping::getBsid).findFirst().orElse(null); + } + return null; + } + + @Override + public void removePolicy(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier<Srv6PolicyMapping, Srv6PolicyMappingKey> mappingIid = getPolicyIid(bsid); + ctx.delete(mappingIid); + } + + private synchronized Long getNextArtificialColor() { + artificialColor++; + return artificialColor; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java new file mode 100644 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 <T extends DataObject> Ipv6Address extractBsid( + final @Nonnull InstanceIdentifier<T> instanceIdentifier, final @Nonnull WriteContext writeContext, + boolean isWrite) { + Optional<Policy> policyOptional = isWrite + ? writeContext.readAfter(RWUtils.cutId(instanceIdentifier, Policy.class)) + : writeContext.readBefore(RWUtils.cutId(instanceIdentifier, Policy.class)); + + if (policyOptional.isPresent() && policyOptional.get().getBindingSid() != null && + policyOptional.get().getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + config = policyOptional.get().getBindingSid().getConfig(); + if (config.getType() == DataplaneType.Srv6 && config.getValue() != null && + config.getValue().getIpAddress() != null && + config.getValue().getIpAddress().getIpv6Address() != null) { + return config.getValue().getIpAddress().getIpv6Address(); + } + } + return null; + } + + /** + * Extracts VRF FIB from Policy. + * + * @param instanceIdentifier identifier used to extract path of policy + * @param writeContext used to store any useful information later utilized by customizers + * @param isWrite condition whether this is a write or delete operation + * @return VRF FIB id when resolved, default VRF FIB (0) otherwise + */ + public static <T extends DataObject> int extractVrfFib(final @Nonnull InstanceIdentifier<T> instanceIdentifier, + final @Nonnull WriteContext writeContext, boolean isWrite) { + Optional<Policy> policyOptional = isWrite + ? writeContext.readAfter(RWUtils.cutId(instanceIdentifier, Policy.class)) + : writeContext.readBefore(RWUtils.cutId(instanceIdentifier, Policy.class)); + + if (policyOptional.isPresent() && policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class) != null && + policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class).getVppSrPolicy() != null) { + + VppSrPolicy vppSrPolicy = + policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class).getVppSrPolicy(); + if (vppSrPolicy.getConfig() != null && vppSrPolicy.getConfig().getTableId() != null) { + return vppSrPolicy.getConfig().getTableId().getValue().intValue(); + } + } + // returning default Vrf Fib table + return 0; + } +} 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<Policy, PolicyKey> { + + private final PolicyContextManager policyContext; + private final CandidatePathContextManager candidateContext; + + public PolicyCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final PolicyContextManager policyContext, + @Nonnull final CandidatePathContextManager candidateContext) { + super(futureJVppCore); + this.policyContext = policyContext; + this.candidateContext = candidateContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> instanceIdentifier, + @Nonnull final Policy policy, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + try { + // Fib table must be created beforehand. First we check if all data is present, then we verify the existence + // of FIB table in current configuration + VppSrPolicyAugmentation policyAugmentation = policy.getAugmentation(VppSrPolicyAugmentation.class); + + if (policyAugmentation != null && policyAugmentation.getVppSrPolicy() != null && + policyAugmentation.getVppSrPolicy().getConfig() != null) { + Config config = policyAugmentation.getVppSrPolicy().getConfig(); + TableKey tableKey = new TableKey(config.getAddressFamily(), new VniReference(config.getTableId())); + KeyedInstanceIdentifier<Table, TableKey> vrfIid = + FibManagementIIds.FM_FIB_TABLES.child(Table.class, tableKey); + if (!writeContext.readAfter(vrfIid).isPresent()) { + throw new IllegalArgumentException( + String.format("VRF table: %s not found. Create table before writing policy.", tableKey)); + } + if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) { + bindWriteRequest(config, policy.getCandidatePaths().getCandidatePath(), writeContext) + .write(instanceIdentifier); + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, true); + policyContext.addPolicy(policy.getName(), policy.getColor(), policy.getEndpoint().getIpv6Address(), + bsid, writeContext.getMappingContext()); + } + } else { + throw new ReadFailedException(instanceIdentifier, + new Throwable("VppSrPolicyAugmentation and/or VppSrPolicy missing.")); + } + } catch (ReadFailedException e) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, policy, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> instanceIdentifier, + @Nonnull final Policy policy, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) { + bindDeleteRequest(policy.getCandidatePaths().getCandidatePath(), writeContext).delete(instanceIdentifier); + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, false); + Preconditions.checkNotNull(bsid, "BSID must not be null"); + policyContext.removePolicy(bsid, writeContext.getMappingContext()); + } + } + + private PolicyDeleteRequest bindDeleteRequest(final @Nonnull List<CandidatePath> candidatePaths, + final @Nonnull WriteContext writeContext) { + final PolicyDeleteRequest request = new PolicyDeleteRequest(getFutureJVpp()); + + Optional<CandidatePath> candidatePathOptional = parseBestCandidate(candidatePaths); + Preconditions.checkArgument(candidatePathOptional.isPresent(), + "Could not parse best Candidate path from list: {}", candidatePaths); + + CandidatePath selectedPath = candidatePathOptional.get(); + if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + sidConfig = selectedPath.getBindingSid().getConfig(); + + if (sidConfig.getType() == DataplaneType.Srv6 && + sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null && + sidConfig.getValue().getIpAddress() != null && + sidConfig.getValue().getIpAddress().getIpv6Address() != null) { + Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address(); + request.setBindingSidAddress(bsid); + candidateContext.removeCandidatePath(bsid, writeContext.getMappingContext()); + } + } + return request; + } + + private PolicyWriteRequest bindWriteRequest(@Nonnull final Config config, + final List<CandidatePath> candidatePaths, + final WriteContext writeContext) { + final PolicyWriteRequest request = new PolicyWriteRequest(getFutureJVpp()); + request.setFibTableIndex(config.getTableId().getValue().intValue()); + request.setPolicyBehavior(config.getPolicyBehavior()); + request.setPolicyType(config.getPolicyType()); + + Optional<CandidatePath> candidatePathOptional = parseBestCandidate(candidatePaths); + Preconditions.checkArgument(candidatePathOptional.isPresent(), + "Could not parse best Candidate path from list: {}", candidatePaths); + + CandidatePath selectedPath = candidatePathOptional.get(); + if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + sidConfig = selectedPath.getBindingSid().getConfig(); + + if (sidConfig.getType() == DataplaneType.Srv6 && + sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null && + sidConfig.getValue().getIpAddress() != null && + sidConfig.getValue().getIpAddress().getIpv6Address() != null) { + Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address(); + request.setBindingSidAddress(bsid); + candidateContext.addCandidatePath(bsid, selectedPath.getName(), selectedPath.getProvisioningMethod(), + selectedPath.getPreference(), selectedPath.getDistinguisher(), + writeContext.getMappingContext()); + } + } + if (selectedPath.getSegmentLists() != null && selectedPath.getSegmentLists().getSegmentList() != null) { + request.setSegments(readSegmentLists(selectedPath.getSegmentLists().getSegmentList(), writeContext)); + } + + return request; + } + + private List<SidList> readSegmentLists(final List<SegmentList> segmentLists, final WriteContext writeContext) { + List<SidList> sidLists = new ArrayList<>(); + + segmentLists.forEach(segmentList -> { + com.google.common.base.Optional<NamedSegmentList> namedSegmentListOptional = writeContext.readAfter( + Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, + new NamedSegmentListKey(segmentList.getName()))); + + if (namedSegmentListOptional.isPresent()) { + sidLists.add(SidList.builder() + .setNamedSegmentList(namedSegmentListOptional.get()) + .setWeight(segmentList.getConfig().getWeight()) + .build()); + } + }); + return sidLists; + } + + /** + * Selects best Candidate based on Preference value (the higher preference the better), + * only static configuration is supported for now (provisioning-method must be equal to provisioning-method-config). + * + * Based on Segment Routing Policy for Traffic Engineering + * https://tools.ietf.org/html/draft-filsfils-spring-segment-routing-policy-00 + * + * @param candidatePaths List of available CandidatePaths + * @return Optional of CandidatePath + */ + private Optional<CandidatePath> parseBestCandidate(final List<CandidatePath> candidatePaths) { + return candidatePaths.stream() + .filter(candidatePath -> candidatePath.getProvisioningMethod().equals(ProvisioningMethodConfig.class)) + .max(Comparator.comparingLong(CandidatePath::getPreference)); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java new file mode 100644 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<SidList> segments; + + public PolicyWriteRequest(final FutureJVppCore api) { + super(api); + } + + private static Srv6Sid[] convertSegmentsToByteArray(final Segments segments) { + List<Srv6Sid> sidList = new ArrayList<>(); + segments.getSegment().stream().sorted(Comparator.comparingLong(Segment::getIndex)) + .map(segment -> segment.getConfig().getSidValue().getIpAddress().getIpv6Address()) + .forEach(ipv6Address -> { + Srv6Sid sid = new Srv6Sid(); + sid.addr = AddressTranslator.INSTANCE.ipv6AddressNoZoneToArray(ipv6Address); + sidList.add(sid); + }); + return sidList.toArray(new Srv6Sid[0]); + } + + @Override + public void write(final InstanceIdentifier<?> identifier) throws WriteFailedException { + checkValid(); + + final SrPolicyAdd createRequest = new SrPolicyAdd(); + createRequest.bsidAddr = ipv6AddressNoZoneToArray(bindingSidAddress); + createRequest.isEncap = (byte) policyBehavior.getIntValue(); + createRequest.type = (byte) policyType.getIntValue(); + createRequest.fibTable = fibTableIndex; + + SidList firstSidList = segments.get(0); + + createRequest.sids = new Srv6SidList(); + createRequest.sids.numSids = (byte) firstSidList.getNamedSegmentList().getSegments().getSegment().size(); + createRequest.sids.sids = convertSegmentsToByteArray(firstSidList.getNamedSegmentList().getSegments()); + createRequest.sids.weight = firstSidList.getWeight().intValue(); + + LOG.info("Writing policy {}", createRequest); + getReplyForWrite(getApi().srPolicyAdd(createRequest).toCompletableFuture(), identifier); + + if (segments.size() > 1) { + LOG.info("Multiple segments detected for policy, modifying"); + segments.stream() + .skip(1) + .map(policySegments -> { + SrPolicyMod modifyRequest = new SrPolicyMod(); + modifyRequest.bsidAddr = createRequest.bsidAddr; + modifyRequest.operation = ADD_NEW;// add new segment list + modifyRequest.fibTable = fibTableIndex; + modifyRequest.sids = new Srv6SidList(); + modifyRequest.sids.numSids = + (byte) policySegments.getNamedSegmentList().getSegments().getSegment().size(); + modifyRequest.sids.sids = + convertSegmentsToByteArray(policySegments.getNamedSegmentList().getSegments()); + modifyRequest.sids.weight = policySegments.getWeight().intValue(); + return modifyRequest; + }) + .peek(modifyRequest -> LOG.info("Adding additional segment list for policy {} / request {}", + bindingSidAddress.getValue(), modifyRequest)) + .forEach(modifyRequest -> { + try { + getReplyForWrite(getApi().srPolicyMod(modifyRequest).toCompletableFuture(), identifier); + } catch (WriteFailedException e) { + throw new IllegalStateException(e); + } + }); + } + } + + @Override + public void checkValid() { + checkNotNull(bindingSidAddress, "Binding sid address not set"); + checkNotNull(policyBehavior, "Policy behavior not set"); + checkNotNull(policyType, "Policy type not set"); + if (policyBehavior != SegmentRoutingPolicyBehavior.Encapsulation) { + checkNotNull(segments, "Segments not set"); + checkState(!segments.isEmpty(), "No segments set"); + } + } + + public void setBindingSidAddress( + final Ipv6Address bindingSidAddress) { + this.bindingSidAddress = bindingSidAddress; + } + + public void setPolicyBehavior( + final SegmentRoutingPolicyBehavior policyBehavior) { + this.policyBehavior = policyBehavior; + } + + public void setPolicyType( + final SegmentRoutingPolicyType policyType) { + this.policyType = policyType; + } + + public void setFibTableIndex(final int fibTableIndex) { + this.fibTableIndex = fibTableIndex; + } + + public void setSegments(final List<SidList> segments) { + this.segments = segments; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java new file mode 100644 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<Interface, InterfaceKey> { + private final NamingContext interfaceContext; + + public InterfacesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore); + this.interfaceContext = interfaceContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> instanceIdentifier, + @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (anInterface.getConfig() != null) { + writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, true); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> instanceIdentifier, + @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (anInterface.getConfig() != null) { + writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, false); + } + } + + private void writeInterfaces(final @Nonnull InstanceIdentifier<Interface> instanceIdentifier, + final @Nonnull Config config, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, config, + new Throwable("Failed to extract BSID from policy for prefix")); + } + if (config.getInputInterface() != null) { + // forward all traffic to policy for current interface + int index = interfaceContext.getIndex(config.getInputInterface(), writeContext.getMappingContext()); + sendL2Steering(instanceIdentifier, bsid, index, getFutureJVpp(), isWrite); + } + } + + private void sendL2Steering(final InstanceIdentifier<Interface> instanceIdentifier, final Ipv6Address bsid, + final int inputInterface, final FutureJVppCore api, final boolean isWrite) + throws WriteFailedException { + L2SteeringRequest request = new L2SteeringRequest(api); + request.setBindingSid(bsid); + request.setInputInterfaceIndex(inputInterface); + if (isWrite) { + request.write(instanceIdentifier); + } else { + request.delete(instanceIdentifier); + } + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java new file mode 100644 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<Prefix, PrefixKey> { + + public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> instanceIdentifier, + @Nonnull final Prefix prefix, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, prefix, writeContext, true).write(instanceIdentifier); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> instanceIdentifier, + @Nonnull final Prefix prefix, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, prefix, writeContext, false).delete(instanceIdentifier); + } + + private L3SteeringRequest writePrefixes(final @Nonnull InstanceIdentifier<Prefix> instanceIdentifier, + final @Nonnull Prefix prefix, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, prefix, + new Throwable("Failed to extract BSID from policy for prefix")); + } + // forward only desired traffic to policy + L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp()); + request.setBindingSid(bsid); + request.setPrefix(prefix.getIpPrefix()); + request.setFibTableIndex(vrfFib); + return request; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java new file mode 100644 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<Config> { + + private static final IpPrefix + DEFAULT_IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("::/0")); + private static final IpPrefix + DEFAULT_IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("0.0.0.0/0")); + + public PrefixesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + private void writePrefixes(final @Nonnull InstanceIdentifier<Config> instanceIdentifier, + final @Nonnull Config config, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, config, + new Throwable("Failed to extract BSID from policy for prefix")); + } + if (config.isPrefixesAll()) { + // forward all traffic to policy + writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV6_PREFIX, bsid, getFutureJVpp(), isWrite); + writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV4_PREFIX, bsid, getFutureJVpp(), isWrite); + } + } + + private void writeL3Steering(int vrfFib, InstanceIdentifier instanceIdentifier, IpPrefix ipPrefix, + final Ipv6Address bsid, FutureJVppCore api, boolean isWrite) + throws WriteFailedException { + L3SteeringRequest request = new L3SteeringRequest(api); + request.setBindingSid(bsid); + request.setPrefix(ipPrefix); + request.setFibTableIndex(vrfFib); + if (isWrite) { + request.write(instanceIdentifier); + } else { + request.delete(instanceIdentifier); + } + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Config> instanceIdentifier, + @Nonnull final Config config, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, config, writeContext, true); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Config> instanceIdentifier, + @Nonnull final Config config, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, config, writeContext, false); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java new file mode 100644 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<ReaderFactory> readerFactoryIterator = readerFactories.iterator(); + assertTrue(readerFactoryIterator.next() instanceof Srv6ReaderFactory); + assertTrue(readerFactoryIterator.next() instanceof Srv6PolicyReaderFactory); } @Test @@ -112,7 +117,9 @@ public class Srv6ModuleTest { final FlatWriterRegistryBuilder registryBuilder = new FlatWriterRegistryBuilder(new YangDAG()); writerFactories.forEach(factory -> factory.init(registryBuilder)); assertNotNull(registryBuilder.build()); - assertEquals(1, writerFactories.size()); - assertTrue(writerFactories.iterator().next() instanceof Srv6WriterFactory); + assertEquals(2, writerFactories.size()); + Iterator<WriterFactory> writerFactoryIterator = writerFactories.iterator(); + assertTrue(writerFactoryIterator.next() instanceof Srv6WriterFactory); + assertTrue(writerFactoryIterator.next() instanceof Srv6PolicyWriterFactory); } } diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizerTest.java new file mode 100644 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<NamedSegmentListKey> segmentListKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_NSLS_NSL_IID, readCtx); + + Assert.assertNotNull(segmentListKeys); + Assert.assertFalse(segmentListKeys.isEmpty()); + Assert.assertEquals(replyDump.srPoliciesDetails.size(), segmentListKeys.size()); + Assert.assertTrue(segmentListKeys.containsAll(ImmutableSet.of(SEGMENT_KEY_1, SEGMENT_KEY_2))); + } + + @Test + public void readCurrentAttributesTest() throws ReadFailedException { + NamedSegmentCustomizer customizer = new NamedSegmentCustomizer(api, policyCtx, candidatePathCtx); + NamedSegmentListBuilder segmentListBuilder = new NamedSegmentListBuilder(); + KeyedInstanceIdentifier<NamedSegmentList, NamedSegmentListKey> + key = Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, SEGMENT_KEY_1); + customizer.readCurrentAttributes(key, segmentListBuilder, readCtx); + + Assert.assertEquals(SEGMENT_KEY_1, segmentListBuilder.getKey()); + Assert.assertEquals(SEGMENT_KEY_1.getName(), segmentListBuilder.getName()); + Assert.assertNotNull(customizer.getBuilder(key)); + + //verify State container + Assert.assertNotNull(segmentListBuilder.getState()); + Assert.assertEquals(SEGMENT_KEY_1.getName(), segmentListBuilder.getState().getName()); + + //verify State container + Assert.assertNotNull(segmentListBuilder.getSegments()); + Assert.assertNotNull(segmentListBuilder.getSegments().getSegment()); + Assert.assertEquals(3, segmentListBuilder.getSegments().getSegment().size()); + + Assert.assertEquals(B_ADDR.getValue(), + segmentListBuilder.getSegments().getSegment().get(0).getState().getSidValue().getIpAddress() + .getIpv6Address().getValue()); + Assert.assertEquals(C_ADDR.getValue(), + segmentListBuilder.getSegments().getSegment().get(1).getState().getSidValue().getIpAddress() + .getIpv6Address().getValue()); + Assert.assertEquals(A_ADDR.getValue(), + segmentListBuilder.getSegments().getSegment().get(2).getState().getSidValue().getIpAddress() + .getIpv6Address().getValue()); + + //verify different path + key = Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, SEGMENT_KEY_2); + customizer.readCurrentAttributes(key, segmentListBuilder, readCtx); + Assert.assertEquals(SEGMENT_KEY_2.getName(), segmentListBuilder.getState().getName()); + Assert.assertEquals(3, segmentListBuilder.getSegments().getSegment().size()); + + Assert.assertEquals(A_ADDR.getValue(), + segmentListBuilder.getSegments().getSegment().get(0).getState().getSidValue().getIpAddress() + .getIpv6Address().getValue()); + Assert.assertEquals(C_ADDR.getValue(), + segmentListBuilder.getSegments().getSegment().get(1).getState().getSidValue().getIpAddress() + .getIpv6Address().getValue()); + Assert.assertEquals(B_ADDR.getValue(), + segmentListBuilder.getSegments().getSegment().get(2).getState().getSidValue().getIpAddress() + .getIpv6Address().getValue()); + + //verify merge + NamedSegmentList segmentList = segmentListBuilder.build(); + NamedSegmentListsBuilder parentBuilder = new NamedSegmentListsBuilder(); + customizer.merge(parentBuilder, segmentList); + Assert.assertEquals(segmentList, parentBuilder.getNamedSegmentList().get(0)); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PoliciesTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PoliciesTest.java new file mode 100644 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<? extends ProvisioningMethodType> PROVISIONING_METHOD = ProvisioningMethodConfig.class; + int WEIGHT = 0; + SrPoliciesDetailsReplyDump replyDump = new SrPoliciesDetailsReplyDump(); + + @Mock + ReadContext readCtx; + @Mock + PolicyContextManager policyCtx; + @Mock + CandidatePathContextManager candidatePathCtx; + Ipv6AddressNoZone A_ADDR = new Ipv6AddressNoZone("a::"); + Ipv6AddressNoZone B_ADDR = new Ipv6AddressNoZone("b::"); + Ipv6AddressNoZone C_ADDR = new Ipv6AddressNoZone("c::"); + + @Mock + private + ModificationCache modificationCache; + private Srv6Sid A = new Srv6Sid(); + private Srv6Sid B = new Srv6Sid(); + private Srv6Sid C = new Srv6Sid(); + private SrPoliciesDetails srPoliciesDetails1 = new SrPoliciesDetails(); + private SrPoliciesDetails srPoliciesDetails2 = new SrPoliciesDetails(); + + @Override + public void init() { + Srv6Sid bsid = new Srv6Sid(); + bsid.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)); + srPoliciesDetails1.bsid = bsid; + + srPoliciesDetails1.numSidLists = 1; + Srv6SidList[] srv6SidLists = new Srv6SidList[1]; + Srv6SidList srv6SidList = new Srv6SidList(); + srv6SidList.weight = WEIGHT; + srv6SidList.numSids = 3; + A.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(A_ADDR)); + B.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(B_ADDR)); + C.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(C_ADDR)); + + srv6SidList.sids = ImmutableSet.of(B, C, A).toArray(new Srv6Sid[3]); + + srv6SidLists[0] = srv6SidList; + srPoliciesDetails1.sidLists = srv6SidLists; + // is_encap - behavior of SR policy.(0.SRH insert // 1.Encapsulation) + srPoliciesDetails1.isEncap = ByteDataTranslator.BYTE_TRUE; + // type is the type of the SR policy. (0.Default // 1.Spray) + srPoliciesDetails1.type = 0; + + Srv6Sid bsid2 = new Srv6Sid(); + bsid2.addr = AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_2_ADR)); + srPoliciesDetails2.bsid = bsid2; + srPoliciesDetails2.numSidLists = 1; + Srv6SidList[] srv6SidLists2 = new Srv6SidList[1]; + Srv6SidList srv6SidList2 = new Srv6SidList(); + srv6SidList2.weight = WEIGHT; + srv6SidList2.numSids = 3; + + srv6SidList2.sids = ImmutableSet.of(A, C, B).toArray(new Srv6Sid[3]); + srv6SidLists2[0] = srv6SidList2; + srPoliciesDetails2.sidLists = srv6SidLists2; + srPoliciesDetails2.isEncap = ByteDataTranslator.BYTE_TRUE; + srPoliciesDetails2.type = 0; + + replyDump.srPoliciesDetails = Arrays.asList(srPoliciesDetails1, srPoliciesDetails2); + + when(readCtx.getModificationCache()).thenReturn(modificationCache); + when(readCtx.getMappingContext()).thenReturn(mappingContext); + when(modificationCache.get(any())).thenReturn(replyDump); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizerTest.java new file mode 100644 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<PolicyKey> policyKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_PLS_POL, readCtx); + + Assert.assertNotNull(policyKeys); + Assert.assertFalse(policyKeys.isEmpty()); + Assert.assertEquals(replyDump.srPoliciesDetails.size(), policyKeys.size()); + Assert.assertTrue(policyKeys.containsAll(ImmutableSet.of(POLICY_KEY, POLICY_KEY_2))); + } + + @Test + public void readCurrentAttributesTest() throws ReadFailedException { + PolicyCustomizer customizer = new PolicyCustomizer(api, policyCtx, candidatePathCtx); + PolicyBuilder policyBuilder = new PolicyBuilder(); + KeyedInstanceIdentifier<Policy, PolicyKey> key = Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY); + customizer.readCurrentAttributes(key, policyBuilder, readCtx); + + Assert.assertEquals(POLICY_KEY, policyBuilder.getKey()); + Assert.assertEquals(BSID_ADR.getValue(), policyBuilder.getName()); + Assert.assertNotNull(customizer.getBuilder(key)); + + //verify BSID container + Assert.assertNotNull(policyBuilder.getBindingSid()); + Assert.assertNotNull(policyBuilder.getBindingSid().getState()); + Assert.assertEquals(DataplaneType.Srv6, policyBuilder.getBindingSid().getState().getType()); + Assert.assertEquals(BSID_ADR, + policyBuilder.getBindingSid().getState().getValue().getIpAddress().getIpv6Address()); + + //verify state container + Assert.assertNotNull(policyBuilder.getState()); + Assert.assertEquals(COLOR_1, policyBuilder.getState().getColor()); + Assert.assertEquals(ENDPOINT_1, policyBuilder.getState().getEndpoint()); + Assert.assertEquals(BSID_ADR.getValue(), policyBuilder.getState().getName()); + + //verify candidate-paths container + Assert.assertNotNull(policyBuilder.getCandidatePaths()); + Assert.assertNotNull(policyBuilder.getCandidatePaths().getCandidatePath()); + Assert.assertEquals(1, policyBuilder.getCandidatePaths().getCandidatePath().size()); + CandidatePath candidatePath = policyBuilder.getCandidatePaths().getCandidatePath().get(0); + Assert.assertEquals(DISTINGUISHER_1, candidatePath.getDistinguisher().longValue()); + Assert.assertEquals(PREFERENCE_1, candidatePath.getPreference().longValue()); + Assert.assertEquals(ProvisioningMethodConfig.class, candidatePath.getProvisioningMethod()); + + //verify candidate-paths/state container + Assert.assertNotNull(candidatePath.getState()); + Assert.assertEquals(DISTINGUISHER_1, candidatePath.getState().getDistinguisher().longValue()); + Assert.assertEquals(PREFERENCE_1, candidatePath.getState().getPreference().longValue()); + Assert.assertEquals(ProvisioningMethodConfig.class, candidatePath.getState().getProvisioningMethod()); + Assert.assertEquals(PathExplicitlyDefined.class, candidatePath.getState().getComputationMethod()); + Assert.assertNotNull(candidatePath.getBindingSid()); + Assert.assertNotNull(candidatePath.getBindingSid().getState()); + Assert.assertEquals(BSID_ADR.getValue(), + candidatePath.getBindingSid().getState().getValue().getIpAddress().getIpv6Address().getValue()); + + //verify candidate-paths/segment-lists container + Assert.assertNotNull(candidatePath.getSegmentLists()); + Assert.assertNotNull(candidatePath.getSegmentLists().getSegmentList()); + Assert.assertEquals(1, candidatePath.getSegmentLists().getSegmentList().size()); + SegmentList segmentList = candidatePath.getSegmentLists().getSegmentList().get(0); + Assert.assertEquals(Srv6Util.getCandidatePathName(BSID_ADR, WEIGHT), segmentList.getName()); + Assert.assertNotNull(segmentList.getState()); + Assert.assertEquals(WEIGHT, segmentList.getState().getWeight().intValue()); + Assert.assertEquals(SegmentListOperState.ACTIVE, segmentList.getState().getOperState()); + + //verify merge + PoliciesBuilder policiesBuilder = new PoliciesBuilder(); + Policy policy = policyBuilder.build(); + customizer.merge(policiesBuilder, policy); + Assert.assertEquals(policy, policiesBuilder.getPolicy().get(0)); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizerTest.java new file mode 100644 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<Interface> key = + Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, new PolicyKey(0L, new IpAddress(new Ipv6Address("e::1")))) + .child(AutorouteInclude.class) + .augmentation(VppL2AutorouteIncludeAugmentation.class).child(Interfaces.class) + .child(Interface.class, L2_KEY); + + InterfaceCustomizer customizer = new InterfaceCustomizer(api, interfaceContext); + InterfaceBuilder builder = customizer.getBuilder(key); + customizer.readCurrentAttributes(key, builder, readCtx); + + Assert.assertEquals(L2_KEY, builder.getKey()); + Assert.assertEquals(LOCAL_0, builder.getInputInterface()); + + InterfacesBuilder policyBuilder = new InterfacesBuilder(); + customizer.merge(policyBuilder, builder.build()); + + Assert.assertNotNull(policyBuilder.getInterface()); + Assert.assertEquals(1, policyBuilder.getInterface().size()); + } + + @Test + public void getAllIdsTest() throws ReadFailedException { + InterfaceCustomizer customizer = new InterfaceCustomizer(api, interfaceContext); + List<InterfaceKey> l2SteeringKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC, readCtx); + + Assert.assertNotNull(l2SteeringKeys); + Assert.assertFalse(l2SteeringKeys.isEmpty()); + Assert.assertEquals(1, l2SteeringKeys.size()); + Assert.assertTrue(l2SteeringKeys.containsAll(ImmutableSet.of(L2_KEY))); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizerTest.java new file mode 100644 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<Prefix, PrefixKey> key = + Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, new PolicyKey(0L, new IpAddress(new Ipv6Address("e::1")))) + .child(AutorouteInclude.class).child(Prefixes.class).child(Prefix.class, L3_KEY); + + PrefixCustomizer customizer = new PrefixCustomizer(api); + PrefixBuilder builder = customizer.getBuilder(key); + + customizer.readCurrentAttributes(key, builder, readCtx); + + Assert.assertEquals(L3_KEY, builder.getKey()); + Assert.assertEquals(IPV6_PREFIX, builder.getIpPrefix()); + + PrefixesBuilder policyBuilder = new PrefixesBuilder(); + customizer.merge(policyBuilder, builder.build()); + + Assert.assertNotNull(policyBuilder.getPrefix()); + Assert.assertEquals(1, policyBuilder.getPrefix().size()); + } + + @Test + public void getAllIdsTest() throws ReadFailedException { + PrefixCustomizer customizer = new PrefixCustomizer(api); + List<PrefixKey> l3SteeringKeys = customizer.getAllIds(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_IID, readCtx); + + Assert.assertNotNull(l3SteeringKeys); + Assert.assertFalse(l3SteeringKeys.isEmpty()); + Assert.assertEquals(2, l3SteeringKeys.size()); + Assert.assertTrue(l3SteeringKeys.containsAll(ImmutableSet.of(L3_KEY, L3_KEY_2))); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizerTest.java new file mode 100644 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<State> iId = + Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, new PolicyKey(0L, new IpAddress(new Ipv6Address("e::1")))) + .child(AutorouteInclude.class).child(Prefixes.class).child(State.class); + + PrefixesStateCustomizer customizer = new PrefixesStateCustomizer(api); + StateBuilder builder = customizer.getBuilder(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_STATE); + + customizer.readCurrentAttributes(iId, builder, readCtx); + Assert.assertEquals(false, builder.isPrefixesAll()); + + PrefixesBuilder parentBuilder = new PrefixesBuilder(); + customizer.merge(parentBuilder, builder.build()); + + Assert.assertNotNull(parentBuilder.getState()); + Assert.assertEquals(false, parentBuilder.getState().isPrefixesAll()); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/SteeringTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/read/steering/SteeringTest.java new file mode 100644 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> 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<Table, TableKey> VRF_IID = + FibManagementIIds.FM_FIB_TABLES.child(Table.class, new TableKey(Ipv6.class, TABLE_ID)); + private static final Table VRF_TABLE = new TableBuilder().setKey(VRF_IID.getKey()).setAddressFamily(Ipv6.class) + .setTableId(TABLE_ID).setName("VRF-0").build(); + + @InjectTestData(resourcePath = "/named-segments.json", id = NAMED_SEG_LISTS_PATH) + private NamedSegmentLists namedSegmentLists; + @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH) + private Policies policies; + + @Mock + private PolicyContextManager policyCtx; + @Mock + private CandidatePathContextManager candidatePathCtx; + + @Captor + private ArgumentCaptor<SrPolicyAdd> requestcaptorAdd; + @Captor + private ArgumentCaptor<SrPolicyDel> requestcaptorDel; + @Captor + private ArgumentCaptor<SrPolicyMod> requestcaptorMod; + + @Override + protected void init() { + when(api.srPolicyAdd(any())).thenReturn(future(new SrPolicyAddReply())); + when(api.srPolicyDel(any())).thenReturn(future(new SrPolicyDelReply())); + when(api.srPolicyMod(any())).thenReturn(future(new SrPolicyModReply())); + when(ctx.readAfter( + Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, new NamedSegmentListKey(PATH_NAME)))) + .thenReturn(Optional.of(namedSegmentLists.getNamedSegmentList().get(0))); + when(ctx.readAfter( + Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, new NamedSegmentListKey(PATH_NAME_2)))) + .thenReturn(Optional.of(namedSegmentLists.getNamedSegmentList().get(1))); + when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + when(ctx.readAfter(VRF_IID)).thenReturn(Optional.of(VRF_TABLE)); + } + + @Test + public void writeCurrentAttributesTest() throws WriteFailedException { + PolicyCustomizer customizer = new PolicyCustomizer(api, policyCtx, candidatePathCtx); + customizer.writeCurrentAttributes(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY), + policies.getPolicy().get(0), ctx); + + verify(api, times(1)).srPolicyAdd(requestcaptorAdd.capture()); + SrPolicyAdd srPolicy = requestcaptorAdd.getValue(); + + verify(api, times(1)).srPolicyMod(requestcaptorMod.capture()); + SrPolicyMod srPolicyMod = requestcaptorMod.getValue(); + + Assert.assertEquals(0L, srPolicy.fibTable); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)), + srPolicy.bsidAddr); + Assert.assertEquals(ByteDataTranslator.BYTE_TRUE, srPolicy.isEncap); + Assert.assertEquals(0, srPolicy.type); + Assert.assertNotNull(srPolicy.sids); + Assert.assertEquals(3, srPolicy.sids.numSids); + Assert.assertEquals(0, srPolicy.sids.weight); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(B_ADDR)), + srPolicy.sids.sids[0].addr); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(C_ADDR)), + srPolicy.sids.sids[1].addr); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(A_ADDR)), + srPolicy.sids.sids[2].addr); + + Assert.assertEquals(0L, srPolicyMod.fibTable); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)), + srPolicyMod.bsidAddr); + Assert.assertNotNull(srPolicy.sids); + Assert.assertEquals(3, srPolicyMod.sids.numSids); + Assert.assertEquals(1, srPolicyMod.sids.weight); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(C_ADDR)), + srPolicyMod.sids.sids[0].addr); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(B_ADDR)), + srPolicyMod.sids.sids[1].addr); + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(A_ADDR)), + srPolicyMod.sids.sids[2].addr); + } + + @Test + public void deleteCurrentAttributesTest() throws WriteFailedException { + PolicyCustomizer customizer = new PolicyCustomizer(api, policyCtx, candidatePathCtx); + customizer.deleteCurrentAttributes(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY), + policies.getPolicy().get(0), ctx); + + verify(api, times(1)).srPolicyDel(requestcaptorDel.capture()); + SrPolicyDel srPolicy = requestcaptorDel.getValue(); + + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)), + srPolicy.bsidAddr.addr); + } + +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizerTest.java new file mode 100644 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<Interface> L2_STEER_IID = + Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY) + .child(AutorouteInclude.class) + .augmentation(VppL2AutorouteIncludeAugmentation.class).child(Interfaces.class) + .child(Interface.class, L2_KEY); + + private NamingContext interfaceContext; + + @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH) + private Policies policies; + + @Captor + private ArgumentCaptor<SrSteeringAddDel> requestcaptor; + + @Override + protected void init() { + when(api.srSteeringAddDel(any())).thenReturn(future(new SrSteeringAddDelReply())); + defineMapping(mappingContext, LOCAL_0, 1, "interface-context"); + defineMapping(mappingContext, "vlan0", 2, "interface-context"); + when(ctx.getMappingContext()).thenReturn(mappingContext); + interfaceContext = new NamingContext("iface", "interface-context"); + when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + } + + @Test + public void writeCurrentAttributesTest() throws WriteFailedException { + InterfacesConfigCustomizer customizer = new InterfacesConfigCustomizer(api, interfaceContext); + customizer.writeCurrentAttributes(L2_STEER_IID, L2_STEERING, ctx); + + verify(api, times(1)).srSteeringAddDel(requestcaptor.capture()); + SrSteeringAddDel srSteering = requestcaptor.getValue(); + + testRequestValidity(srSteering, ByteDataTranslator.BYTE_FALSE); + } + + @Test + public void deleteCurrentAttributesV6Test() throws WriteFailedException { + InterfacesConfigCustomizer customizer = new InterfacesConfigCustomizer(api, interfaceContext); + customizer.deleteCurrentAttributes(L2_STEER_IID, L2_STEERING, ctx); + + verify(api, times(1)).srSteeringAddDel(requestcaptor.capture()); + SrSteeringAddDel srSteering = requestcaptor.getValue(); + + testRequestValidity(srSteering, ByteDataTranslator.BYTE_TRUE); + } + + private void testRequestValidity(SrSteeringAddDel srSteering, byte byteTrue) { + Assert.assertArrayEquals(AddressTranslator.INSTANCE.ipAddressToArray(new IpAddress(BSID_ADR)), + srSteering.bsidAddr); + Assert.assertEquals(byteTrue, srSteering.isDel); + Assert.assertEquals((byte) 2, srSteering.trafficType); + Assert.assertEquals(1, srSteering.swIfIndex); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizerTest.java new file mode 100644 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> + PREFIXES_IID = Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY).child(AutorouteInclude.class) + .child(Prefixes.class); + private static final Ipv6Address BSID_ADR = new Ipv6Address("a::e"); + private static final IpPrefix IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("a::/64")); + private static final PrefixKey L3_STEER_KEY = new PrefixKey(IPV6_PREFIX); + private static final IpPrefix IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("10.0.0.1/24")); + private static final PrefixKey L3_STEER_KEY_2 = new PrefixKey(IPV4_PREFIX); + + private static final Prefix L3_STEERING_V6 = new PrefixBuilder() + .setIpPrefix(IPV6_PREFIX) + .setConfig(new ConfigBuilder().setIpPrefix(IPV6_PREFIX).build()) + .build(); + + private static final Prefix L3_STEERING_V4 = new PrefixBuilder() + .setIpPrefix(IPV4_PREFIX) + .setConfig(new ConfigBuilder().setIpPrefix(IPV4_PREFIX).build()) + .build(); + + private InstanceIdentifier<Prefix> L3_STEER_V6_IID = PREFIXES_IID.child(Prefix.class, L3_STEER_KEY); + private InstanceIdentifier<Prefix> L3_STEER_V4_IID = PREFIXES_IID.child(Prefix.class, L3_STEER_KEY_2); + + @Captor + private ArgumentCaptor<SrSteeringAddDel> requestcaptor; + + @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH) + private Policies policies; + + @Override + protected void init() { + when(api.srSteeringAddDel(any())).thenReturn(future(new SrSteeringAddDelReply())); + when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + } + + @Test + public void writeCurrentAttributesV6Test() throws WriteFailedException { + PrefixCustomizer customizer = new PrefixCustomizer(api); + customizer.writeCurrentAttributes(L3_STEER_V6_IID, L3_STEERING_V6, ctx); + + verify(api, times(1)).srSteeringAddDel(requestcaptor.capture()); + SrSteeringAddDel srSteering = requestcaptor.getValue(); + + testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_FALSE, (byte) 6, true, BSID_ADR, IPV6_PREFIX); + } + + @Test + public void writeCurrentAttributesV4Test() throws WriteFailedException { + PrefixCustomizer customizer = new PrefixCustomizer(api); + customizer.writeCurrentAttributes(L3_STEER_V4_IID, L3_STEERING_V4, ctx); + + verify(api, times(1)).srSteeringAddDel(requestcaptor.capture()); + SrSteeringAddDel srSteering = requestcaptor.getValue(); + + testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_FALSE, (byte) 4, false, BSID_ADR, IPV4_PREFIX); + } + + @Test + public void deleteCurrentAttributesV6Test() throws WriteFailedException { + PrefixCustomizer customizer = new PrefixCustomizer(api); + customizer.deleteCurrentAttributes(L3_STEER_V6_IID, L3_STEERING_V6, ctx); + + verify(api, times(1)).srSteeringAddDel(requestcaptor.capture()); + SrSteeringAddDel srSteering = requestcaptor.getValue(); + + testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_TRUE, (byte) 6, true, BSID_ADR, IPV6_PREFIX); + } + + @Test + public void deleteCurrentAttributesV4Test() throws WriteFailedException { + PrefixCustomizer customizer = new PrefixCustomizer(api); + customizer.deleteCurrentAttributes(L3_STEER_V4_IID, L3_STEERING_V4, ctx); + + verify(api, times(1)).srSteeringAddDel(requestcaptor.capture()); + SrSteeringAddDel srSteering = requestcaptor.getValue(); + + testSrSteeringAddDelValidity(srSteering, ByteDataTranslator.BYTE_TRUE, (byte) 4, false, BSID_ADR, IPV4_PREFIX); + } +} diff --git a/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizerTest.java b/srv6/srv6-impl/src/test/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizerTest.java new file mode 100644 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<Config> PREFIXES_CFG_IID = + Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY).child(AutorouteInclude.class).child(Prefixes.class) + .child(Config.class); + @Captor + private ArgumentCaptor<SrSteeringAddDel> requestcaptor; + + @InjectTestData(resourcePath = "/policy.json", id = POLICIES_LISTS_PATH) + private Policies policies; + + @Override + protected void init() { + when(api.srSteeringAddDel(any())).thenReturn(future(new SrSteeringAddDelReply())); + when(ctx.readAfter(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + when(ctx.readBefore(Srv6PolicyIIds.SR_TE_PLS.child(Policy.class, POLICY_KEY))) + .thenReturn(Optional.of(policies.getPolicy().get(0))); + } + + @Test + public void writeCurrentAttributes() throws WriteFailedException { + PrefixesConfigCustomizer customizer = new PrefixesConfigCustomizer(api); + customizer.writeCurrentAttributes(PREFIXES_CFG_IID, CONFIG, ctx); + + verify(api, times(2)).srSteeringAddDel(requestcaptor.capture()); + List<SrSteeringAddDel> srSteerings = requestcaptor.getAllValues(); + + testSrSteeringAddDelValidity(srSteerings.get(0), ByteDataTranslator.BYTE_FALSE, L3SteeringRequest.VPP_IPV6_TYPE, + true, BSID_ADR, DEFAULT_IPV6_PREFIX); + testSrSteeringAddDelValidity(srSteerings.get(1), ByteDataTranslator.BYTE_FALSE, + L3SteeringRequest.VPP_IPV4_TYPE, false, BSID_ADR, DEFAULT_IPV4_PREFIX); + } + + @Test + public void deleteCurrentAttributes() throws WriteFailedException { + PrefixesConfigCustomizer customizer = new PrefixesConfigCustomizer(api); + customizer.deleteCurrentAttributes(PREFIXES_CFG_IID, CONFIG, ctx); + + verify(api, times(2)).srSteeringAddDel(requestcaptor.capture()); + List<SrSteeringAddDel> srSteerings = requestcaptor.getAllValues(); + + testSrSteeringAddDelValidity(srSteerings.get(0), ByteDataTranslator.BYTE_TRUE, L3SteeringRequest.VPP_IPV6_TYPE, + true, BSID_ADR, DEFAULT_IPV6_PREFIX); + testSrSteeringAddDelValidity(srSteerings.get(1), ByteDataTranslator.BYTE_TRUE, L3SteeringRequest.VPP_IPV4_TYPE, + false, BSID_ADR, DEFAULT_IPV4_PREFIX); + } + +} diff --git a/srv6/srv6-impl/src/test/resources/named-segments.json b/srv6/srv6-impl/src/test/resources/named-segments.json new file mode 100644 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" + } + } + }] + } +} |