From b77a5725338dc700873b36c98af85d70acd7bbe4 Mon Sep 17 00:00:00 2001 From: Michal Cmarada Date: Fri, 15 Jun 2018 13:12:53 +0200 Subject: HC2VPP-304 - add SRv6 policy module new models: - hc2vpp-oc-srte-policy@2017-09-18.yang (ietf draft for srte-policies) - vpp-oc-srte-policy@2018-05-14.yang (augments oc-srte-policy model with VPP specific configuration) - policy-context@2018-06-07.yang defines policy contexts for policies and candidate paths new features: - adds support for writing/reading SRv6 policies - adds support for writing/reading L2 steering - adds support for writing/reading L3 steering - implements support for FIB table management (HC2VPP-345) Change-Id: Ie83ac8ecdcc0e46086e1ecdaecbb811746151c2f Signed-off-by: Michal Cmarada --- .../main/java/io/fd/hc2vpp/srv6/Srv6Module.java | 14 +- .../java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java | 200 +++++++++++++++ .../hc2vpp/srv6/read/Srv6PolicyReaderFactory.java | 104 ++++++++ .../io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java | 2 +- .../srv6/read/policy/NamedSegmentCustomizer.java | 80 ++++++ .../hc2vpp/srv6/read/policy/PolicyCustomizer.java | 75 ++++++ .../read/policy/request/PolicyReadRequest.java | 281 +++++++++++++++++++++ .../srv6/read/steering/InterfaceCustomizer.java | 72 ++++++ .../srv6/read/steering/PrefixCustomizer.java | 67 +++++ .../read/steering/PrefixesStateCustomizer.java | 72 ++++++ .../read/steering/request/L2SteeringRequest.java | 83 ++++++ .../read/steering/request/L3SteeringRequest.java | 125 +++++++++ .../read/steering/request/SteeringRequest.java | 43 ++++ .../srv6/util/CandidatePathContextManager.java | 61 +++++ .../srv6/util/CandidatePathContextManagerImpl.java | 112 ++++++++ .../io/fd/hc2vpp/srv6/util/NoopCustomizer.java | 46 ++++ .../fd/hc2vpp/srv6/util/PolicyContextManager.java | 68 +++++ .../hc2vpp/srv6/util/PolicyContextManagerImpl.java | 108 ++++++++ .../main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java | 99 ++++++++ .../function/xconnect/EndDX2FunctionBinder.java | 2 + .../hc2vpp/srv6/write/Srv6PolicyWriterFactory.java | 88 +++++++ .../io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java | 2 +- .../hc2vpp/srv6/write/policy/PolicyCustomizer.java | 211 ++++++++++++++++ .../write/policy/request/PolicyDeleteRequest.java | 60 +++++ .../write/policy/request/PolicyWriteRequest.java | 178 +++++++++++++ .../srv6/write/policy/request/dto/SidList.java | 64 +++++ .../write/steering/InterfacesConfigCustomizer.java | 92 +++++++ .../srv6/write/steering/PrefixCustomizer.java | 71 ++++++ .../write/steering/PrefixesConfigCustomizer.java | 91 +++++++ .../write/steering/request/L2SteeringRequest.java | 65 +++++ .../write/steering/request/L3SteeringRequest.java | 99 ++++++++ .../write/steering/request/SteeringRequest.java | 52 ++++ 32 files changed, 2784 insertions(+), 3 deletions(-) create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java create mode 100644 srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java (limited to 'srv6/srv6-impl/src/main') diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java index ec91b2133..3e51a4b01 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6Module.java @@ -21,13 +21,19 @@ import static io.fd.hc2vpp.srv6.Srv6Configuration.DEFAULT_LOCATOR_LENGTH; import com.google.inject.AbstractModule; import com.google.inject.Singleton; import com.google.inject.multibindings.Multibinder; +import io.fd.hc2vpp.srv6.read.Srv6PolicyReaderFactory; import io.fd.hc2vpp.srv6.read.Srv6ReaderFactory; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManagerImpl; import io.fd.hc2vpp.srv6.util.LocatorContextManager; import io.fd.hc2vpp.srv6.util.LocatorContextManagerImpl; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.hc2vpp.srv6.util.PolicyContextManagerImpl; import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistry; import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistryProvider; import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionWriteBindingRegistry; import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionWriteBindingRegistryProvider; +import io.fd.hc2vpp.srv6.write.Srv6PolicyWriterFactory; import io.fd.hc2vpp.srv6.write.Srv6WriterFactory; import io.fd.honeycomb.translate.read.ReaderFactory; import io.fd.honeycomb.translate.write.WriterFactory; @@ -35,7 +41,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Srv6Module extends AbstractModule { - private static final Logger LOG = LoggerFactory.getLogger(Srv6Module.class); @Override @@ -45,20 +50,27 @@ public class Srv6Module extends AbstractModule { requestInjection(Srv6Configuration.class); bind(LocatorContextManager.class).toInstance(new LocatorContextManagerImpl(DEFAULT_LOCATOR_LENGTH)); + bind(PolicyContextManager.class).toInstance(new PolicyContextManagerImpl()); + bind(CandidatePathContextManager.class).toInstance(new CandidatePathContextManagerImpl()); bind(LocalSidFunctionReadBindingRegistry.class).toProvider(LocalSidFunctionReadBindingRegistryProvider.class) .in(Singleton.class); bind(LocalSidFunctionWriteBindingRegistry.class).toProvider(LocalSidFunctionWriteBindingRegistryProvider.class) .in(Singleton.class); + LOG.info("Binding SrPolicy context"); LOG.info("Injecting SRv6 writers"); final Multibinder writeBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); writeBinder.addBinding().to(Srv6WriterFactory.class); + LOG.info("Injecting SRv6 Policy writers"); + writeBinder.addBinding().to(Srv6PolicyWriterFactory.class); LOG.info("Injecting SRv6 readers"); final Multibinder readerBinder = Multibinder.newSetBinder(binder(), ReaderFactory.class); readerBinder.addBinding().to(Srv6ReaderFactory.class); + LOG.info("Injecting SRv6 Policy readers"); + readerBinder.addBinding().to(Srv6PolicyReaderFactory.class); LOG.info("SRv6 module successfully configured"); } diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java new file mode 100644 index 000000000..19f62542e --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/Srv6PolicyIIds.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6; + +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentRouting; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteInclude; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.BindingSid; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.CandidatePaths; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentLists; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.Segments; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.Segment; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.SegmentLists; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.Policies; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.Config; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.routing.TrafficEngineering; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppL2AutorouteIncludeAugmentation; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.VppSrPolicy; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.Interfaces; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev180313.Routing; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.Locator1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.multi.paths.v6.Paths; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.multi.paths.v6.paths.Path; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.routing.srv6.locators.locator.Static; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.routing.srv6.locators.locator._static.LocalSids; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6._static.cfg.Sid; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.End; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndB6; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndB6Encaps; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndBm; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDt4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDt46; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDt6; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDx2; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDx4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndDx6; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndT; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6.sid.config.EndX; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.Routing1; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.routing.Srv6; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.encap.Encapsulation; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.Locators; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.locators.Locator; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.locators.locator.Prefix; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class Srv6PolicyIIds { + // SRV6 POLICIES + //segment-routing + public static final InstanceIdentifier SR = InstanceIdentifier.create(SegmentRouting.class); + public static final InstanceIdentifier SR_TE = SR.child(TrafficEngineering.class); + + //segment-routing/traffic-engineering/named-segment-lists + public static final InstanceIdentifier SR_TE_NSLS = SR_TE.child(NamedSegmentLists.class); + public static final InstanceIdentifier SR_TE_NSLS_NSL_IID = + SR_TE_NSLS.child(NamedSegmentList.class); + public static final InstanceIdentifier + SR_TE_NSLS_NSL_CFG = SR_TE_NSLS_NSL_IID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.Config.class); + public static final InstanceIdentifier SR_TE_NSLS_NSL_SGS = SR_TE_NSLS_NSL_IID.child(Segments.class); + public static final InstanceIdentifier SR_TE_NSLS_NSL_SGS_SG = SR_TE_NSLS_NSL_SGS.child(Segment.class); + public static final InstanceIdentifier + SR_TE_NSLS_NSL_SGS_SG_CFG = SR_TE_NSLS_NSL_SGS_SG + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.Config.class); + public static final InstanceIdentifier NSL = InstanceIdentifier.create(NamedSegmentList.class); + public static final InstanceIdentifier + NSL_STATE = NSL + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.State.class); + public static final InstanceIdentifier NSL_SGS = NSL.child(Segments.class); + public static final InstanceIdentifier NSL_SGS_SG = NSL_SGS.child(Segment.class); + public static final InstanceIdentifier + NSL_SGS_SG_STATE = NSL_SGS_SG + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.State.class); + + // policies + public static final InstanceIdentifier SR_TE_PLS = SR_TE.child(Policies.class); + public static final InstanceIdentifier SR_TE_PLS_POL = SR_TE_PLS.child(Policy.class); + public static final InstanceIdentifier SR_TE_PLS_POL_BSID = SR_TE_PLS_POL.child(BindingSid.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_BSID_CFG = SR_TE_PLS_POL_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config.class); + + // policy + public static final InstanceIdentifier SR_POLICY = InstanceIdentifier.create(Policy.class); + public static final InstanceIdentifier SR_POLICY_CFG = SR_POLICY.child(Config.class); + public static final InstanceIdentifier + SR_POLICY_STATE = SR_POLICY + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.State.class); + + // policies/policy/autoroute-include + public static final InstanceIdentifier SR_TE_PLS_POL_AI = + SR_TE_PLS_POL.child(AutorouteInclude.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_CFG = SR_TE_PLS_POL_AI + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.autoroute.include.Config.class); + + // policies/policy/autoroute-include/prefixes + public static final InstanceIdentifier SR_TE_PLS_POL_AI_PFS = SR_TE_PLS_POL_AI.child(Prefixes.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_PFS_CFG = SR_TE_PLS_POL_AI_PFS + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_PFS_STATE = SR_TE_PLS_POL_AI_PFS + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_PFS_PF_IID = SR_TE_PLS_POL_AI_PFS + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_PFS_PF = InstanceIdentifier + .create(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_PFS_PF_CFG = SR_TE_PLS_POL_AI_PFS_PF + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.Config.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_PFS_PF_STATE = SR_TE_PLS_POL_AI_PFS_PF + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.State.class); + + // policies/policy/autoroute-include/interfaces + public static final InstanceIdentifier SR_TE_PLS_POL_AI_IFAUG = + SR_TE_PLS_POL_AI.augmentation(VppL2AutorouteIncludeAugmentation.class); + public static final InstanceIdentifier SR_TE_PLS_POL_AI_IFCS = + SR_TE_PLS_POL_AI_IFAUG.child(Interfaces.class); + public static final InstanceIdentifier SR_TE_PLS_POL_AI_IFCS_IFC_IID = + SR_TE_PLS_POL_AI_IFCS.child(Interface.class); + public static final InstanceIdentifier SR_TE_PLS_POL_AI_IFCS_IFC = + InstanceIdentifier.create(Interface.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_IFCS_IFC_CFG = SR_TE_PLS_POL_AI_IFCS_IFC + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config.class); + public static final InstanceIdentifier + SR_TE_PLS_POL_AI_IFCS_IFC_STATE = SR_TE_PLS_POL_AI_IFCS_IFC + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.State.class); + + // policy/binding-sid + public static final InstanceIdentifier SR_POLICY_BSID = SR_POLICY.child(BindingSid.class); + public static final InstanceIdentifier + SR_POLICY_BSID_STATE = SR_POLICY_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class); + public static final InstanceIdentifier + SR_POLICY_BSID_CFG = SR_POLICY_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class); + + // policy/vpp-sr-policy + public static final InstanceIdentifier SR_POLICY_VPP = + SR_POLICY.augmentation(VppSrPolicyAugmentation.class); + public static final InstanceIdentifier SR_POLICY_VPP_SR = + SR_POLICY_VPP.child(VppSrPolicy.class); + public static final InstanceIdentifier + SR_POLICY_VPP_SR_CFG = SR_POLICY_VPP_SR + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config.class); + public static final InstanceIdentifier + SR_POLICY_VPP_SR_STATE = SR_POLICY_VPP_SR + .child(org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.State.class); + + // policy/candidate-paths + public static final InstanceIdentifier SR_POLICY_CPS = SR_POLICY.child(CandidatePaths.class); + public static final InstanceIdentifier SR_POLICY_CPS_CP = SR_POLICY_CPS.child(CandidatePath.class); + public static final InstanceIdentifier + SR_POLICY_CPS_CP_CFG = SR_POLICY_CPS_CP + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.Config.class); + public static final InstanceIdentifier + SR_POLICY_CPS_CP_STATE = SR_POLICY_CPS_CP + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.State.class); + + public static final InstanceIdentifier SR_POLICY_CPS_CP_SLS = + SR_POLICY_CPS_CP.child(SegmentLists.class); + public static final InstanceIdentifier SR_POLICY_CPS_CP_SLS_SL = + SR_POLICY_CPS_CP_SLS.child(SegmentList.class); + public static final InstanceIdentifier + SR_POLICY_CPS_CP_SLS_SL_CFG = SR_POLICY_CPS_CP_SLS_SL + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.Config.class); + public static final InstanceIdentifier SR_POLICY_CPS_CP_BSID = SR_POLICY_CPS_CP.child(BindingSid.class); + public static final InstanceIdentifier + SR_POLICY_CPS_CP_BSID_CFG = SR_POLICY_CPS_CP_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config.class); + public static final InstanceIdentifier + SR_POLICY_CPS_CP_BSID_STATE = SR_POLICY_CPS_CP_BSID + .child(org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.State.class); +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java new file mode 100644 index 000000000..79b18d235 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6PolicyReaderFactory.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.srv6.Srv6PolicyIIds; +import io.fd.hc2vpp.srv6.read.policy.NamedSegmentCustomizer; +import io.fd.hc2vpp.srv6.read.policy.PolicyCustomizer; +import io.fd.hc2vpp.srv6.read.steering.InterfaceCustomizer; +import io.fd.hc2vpp.srv6.read.steering.PrefixCustomizer; +import io.fd.hc2vpp.srv6.read.steering.PrefixesStateCustomizer; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.honeycomb.translate.impl.read.GenericListReader; +import io.fd.honeycomb.translate.impl.read.GenericReader; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentRoutingBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.autoroute.include.AutorouteIncludeBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentListsBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.PoliciesBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.routing.TrafficEngineeringBuilder; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppL2AutorouteIncludeAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.InterfacesBuilder; + +public class Srv6PolicyReaderFactory implements ReaderFactory { + + @Inject + @Named("interface-context") + private NamingContext interfaceContext; + + @Inject + private FutureJVppCore vppApi; + + @Inject + private LocatorContextManager locatorContext; + + @Inject + private PolicyContextManager policyContext; + + @Inject + private CandidatePathContextManager candidateContext; + + @Override + public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { + registry.addStructuralReader(Srv6PolicyIIds.SR, SegmentRoutingBuilder.class); + registry.addStructuralReader(Srv6PolicyIIds.SR_TE, TrafficEngineeringBuilder.class); + registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS, PoliciesBuilder.class); + registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI, AutorouteIncludeBuilder.class); + registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS, PrefixesBuilder.class); + registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS, InterfacesBuilder.class); + registry.addStructuralReader(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFAUG, + VppL2AutorouteIncludeAugmentationBuilder.class); + registry.addStructuralReader(Srv6PolicyIIds.SR_TE_NSLS, NamedSegmentListsBuilder.class); + + registry.subtreeAdd(ImmutableSet + .of(Srv6PolicyIIds.SR_POLICY_BSID, Srv6PolicyIIds.SR_POLICY_BSID_STATE, + Srv6PolicyIIds.SR_POLICY_VPP, Srv6PolicyIIds.SR_POLICY_VPP_SR, + Srv6PolicyIIds.SR_POLICY_VPP_SR_STATE, Srv6PolicyIIds.SR_POLICY_STATE, + Srv6PolicyIIds.SR_POLICY_CPS, Srv6PolicyIIds.SR_POLICY_CPS_CP, + Srv6PolicyIIds.SR_POLICY_CPS_CP_STATE, Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID, + Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID_STATE, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS, + Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL_CFG), + new GenericListReader<>(Srv6PolicyIIds.SR_TE_PLS_POL, + new PolicyCustomizer(vppApi, policyContext, candidateContext))); + registry.add( + new GenericReader<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_STATE, + new PrefixesStateCustomizer(vppApi))); + + registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_STATE), + new GenericListReader<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_IID, + new PrefixCustomizer(vppApi))); + registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_STATE), + new GenericListReader<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_IID, + new InterfaceCustomizer(vppApi, interfaceContext))); + + registry.subtreeAdd( + ImmutableSet.of(Srv6PolicyIIds.NSL_STATE, Srv6PolicyIIds.NSL_SGS, Srv6PolicyIIds.NSL_SGS_SG, + Srv6PolicyIIds.NSL_SGS_SG_STATE), + new GenericListReader<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_IID, + new NamedSegmentCustomizer(vppApi, policyContext, candidateContext))); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java index 312280dce..41c33f98b 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java @@ -43,7 +43,7 @@ public class Srv6ReaderFactory implements ReaderFactory { private LocalSidFunctionReadBindingRegistry bindingRegistry; @Inject - protected LocatorContextManager locatorContext; + private LocatorContextManager locatorContext; @Override public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java new file mode 100644 index 000000000..9f9c0e2ab --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/NamedSegmentCustomizer.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.read.policy; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.read.policy.request.PolicyReadRequest; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.NamedSegmentListsBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class NamedSegmentCustomizer extends FutureJVppCustomizer + implements ListReaderCustomizer { + private final PolicyContextManager policyContext; + private final CandidatePathContextManager candidateContext; + + public NamedSegmentCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + final PolicyContextManager policyContext, + final CandidatePathContextManager candidateContext) { + super(futureJVppCore); + this.policyContext = policyContext; + this.candidateContext = candidateContext; + } + + @Nonnull + @Override + public List getAllIds(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final ReadContext readContext) throws ReadFailedException { + PolicyReadRequest + policyReadRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + policyReadRequest.checkValid(); + return policyReadRequest.readNamedSegmentListKeys(instanceIdentifier, readContext); + } + + @Override + public void merge(@Nonnull final Builder builder, + @Nonnull final List list) { + ((NamedSegmentListsBuilder) builder).setNamedSegmentList(list); + } + + @Nonnull + @Override + public NamedSegmentListBuilder getBuilder(@Nonnull final InstanceIdentifier instanceIdentifier) { + return new NamedSegmentListBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final NamedSegmentListBuilder builder, + @Nonnull final ReadContext readContext) throws ReadFailedException { + PolicyReadRequest readRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + readRequest.readNamedSegmentList(instanceIdentifier, builder, readContext); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java new file mode 100644 index 000000000..c4c323b52 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/PolicyCustomizer.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.policy; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.read.policy.request.PolicyReadRequest; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.PoliciesBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PolicyCustomizer extends FutureJVppCustomizer + implements ListReaderCustomizer { + + private final PolicyContextManager policyContext; + private final CandidatePathContextManager candidateContext; + + public PolicyCustomizer(@Nonnull final FutureJVppCore futureJVppCore, PolicyContextManager policyContext, + final CandidatePathContextManager candidateContext) { + super(futureJVppCore); + this.policyContext = policyContext; + this.candidateContext = candidateContext; + } + + @Nonnull + @Override + public List getAllIds(@Nonnull InstanceIdentifier id, @Nonnull ReadContext context) + throws ReadFailedException { + PolicyReadRequest policyReadRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + return policyReadRequest.readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder builder, @Nonnull List readData) { + ((PoliciesBuilder) builder).setPolicy(readData); + } + + @Nonnull + @Override + public PolicyBuilder getBuilder(@Nonnull InstanceIdentifier id) { + return new PolicyBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier id, @Nonnull PolicyBuilder builder, + @Nonnull ReadContext ctx) throws ReadFailedException { + PolicyReadRequest readRequest = new PolicyReadRequest(getFutureJVpp(), policyContext, candidateContext); + readRequest.readSpecific(id, ctx, builder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java new file mode 100644 index 000000000..8117d4d91 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/policy/request/PolicyReadRequest.java @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.policy.request; + +import com.google.common.base.Preconditions; +import io.fd.hc2vpp.srv6.read.ReadRequest; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.vpp.jvpp.core.dto.SrPoliciesDetails; +import io.fd.vpp.jvpp.core.dto.SrPoliciesDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.SrPoliciesDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import io.fd.vpp.jvpp.core.types.Srv6Sid; +import io.fd.vpp.jvpp.core.types.Srv6SidList; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.BindingSidAllocMode; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.PathExplicitlyDefined; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.PolicyAdminState; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentListOperState; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SegmentType; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.SidValueType; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.BindingSidBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.StateBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.CandidatePathsBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePathBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.SegmentsBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.Segment; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.SegmentBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.SegmentKey; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.SegmentListsBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentListBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyBehavior; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyType; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.VppSrPolicyBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMapping; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.Ipv6; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.VniReference; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PolicyReadRequest extends JVppRequest + implements ReadRequest { + + private static final String DASH_SEPARATOR = "-"; + private static final Logger LOG = LoggerFactory.getLogger(PolicyReadRequest.class); + private static final SrPoliciesDump STATIC_DUMP_REQUEST = new SrPoliciesDump(); + private static final SrPoliciesDetailsReplyDump STATIC_EMPTY_REPLY = new SrPoliciesDetailsReplyDump(); + private final PolicyContextManager policyCtx; + private final CandidatePathContextManager candidateCtx; + private final DumpCacheManager dumpManager; + + public PolicyReadRequest(FutureJVppCore futureJVpp, PolicyContextManager policyCtx, + final CandidatePathContextManager candidateCtx) { + super(futureJVpp); + this.policyCtx = policyCtx; + this.candidateCtx = candidateCtx; + this.dumpManager = new DumpCacheManager.DumpCacheManagerBuilder().acceptOnly( + SrPoliciesDetailsReplyDump.class) + .withExecutor((identifier, params) -> getReplyForRead( + getApi().srPoliciesDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier)) + .build(); + } + + @Nonnull + public List readAllKeys(@Nonnull InstanceIdentifier id, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .map(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr)) + .map(bsid -> parsePolicyKey(ctx, bsid)) + .collect(Collectors.toList()); + } + + private PolicyKey parsePolicyKey(final @Nonnull ReadContext ctx, final Ipv6Address bsid) { + Srv6PolicyMapping policy = policyCtx.getPolicy(bsid, ctx.getMappingContext()); + return new PolicyKey(policy.getColor(), new IpAddress(policy.getEndpoint())); + } + + @Override + public void readSpecific(@Nonnull InstanceIdentifier id, @Nonnull ReadContext ctx, + @Nonnull PolicyBuilder builder) throws ReadFailedException { + PolicyKey key = id.firstKeyOf(Policy.class); + Ipv6Address bsid = + policyCtx.getPolicyBsid(key.getColor(), key.getEndpoint().getIpv6Address(), ctx.getMappingContext()); + + dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .filter(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue() + .equals(bsid.getValue())) + .findFirst() + .ifPresent((SrPoliciesDetails details) -> bindPolicy(details, ctx, builder)); + } + + private void bindPolicy(SrPoliciesDetails srPoliciesDetails, @Nonnull ReadContext ctx, + final PolicyBuilder builder) { + + Ipv6Address bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr); + Srv6PolicyMapping policy = policyCtx.getPolicy(bsid, ctx.getMappingContext()); + IpAddress endpoint = new IpAddress(policy.getEndpoint()); + builder.setName(policy.getName()).setEndpoint(endpoint).setColor(policy.getColor()); + builder.setKey(new PolicyKey(policy.getColor(), endpoint)); + builder.setBindingSid(new BindingSidBuilder().setState( + new StateBuilder().setType(DataplaneType.Srv6).setAllocMode(BindingSidAllocMode.Explicit) + .setValue(new SidValueType(new IpAddress(bsid))).build()).build()); + builder.addAugmentation(VppSrPolicyAugmentation.class, new VppSrPolicyAugmentationBuilder() + .setVppSrPolicy(new VppSrPolicyBuilder().setState( + new org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.StateBuilder() + .setPolicyBehavior( + SegmentRoutingPolicyBehavior.forValue((int) srPoliciesDetails.isEncap)) + .setPolicyType(SegmentRoutingPolicyType.forValue((int) srPoliciesDetails.type)) + .setTableId(new VniReference(Integer.toUnsignedLong(srPoliciesDetails.fibTable))) + .setAddressFamily(Ipv6.class) + .build()).build()) + .build()); + + builder.setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policy.properties.StateBuilder() + .setName(policy.getName()).setEndpoint(endpoint) + .setColor(policy.getColor()).setAdminState(PolicyAdminState.UP) + .build()); + + builder.setCandidatePaths( + new CandidatePathsBuilder().setCandidatePath(resolveCandidatePaths(srPoliciesDetails, ctx)).build()); + } + + private List resolveCandidatePaths(final SrPoliciesDetails srPoliciesDetails, + final ReadContext ctx) { + List candidatePaths = new ArrayList<>(); + //only one candidate path can be selected and present on device at the same time + if (srPoliciesDetails.sidLists == null) { + LOG.debug("No policy segments found for BSID: {}", srPoliciesDetails.bsid); + return candidatePaths; + } + Ipv6Address bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr); + Srv6CandidatePathMapping candidatePath = + candidateCtx.getCandidatePath(bsid, ctx.getMappingContext()); + + CandidatePathBuilder candidatePathBuilder = + new CandidatePathBuilder() + .setDistinguisher(candidatePath.getDistinguisher()) + .setPreference(candidatePath.getPreference()) + .setProvisioningMethod(candidatePath.getProvisioningMethod()) + .setName(candidatePath.getName()); + + candidatePathBuilder.setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.candidate.path.StateBuilder() + .setDistinguisher(candidatePath.getDistinguisher()) + .setPreference(candidatePath.getPreference()) + .setProvisioningMethod(candidatePath.getProvisioningMethod()) + .setComputationMethod(PathExplicitlyDefined.class) + .setName(candidatePath.getName()) + .build()); + candidatePathBuilder.setBindingSid(new BindingSidBuilder().setState( + new StateBuilder().setAllocMode(BindingSidAllocMode.Explicit).setType(DataplaneType.Srv6) + .setValue(new SidValueType(new IpAddress(bsid))).build()).build()); + + List segments = new ArrayList<>(); + for (Srv6SidList sidlist : srPoliciesDetails.sidLists) { + long weight = Integer.toUnsignedLong(sidlist.weight); + SegmentListBuilder segmentListBuilder = + new SegmentListBuilder().setName(Srv6Util.getCandidatePathName(bsid, weight)); + segmentListBuilder.setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.StateBuilder() + .setName(Srv6Util.getCandidatePathName(bsid, weight)) + .setWeight(weight) + .setOperState(SegmentListOperState.ACTIVE) + .build()); + segments.add(segmentListBuilder.build()); + } + candidatePathBuilder.setSegmentLists(new SegmentListsBuilder().setSegmentList(segments).build()); + candidatePaths.add(candidatePathBuilder.build()); + return candidatePaths; + } + + public List readNamedSegmentListKeys(final InstanceIdentifier id, + final ReadContext ctx) throws ReadFailedException { + return dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .map(srPoliciesDetails -> { + String bsid = arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue(); + return Arrays.stream(srPoliciesDetails.sidLists).map(srv6SidList -> srv6SidList.weight) + .map(weight -> bsid + DASH_SEPARATOR + weight).collect(Collectors.toList()); + }).flatMap(Collection::stream).map(NamedSegmentListKey::new).distinct().collect(Collectors.toList()); + } + + public void readNamedSegmentList(final InstanceIdentifier id, + final NamedSegmentListBuilder builder, + final ReadContext ctx) + throws ReadFailedException { + NamedSegmentListKey key = id.firstKeyOf(NamedSegmentList.class); + builder.setKey(key) + .setName(key.getName()) + .setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.list.properties.StateBuilder() + .setName(key.getName()) + .build()); + + Long weight = parseWeight(key); + String bsid = parseBsid(key); + Preconditions.checkNotNull(bsid, "Weight/Bsid not resolved for Iid: {}", id); + + builder.setSegments(new SegmentsBuilder().build()); + dumpManager.getDump(id, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srPoliciesDetails.stream() + .filter(srPoliciesDetails -> arrayToIpv6AddressNoZone(srPoliciesDetails.bsid.addr).getValue() + .equals(bsid)) + .forEach(srPoliciesDetails -> Arrays.stream(srPoliciesDetails.sidLists) + .forEach(srv6SidList -> { + if (srv6SidList.weight == weight.intValue()) { + List segments = IntStream.range(0, srv6SidList.numSids) + .mapToObj(i -> parseSrv6Sid(i, srv6SidList.sids[i])) + .collect(Collectors.toList()); + builder.setSegments(new SegmentsBuilder().setSegment(segments).build()); + } + })); + } + + private Segment parseSrv6Sid(final int i, final Srv6Sid srv6Sid) { + // shifting index by 1 so it matches original indexing + long index = i + 1; + SegmentBuilder builder = new SegmentBuilder().setKey(new SegmentKey(index)).setState( + new org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.segment.properties.StateBuilder() + .setIndex(index) + .setType(SegmentType.Type2) + .setSidValue(new SidValueType( + new IpAddress(new Ipv6Address(arrayToIpv6AddressNoZone(srv6Sid.addr))))) + .build()); + return builder.build(); + } + + + private Long parseWeight(final NamedSegmentListKey key) { + String[] values = key.getName().split(DASH_SEPARATOR); + + return values.length == 2 + ? Long.parseLong(values[1]) + : 0; + } + + private String parseBsid(final NamedSegmentListKey key) { + String[] values = key.getName().split(DASH_SEPARATOR); + return values.length == 2 ? values[0] : null; + } + +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java new file mode 100644 index 000000000..9151a9822 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/InterfaceCustomizer.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.srv6.read.steering.request.L2SteeringRequest; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.autoroute.include.InterfacesBuilder; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class InterfaceCustomizer extends FutureJVppCustomizer + implements ListReaderCustomizer { + + private final NamingContext interfaceContext; + + public InterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore); + this.interfaceContext = interfaceContext; + } + + @Nonnull + @Override + public List getAllIds(@Nonnull InstanceIdentifier id, @Nonnull ReadContext context) + throws ReadFailedException { + return + new L2SteeringRequest(getFutureJVpp(), interfaceContext).readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder builder, @Nonnull List readData) { + ((InterfacesBuilder) builder).setInterface(readData); + } + + @Nonnull + @Override + public InterfaceBuilder getBuilder(@Nonnull InstanceIdentifier id) { + return new InterfaceBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier id, @Nonnull InterfaceBuilder builder, + @Nonnull ReadContext ctx) throws ReadFailedException { + L2SteeringRequest readRequest = new L2SteeringRequest(getFutureJVpp(), interfaceContext); + readRequest.readSpecific(id, ctx, builder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java new file mode 100644 index 000000000..b0ee7c3f8 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixCustomizer.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.read.steering.request.L3SteeringRequest; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PrefixCustomizer extends FutureJVppCustomizer + implements ListReaderCustomizer { + + public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Nonnull + @Override + public List getAllIds(@Nonnull InstanceIdentifier id, @Nonnull ReadContext context) + throws ReadFailedException { + return + new L3SteeringRequest(getFutureJVpp()).readAllKeys(id, context); + } + + @Override + public void merge(@Nonnull Builder builder, @Nonnull List readData) { + ((PrefixesBuilder) builder).setPrefix(readData); + } + + @Nonnull + @Override + public PrefixBuilder getBuilder(@Nonnull InstanceIdentifier id) { + return new PrefixBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier id, @Nonnull PrefixBuilder builder, + @Nonnull ReadContext ctx) throws ReadFailedException { + L3SteeringRequest readRequest = new L3SteeringRequest(getFutureJVpp()); + readRequest.readSpecific(id, ctx, builder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java new file mode 100644 index 000000000..b099939eb --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/PrefixesStateCustomizer.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.read.steering; + +import com.google.common.collect.ImmutableSet; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.read.steering.request.L3SteeringRequest; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.PrefixesBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.State; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.StateBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PrefixesStateCustomizer extends FutureJVppCustomizer implements ReaderCustomizer { + + public PrefixesStateCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Nonnull + @Override + public StateBuilder getBuilder(@Nonnull final InstanceIdentifier instanceIdentifier) { + return new StateBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final StateBuilder stateBuilder, @Nonnull final ReadContext readContext) + throws ReadFailedException { + L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp()); + List ipPrefixes = + request.readAllIpPrefixes(RWUtils.cutId(instanceIdentifier, Prefixes.class), readContext); + // checks whether L3 steering contains default routes to steer all traffic to SRv6 policy. If found sets + // allPrefixes flag to true in autoroute-include/prefixes/state + boolean allPrefixes = ipPrefixes.containsAll( + ImmutableSet.of(new IpPrefix(new Ipv4Prefix("0.0.0.0/0")), new IpPrefix(new Ipv6Prefix("::/0")))); + + stateBuilder.setPrefixesAll(allPrefixes); + } + + @Override + public void merge(@Nonnull final Builder builder, @Nonnull final State state) { + ((PrefixesBuilder) builder).setState(state); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java new file mode 100644 index 000000000..eb9370787 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L2SteeringRequest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.steering.request; + +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.srv6.read.ReadRequest; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetails; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.StateBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Request for steering of L2 traffic + */ + +public class L2SteeringRequest extends SteeringRequest + implements ReadRequest { + + static final int L2_TRAFFIC_TYPE = 2; + private final NamingContext ifcNamingContext; + + public L2SteeringRequest(FutureJVppCore api, NamingContext namingContext) { + super(api); + this.ifcNamingContext = namingContext; + } + + @Override + @Nonnull + public List readAllKeys(@Nonnull InstanceIdentifier identifier, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter(srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) == L2_TRAFFIC_TYPE) + .map(srSteeringPolDetails -> srSteeringPolDetails.swIfIndex) + .map(ifIndex -> new InterfaceKey(ifcNamingContext.getName(ifIndex, ctx.getMappingContext()))) + .collect(Collectors.toList()); + } + + @Override + public void readSpecific(@Nonnull InstanceIdentifier identifier, @Nonnull ReadContext ctx, + @Nonnull InterfaceBuilder builder) throws ReadFailedException { + int index = + ifcNamingContext.getIndex(identifier.firstKeyOf(Interface.class).getInputInterface(), + ctx.getMappingContext()); + + dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter(srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) == L2_TRAFFIC_TYPE) + .filter(srSteeringPolDetails -> srSteeringPolDetails.swIfIndex == index) + .findFirst() + .ifPresent(srSteeringPolDetails -> parseL2Steering(srSteeringPolDetails, builder, ctx)); + } + + private void parseL2Steering(SrSteeringPolDetails srSteeringPolDetails, final InterfaceBuilder builder, + ReadContext ctx) { + String name = ifcNamingContext.getName(srSteeringPolDetails.swIfIndex, ctx.getMappingContext()); + builder.setInputInterface(name).setKey(new InterfaceKey(name)) + .setState(new StateBuilder().setInputInterface(name).build()); + } +} + diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java new file mode 100644 index 000000000..1043746e9 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/L3SteeringRequest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.steering.request; + +import com.google.common.base.Preconditions; +import io.fd.hc2vpp.srv6.read.ReadRequest; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetails; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.include.prefix.StateBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.Prefixes; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixBuilder; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Request for steering of L3 traffic + */ + +public class L3SteeringRequest extends SteeringRequest + implements ReadRequest { + + private static final int L3_TRAFFIC_TYPE_IPV6 = 6; + private static final int L3_TRAFFIC_TYPE_IPV4 = 4; + + public L3SteeringRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + super.checkValid(); + } + + @Override + @Nonnull + public List readAllKeys(@Nonnull InstanceIdentifier identifier, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter( + srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) != + L2SteeringRequest.L2_TRAFFIC_TYPE) + .map(this::parseL3SteeringKey) + .collect(Collectors.toList()); + } + + public List readAllIpPrefixes(@Nonnull InstanceIdentifier identifier, @Nonnull ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter( + srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) != + L2SteeringRequest.L2_TRAFFIC_TYPE) + .map(this::parseIpPrefix) + .collect(Collectors.toList()); + } + + @Override + public void readSpecific(@Nonnull InstanceIdentifier identifier, @Nonnull ReadContext ctx, + @Nonnull PrefixBuilder builder) throws ReadFailedException { + checkValid(); + PrefixKey key = identifier.firstKeyOf(Prefix.class); + dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY) + .srSteeringPolDetails.stream() + .filter( + srSteeringPolDetails -> ((int) srSteeringPolDetails.trafficType) != + L2SteeringRequest.L2_TRAFFIC_TYPE) + .filter(srSteeringPolDetails -> parseL3SteeringKey(srSteeringPolDetails).equals(key)) + .findFirst() + .ifPresent(srSteeringPolDetails1 -> parseL3Steering(srSteeringPolDetails1, builder)); + } + + private void parseL3Steering(SrSteeringPolDetails srSteeringPolDetails, final PrefixBuilder builder) { + PrefixKey key = parseL3SteeringKey(srSteeringPolDetails); + builder.setKey(key).setIpPrefix(key.getIpPrefix()) + .setState(new StateBuilder().setIpPrefix(key.getIpPrefix()).build()); + } + + private PrefixKey parseL3SteeringKey(SrSteeringPolDetails policyDetails) { + return new PrefixKey(parseIpPrefix(policyDetails)); + } + + private IpPrefix parseIpPrefix(final SrSteeringPolDetails policyDetails) { + boolean isIpv6 = isIpv6L3TrafficType(policyDetails.trafficType); + IpPrefix ipPrefix; + if (isIpv6) { + Ipv6Prefix ipv6Prefix = toIpv6Prefix(policyDetails.prefixAddr, policyDetails.maskWidth); + ipPrefix = new IpPrefix(ipv6Prefix); + } else { + Ipv4Prefix ipv4Prefix = toIpv4Prefix(policyDetails.prefixAddr, policyDetails.maskWidth); + ipPrefix = new IpPrefix(ipv4Prefix); + } + return ipPrefix; + } + + private boolean isIpv6L3TrafficType(final byte trafficType) { + Preconditions.checkArgument(trafficType == L3_TRAFFIC_TYPE_IPV4 || trafficType == L3_TRAFFIC_TYPE_IPV6, + "Unsupported traffic type for L3 steering"); + + return trafficType == L3_TRAFFIC_TYPE_IPV6; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java new file mode 100644 index 000000000..04b67f67e --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/steering/request/SteeringRequest.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.steering.request; + +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.vpp.jvpp.core.dto.SrSteeringPolDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.SrSteeringPolDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; + +/** + * General template for steering requests + */ +abstract class SteeringRequest extends JVppRequest { + + static final SrSteeringPolDetailsReplyDump STATIC_EMPTY_REPLY = new SrSteeringPolDetailsReplyDump(); + private static final SrSteeringPolDump STATIC_DUMP_REQUEST = new SrSteeringPolDump(); + final DumpCacheManager dumpManager; + + SteeringRequest(final FutureJVppCore api) { + super(api); + this.dumpManager = + new DumpCacheManager.DumpCacheManagerBuilder().acceptOnly( + SrSteeringPolDetailsReplyDump.class) + .withExecutor((identifier, params) -> getReplyForRead( + getApi().srSteeringPolDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier)) + .build(); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java new file mode 100644 index 000000000..d0b6479be --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManager.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.util; + +import io.fd.honeycomb.translate.MappingContext; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodType; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMapping; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; + +/** + * Manages metadata for SRv6 policy plugin + */ +public interface CandidatePathContextManager { + /** + * Creates metadata for candidate path. Existing mapping is overwritten if exists. + * + * @param bsid candidate path bsid + * @param name candidate path name + * @param provisioningMethod candidate path provisioning method + * @param preference candidate path preference + * @param distinguisher candidate path distinguisher + * @param ctx mapping context providing context data for current transaction + */ + void addCandidatePath(@Nonnull Ipv6Address bsid, @Nonnull final String name, + @Nonnull final Class provisioningMethod, + @Nonnull Long preference, @Nonnull Long distinguisher, @Nonnull final MappingContext ctx); + + /** + * Retrieves candidate path for given name. If not present it will generate artificial mapping + * + * @param bsid candidate path BSID + * @param ctx mapping context providing context data for current transaction + * @return candidate path matching supplied candidate path BSID if present, artificial mapping otherwise + */ + @Nonnull + Srv6CandidatePathMapping getCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx); + + /** + * Removes candidate path metadata from current context. + * + * @param bsid candidate path BSID + * @param ctx mapping context providing context data for current transaction + */ + void removeCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx); + +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java new file mode 100644 index 000000000..15fb5c0ff --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/CandidatePathContextManagerImpl.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.util; + +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.MappingContext; +import java.util.concurrent.atomic.AtomicLong; +import javax.annotation.Nonnull; +import javax.annotation.concurrent.ThreadSafe; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodConfig; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodType; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.Srv6PolicyContextAugmentation; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.Srv6CandidatePathMappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMappingBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.candidate.path.context.attributes.srv6.candidate.path.mappings.Srv6CandidatePathMappingKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Facade on top of {@link MappingContext} that manages {@link Srv6CandidatePathMappings}. + */ +@ThreadSafe +public class CandidatePathContextManagerImpl implements CandidatePathContextManager { + + private static final long DEFAULT_PREFERENCE = 100L; + private AtomicLong distinguisher; + + private final InstanceIdentifier ctxIid; + + public CandidatePathContextManagerImpl() { + this.ctxIid = InstanceIdentifier.create(Contexts.class) + .augmentation(Srv6PolicyContextAugmentation.class) + .child(Srv6CandidatePathMappings.class); + distinguisher = new AtomicLong(0L); + } + + @Override + public void addCandidatePath(@Nonnull Ipv6Address bsid, @Nonnull final String name, + @Nonnull final Class provisioningMethod, + @Nonnull Long preference, @Nonnull Long distinguisher, + @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier mappingIid = + getCandidatePathIid(bsid); + final Srv6CandidatePathMappingBuilder builder = + new Srv6CandidatePathMappingBuilder().setKey(new Srv6CandidatePathMappingKey(bsid)) + .setProvisioningMethod(provisioningMethod).setPreference(preference) + .setDistinguisher(distinguisher).setBsid(bsid).setName(name); + ctx.put(mappingIid, builder.build()); + } + + private KeyedInstanceIdentifier getCandidatePathIid( + final Ipv6Address bsid) { + return ctxIid.child(Srv6CandidatePathMapping.class, new Srv6CandidatePathMappingKey(bsid)); + } + + @Override + @Nonnull + public synchronized Srv6CandidatePathMapping getCandidatePath(@Nonnull final Ipv6Address bsid, + @Nonnull final MappingContext ctx) { + final Optional read = ctx.read(ctxIid); + if (read.isPresent()) { + java.util.Optional mappingOpt = read.get().getSrv6CandidatePathMapping().stream() + .filter(srv6CandidatePathMapping -> srv6CandidatePathMapping.getBsid().getValue() + .equals(bsid.getValue())).findAny(); + if (mappingOpt.isPresent()) { + return mappingOpt.get(); + } + } + return getArtificialMapping(bsid, ctx, bsid.getValue()); + } + + private Srv6CandidatePathMapping getArtificialMapping(final @Nonnull Ipv6Address bsid, + final @Nonnull MappingContext ctx, final String name) { + // if not present we need to generate artificial mapping + // for given policy only one candidate path can be selected and be configured on the device. + Srv6CandidatePathMapping mapping = + new Srv6CandidatePathMappingBuilder() + .setProvisioningMethod(ProvisioningMethodConfig.class) + .setBsid(bsid) //when we read name from VPP it is always the BSID value + .setPreference(DEFAULT_PREFERENCE) + .setDistinguisher(distinguisher.incrementAndGet()) + .build(); + addCandidatePath(mapping.getBsid(), name, mapping.getProvisioningMethod(), mapping.getPreference(), + mapping.getDistinguisher(), ctx); + return mapping; + } + + @Override + public void removeCandidatePath(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier mappingIid = + getCandidatePathIid(bsid); + ctx.delete(mappingIid); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java new file mode 100644 index 000000000..dd0f2615e --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/NoopCustomizer.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.util; + +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NoopCustomizer implements WriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(NoopCustomizer.class); + + public NoopCustomizer() { + super(); + } + + @Override + public void writeCurrentAttributes(@Nonnull InstanceIdentifier instanceIdentifier, @Nonnull T data, + @Nonnull WriteContext writeContext) { + LOG.trace("Noop write called for IId: {}, data: {}", instanceIdentifier, data); + } + + @Override + public void deleteCurrentAttributes(@Nonnull InstanceIdentifier instanceIdentifier, @Nonnull T data, + @Nonnull WriteContext writeContext) { + LOG.trace("Noop delete called for IId: {}, data: {}", instanceIdentifier, data); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java new file mode 100644 index 000000000..3a07fe024 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManager.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.util; + +import io.fd.honeycomb.translate.MappingContext; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMapping; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; + +/** + * Manages metadata for SRv6 policy plugin + */ +public interface PolicyContextManager { + /** + * Creates metadata for policy. Existing mapping is overwritten if exists. + * + * @param name policy name + * @param color policy color + * @param endpoint policy endpoint + * @param bsid policy bsid + * @param ctx mapping context providing context data for current transaction + */ + void addPolicy(@Nonnull final String name, @Nonnull Long color, @Nonnull Ipv6Address endpoint, + @Nonnull Ipv6Address bsid, @Nonnull final MappingContext ctx); + + /** + * Retrieves policy for given policy BSID. If not present it wil generate artificial mapping + * + * @param bsid policy BSID + * @param ctx mapping context providing context data for current transaction + * @return policy matching supplied policy BSID if present, or artificial mapping if not + */ + @Nonnull + Srv6PolicyMapping getPolicy(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx); + + /** + * Retrieves policy BSID for given policy color and endpoint. + * + * @param color policy color + * @param endpoint policy endpoint + * @param ctx mapping context providing context data for current transaction + * @return policy BSID matching supplied policy color and endpoint if present, null otherwise + */ + Ipv6Address getPolicyBsid(@Nonnull Long color, @Nonnull Ipv6Address endpoint, @Nonnull final MappingContext ctx); + + /** + * Removes policy metadata from current context. + * + * @param bsid policy BSID + * @param ctx mapping context providing context data for current transaction + */ + void removePolicy(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx); + +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java new file mode 100644 index 000000000..1997043e2 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/PolicyContextManagerImpl.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.util; + +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.MappingContext; +import javax.annotation.Nonnull; +import javax.annotation.concurrent.ThreadSafe; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.Contexts; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.Srv6PolicyContextAugmentation; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.Srv6PolicyMappings; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMapping; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMappingBuilder; +import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.policy.context.rev180607.srv6.policy.context.attributes.srv6.policy.mappings.Srv6PolicyMappingKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Facade on top of {@link MappingContext} that manages {@link Srv6PolicyMappings}. + */ +@ThreadSafe +public class PolicyContextManagerImpl implements PolicyContextManager { + + private final InstanceIdentifier ctxIid; + // 2001:db8::/32 This address range is used for documentation and example source code. We can use it as dummy + // addresses for our artificial policies + private static final String DUMMY_EP = "2001:db8::"; + private Long artificialColor; + + public PolicyContextManagerImpl() { + this.ctxIid = InstanceIdentifier.create(Contexts.class) + .augmentation(Srv6PolicyContextAugmentation.class) + .child(Srv6PolicyMappings.class); + this.artificialColor = 0L; + } + + @Override + public void addPolicy(@Nonnull final String name, @Nonnull final Long color, @Nonnull final Ipv6Address endpoint, + @Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier mappingIid = getPolicyIid(bsid); + final Srv6PolicyMappingBuilder builder = + new Srv6PolicyMappingBuilder().setKey(new Srv6PolicyMappingKey(bsid)).setColor(color) + .setEndpoint(endpoint).setBsid(bsid).setName(name); + ctx.put(mappingIid, builder.build()); + } + + private KeyedInstanceIdentifier getPolicyIid(final Ipv6Address bsid) { + return ctxIid.child(Srv6PolicyMapping.class, new Srv6PolicyMappingKey(bsid)); + } + + @Nonnull + public synchronized Srv6PolicyMapping getPolicy(@Nonnull final Ipv6Address bsid, + @Nonnull final MappingContext ctx) { + final Optional read = ctx.read(getPolicyIid(bsid)); + if (read.isPresent()) { + return read.get(); + } + + //if not present we need to generate artificial mapping + Long nextArtificialColor = getNextArtificialColor(); + Ipv6Address endpoint = new Ipv6Address(DUMMY_EP + nextArtificialColor); + Srv6PolicyMapping mapping = + new Srv6PolicyMappingBuilder().setBsid(bsid).setColor(nextArtificialColor).setEndpoint(endpoint) + .setName(bsid.getValue()).build(); + addPolicy(mapping.getName(), mapping.getColor(), mapping.getEndpoint(), mapping.getBsid(), ctx); + return mapping; + } + + @Override + public Ipv6Address getPolicyBsid(@Nonnull Long color, @Nonnull Ipv6Address endpoint, + @Nonnull final MappingContext ctx) { + Optional read = ctx.read(ctxIid); + if (read.isPresent()) { + return read.get().getSrv6PolicyMapping().stream() + .filter(srv6PolicyMapping -> srv6PolicyMapping.getColor().equals(color) && + srv6PolicyMapping.getEndpoint().equals(endpoint)) + .map(Srv6PolicyMapping::getBsid).findFirst().orElse(null); + } + return null; + } + + @Override + public void removePolicy(@Nonnull final Ipv6Address bsid, @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier mappingIid = getPolicyIid(bsid); + ctx.delete(mappingIid); + } + + private synchronized Long getNextArtificialColor() { + artificialColor++; + return artificialColor; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java new file mode 100644 index 000000000..ea308efcf --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/Srv6Util.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.util; + +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.write.WriteContext; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.segment.routing.traffic.engineering.policies.policy.VppSrPolicy; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public final class Srv6Util { + + /** + * Constructs unique name for candidate path based on binding sid and weight + * + * @param bsid binding sid associated with candidate path + * @param weight weight of actual sidList + * @return candidate path name + */ + public static String getCandidatePathName(final Ipv6Address bsid, final long weight) { + return bsid.getValue() + "-" + weight; + } + + /** + * Extracts BSID from policy, based on read/write operation it uses dataBefore/dataAfter while reading config + * + * @param instanceIdentifier identifier used to extract path of policy + * @param writeContext used to store any useful information later utilized by customizers + * @param isWrite condition whether this is a write or delete operation + * @return BSID in form of IPv6 address or null if not resolved + */ + public static Ipv6Address extractBsid( + final @Nonnull InstanceIdentifier instanceIdentifier, final @Nonnull WriteContext writeContext, + boolean isWrite) { + Optional policyOptional = isWrite + ? writeContext.readAfter(RWUtils.cutId(instanceIdentifier, Policy.class)) + : writeContext.readBefore(RWUtils.cutId(instanceIdentifier, Policy.class)); + + if (policyOptional.isPresent() && policyOptional.get().getBindingSid() != null && + policyOptional.get().getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + config = policyOptional.get().getBindingSid().getConfig(); + if (config.getType() == DataplaneType.Srv6 && config.getValue() != null && + config.getValue().getIpAddress() != null && + config.getValue().getIpAddress().getIpv6Address() != null) { + return config.getValue().getIpAddress().getIpv6Address(); + } + } + return null; + } + + /** + * Extracts VRF FIB from Policy. + * + * @param instanceIdentifier identifier used to extract path of policy + * @param writeContext used to store any useful information later utilized by customizers + * @param isWrite condition whether this is a write or delete operation + * @return VRF FIB id when resolved, default VRF FIB (0) otherwise + */ + public static int extractVrfFib(final @Nonnull InstanceIdentifier instanceIdentifier, + final @Nonnull WriteContext writeContext, boolean isWrite) { + Optional policyOptional = isWrite + ? writeContext.readAfter(RWUtils.cutId(instanceIdentifier, Policy.class)) + : writeContext.readBefore(RWUtils.cutId(instanceIdentifier, Policy.class)); + + if (policyOptional.isPresent() && policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class) != null && + policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class).getVppSrPolicy() != null) { + + VppSrPolicy vppSrPolicy = + policyOptional.get().getAugmentation(VppSrPolicyAugmentation.class).getVppSrPolicy(); + if (vppSrPolicy.getConfig() != null && vppSrPolicy.getConfig().getTableId() != null) { + return vppSrPolicy.getConfig().getTableId().getValue().intValue(); + } + } + // returning default Vrf Fib table + return 0; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java index 551a211dd..5321bffcf 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/util/function/xconnect/EndDX2FunctionBinder.java @@ -52,6 +52,8 @@ public class EndDX2FunctionBinder extends XConnectFunctionBinder { "Failed to map data: {} for request: {}", data, request); request.setOutgoingInterfaceIndex(getInterfaceIndex(ctx.getMappingContext(), outInterface)); request.setFunction(getBehaviourFunctionType()); + // TODO (HC2VPP-357): check model for ENDDX2V support, when added we can set the VLAN index + // request.setVlanIndex(getVLanIndex(ctx.getMappingContext(), )); return request; } diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java new file mode 100644 index 000000000..87e07d216 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.srv6.Srv6PolicyIIds; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.hc2vpp.srv6.util.NoopCustomizer; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.hc2vpp.srv6.write.policy.PolicyCustomizer; +import io.fd.hc2vpp.srv6.write.steering.InterfacesConfigCustomizer; +import io.fd.hc2vpp.srv6.write.steering.PrefixCustomizer; +import io.fd.hc2vpp.srv6.write.steering.PrefixesConfigCustomizer; +import io.fd.honeycomb.translate.impl.write.GenericListWriter; +import io.fd.honeycomb.translate.impl.write.GenericWriter; +import io.fd.honeycomb.translate.write.WriterFactory; +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; + +public class Srv6PolicyWriterFactory implements WriterFactory { + + @Inject + private FutureJVppCore futureJVppCore; + @Inject + @Named("interface-context") + private NamingContext interfaceContext; + @Inject + private LocatorContextManager locatorContext; + @Inject + private PolicyContextManager policyContext; + @Inject + private CandidatePathContextManager candidateContext; + + @Override + public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_IID, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_CFG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS_SG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS_SG_CFG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_BSID, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_BSID_CFG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_CFG, new NoopCustomizer<>())); + + registry.subtreeAdd(ImmutableSet + .of(Srv6PolicyIIds.SR_POLICY_BSID, Srv6PolicyIIds.SR_POLICY_BSID_CFG, + Srv6PolicyIIds.SR_POLICY_VPP, Srv6PolicyIIds.SR_POLICY_VPP_SR, + Srv6PolicyIIds.SR_POLICY_VPP_SR_CFG, Srv6PolicyIIds.SR_POLICY_CFG, + Srv6PolicyIIds.SR_POLICY_CPS, Srv6PolicyIIds.SR_POLICY_CPS_CP, + Srv6PolicyIIds.SR_POLICY_CPS_CP_CFG, Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID, + Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID_CFG, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS, + Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL_CFG), + new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL, + new PolicyCustomizer(futureJVppCore, policyContext, candidateContext))); + + registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_CFG), + new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_IID, + new PrefixCustomizer(futureJVppCore))); + registry.add( + new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_CFG, + new PrefixesConfigCustomizer(futureJVppCore))); + registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_CFG), + new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_IID, + new InterfacesConfigCustomizer(futureJVppCore, interfaceContext))); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java index d9f022970..bb2619755 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java @@ -38,7 +38,7 @@ public class Srv6WriterFactory implements WriterFactory { @Inject private LocalSidFunctionWriteBindingRegistry bindingRegistry; @Inject - protected LocatorContextManager locatorContext; + private LocatorContextManager locatorContext; @Override public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java new file mode 100644 index 000000000..d8e09e84d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.policy; + +import com.google.common.base.Preconditions; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.fib.management.FibManagementIIds; +import io.fd.hc2vpp.srv6.Srv6PolicyIIds; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.policy.request.PolicyDeleteRequest; +import io.fd.hc2vpp.srv6.write.policy.request.PolicyWriteRequest; +import io.fd.hc2vpp.srv6.write.policy.request.dto.SidList; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.BindingSidAllocMode; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodConfig; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.VniReference; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.TableKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +public class PolicyCustomizer extends FutureJVppCustomizer + implements ListWriterCustomizer { + + private final PolicyContextManager policyContext; + private final CandidatePathContextManager candidateContext; + + public PolicyCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final PolicyContextManager policyContext, + @Nonnull final CandidatePathContextManager candidateContext) { + super(futureJVppCore); + this.policyContext = policyContext; + this.candidateContext = candidateContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Policy policy, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + try { + // Fib table must be created beforehand. First we check if all data is present, then we verify the existence + // of FIB table in current configuration + VppSrPolicyAugmentation policyAugmentation = policy.getAugmentation(VppSrPolicyAugmentation.class); + + if (policyAugmentation != null && policyAugmentation.getVppSrPolicy() != null && + policyAugmentation.getVppSrPolicy().getConfig() != null) { + Config config = policyAugmentation.getVppSrPolicy().getConfig(); + TableKey tableKey = new TableKey(config.getAddressFamily(), new VniReference(config.getTableId())); + KeyedInstanceIdentifier vrfIid = + FibManagementIIds.FM_FIB_TABLES.child(Table.class, tableKey); + if (!writeContext.readAfter(vrfIid).isPresent()) { + throw new IllegalArgumentException( + String.format("VRF table: %s not found. Create table before writing policy.", tableKey)); + } + if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) { + bindWriteRequest(config, policy.getCandidatePaths().getCandidatePath(), writeContext) + .write(instanceIdentifier); + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, true); + policyContext.addPolicy(policy.getName(), policy.getColor(), policy.getEndpoint().getIpv6Address(), + bsid, writeContext.getMappingContext()); + } + } else { + throw new ReadFailedException(instanceIdentifier, + new Throwable("VppSrPolicyAugmentation and/or VppSrPolicy missing.")); + } + } catch (ReadFailedException e) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, policy, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Policy policy, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) { + bindDeleteRequest(policy.getCandidatePaths().getCandidatePath(), writeContext).delete(instanceIdentifier); + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, false); + Preconditions.checkNotNull(bsid, "BSID must not be null"); + policyContext.removePolicy(bsid, writeContext.getMappingContext()); + } + } + + private PolicyDeleteRequest bindDeleteRequest(final @Nonnull List candidatePaths, + final @Nonnull WriteContext writeContext) { + final PolicyDeleteRequest request = new PolicyDeleteRequest(getFutureJVpp()); + + Optional candidatePathOptional = parseBestCandidate(candidatePaths); + Preconditions.checkArgument(candidatePathOptional.isPresent(), + "Could not parse best Candidate path from list: {}", candidatePaths); + + CandidatePath selectedPath = candidatePathOptional.get(); + if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + sidConfig = selectedPath.getBindingSid().getConfig(); + + if (sidConfig.getType() == DataplaneType.Srv6 && + sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null && + sidConfig.getValue().getIpAddress() != null && + sidConfig.getValue().getIpAddress().getIpv6Address() != null) { + Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address(); + request.setBindingSidAddress(bsid); + candidateContext.removeCandidatePath(bsid, writeContext.getMappingContext()); + } + } + return request; + } + + private PolicyWriteRequest bindWriteRequest(@Nonnull final Config config, + final List candidatePaths, + final WriteContext writeContext) { + final PolicyWriteRequest request = new PolicyWriteRequest(getFutureJVpp()); + request.setFibTableIndex(config.getTableId().getValue().intValue()); + request.setPolicyBehavior(config.getPolicyBehavior()); + request.setPolicyType(config.getPolicyType()); + + Optional candidatePathOptional = parseBestCandidate(candidatePaths); + Preconditions.checkArgument(candidatePathOptional.isPresent(), + "Could not parse best Candidate path from list: {}", candidatePaths); + + CandidatePath selectedPath = candidatePathOptional.get(); + if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + sidConfig = selectedPath.getBindingSid().getConfig(); + + if (sidConfig.getType() == DataplaneType.Srv6 && + sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null && + sidConfig.getValue().getIpAddress() != null && + sidConfig.getValue().getIpAddress().getIpv6Address() != null) { + Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address(); + request.setBindingSidAddress(bsid); + candidateContext.addCandidatePath(bsid, selectedPath.getName(), selectedPath.getProvisioningMethod(), + selectedPath.getPreference(), selectedPath.getDistinguisher(), + writeContext.getMappingContext()); + } + } + if (selectedPath.getSegmentLists() != null && selectedPath.getSegmentLists().getSegmentList() != null) { + request.setSegments(readSegmentLists(selectedPath.getSegmentLists().getSegmentList(), writeContext)); + } + + return request; + } + + private List readSegmentLists(final List segmentLists, final WriteContext writeContext) { + List sidLists = new ArrayList<>(); + + segmentLists.forEach(segmentList -> { + com.google.common.base.Optional namedSegmentListOptional = writeContext.readAfter( + Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, + new NamedSegmentListKey(segmentList.getName()))); + + if (namedSegmentListOptional.isPresent()) { + sidLists.add(SidList.builder() + .setNamedSegmentList(namedSegmentListOptional.get()) + .setWeight(segmentList.getConfig().getWeight()) + .build()); + } + }); + return sidLists; + } + + /** + * Selects best Candidate based on Preference value (the higher preference the better), + * only static configuration is supported for now (provisioning-method must be equal to provisioning-method-config). + * + * Based on Segment Routing Policy for Traffic Engineering + * https://tools.ietf.org/html/draft-filsfils-spring-segment-routing-policy-00 + * + * @param candidatePaths List of available CandidatePaths + * @return Optional of CandidatePath + */ + private Optional parseBestCandidate(final List candidatePaths) { + return candidatePaths.stream() + .filter(candidatePath -> candidatePath.getProvisioningMethod().equals(ProvisioningMethodConfig.class)) + .max(Comparator.comparingLong(CandidatePath::getPreference)); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java new file mode 100644 index 000000000..71b9d72e8 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.policy.request; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.hc2vpp.srv6.write.DeleteRequest; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrPolicyDel; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import io.fd.vpp.jvpp.core.types.Srv6Sid; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PolicyDeleteRequest extends JVppRequest implements DeleteRequest { + + /** + * Binding SID of the policy + */ + private Ipv6Address bindingSidAddress; + + public PolicyDeleteRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + checkNotNull(bindingSidAddress, "Binding sid address not set"); + } + + @Override + public void delete(final InstanceIdentifier identifier) throws WriteFailedException { + checkValid(); + final SrPolicyDel request = new SrPolicyDel(); + Srv6Sid bsid = new Srv6Sid(); + bsid.addr = ipv6AddressNoZoneToArray(bindingSidAddress); + request.bsidAddr = bsid; + getReplyForDelete(getApi().srPolicyDel(request).toCompletableFuture(), identifier); + } + + public void setBindingSidAddress( + final Ipv6Address bindingSidAddress) { + this.bindingSidAddress = bindingSidAddress; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java new file mode 100644 index 000000000..6dc3e867d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.policy.request; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import io.fd.hc2vpp.common.translate.util.AddressTranslator; +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.hc2vpp.srv6.write.WriteRequest; +import io.fd.hc2vpp.srv6.write.policy.request.dto.SidList; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrPolicyAdd; +import io.fd.vpp.jvpp.core.dto.SrPolicyMod; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import io.fd.vpp.jvpp.core.types.Srv6Sid; +import io.fd.vpp.jvpp.core.types.Srv6SidList; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.Segments; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.Segment; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyBehavior; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PolicyWriteRequest extends JVppRequest implements WriteRequest { + + /** + * Types of modification operations + */ + private static final int ADD_NEW = 1; + private static final int DELETE_EXISTING = 2; + private static final int MODIFY_WEIGHT = 3; + + private static final Logger LOG = LoggerFactory.getLogger(PolicyWriteRequest.class); + + /** + * Binding SID of the policy + */ + private Ipv6Address bindingSidAddress; + + /** + * Behavior used by this policy. Either inserts to existing header or encapsulate to new one + */ + private SegmentRoutingPolicyBehavior policyBehavior; + + /** + * Revelant if multiple segment lists are used. Default is load-balancing, spray will send traffic to every segment + */ + private SegmentRoutingPolicyType policyType; + + /** + * FIB table where entry should be installed + */ + private int fibTableIndex; + + /** + * List of SidList + */ + private List segments; + + public PolicyWriteRequest(final FutureJVppCore api) { + super(api); + } + + private static Srv6Sid[] convertSegmentsToByteArray(final Segments segments) { + List sidList = new ArrayList<>(); + segments.getSegment().stream().sorted(Comparator.comparingLong(Segment::getIndex)) + .map(segment -> segment.getConfig().getSidValue().getIpAddress().getIpv6Address()) + .forEach(ipv6Address -> { + Srv6Sid sid = new Srv6Sid(); + sid.addr = AddressTranslator.INSTANCE.ipv6AddressNoZoneToArray(ipv6Address); + sidList.add(sid); + }); + return sidList.toArray(new Srv6Sid[0]); + } + + @Override + public void write(final InstanceIdentifier identifier) throws WriteFailedException { + checkValid(); + + final SrPolicyAdd createRequest = new SrPolicyAdd(); + createRequest.bsidAddr = ipv6AddressNoZoneToArray(bindingSidAddress); + createRequest.isEncap = (byte) policyBehavior.getIntValue(); + createRequest.type = (byte) policyType.getIntValue(); + createRequest.fibTable = fibTableIndex; + + SidList firstSidList = segments.get(0); + + createRequest.sids = new Srv6SidList(); + createRequest.sids.numSids = (byte) firstSidList.getNamedSegmentList().getSegments().getSegment().size(); + createRequest.sids.sids = convertSegmentsToByteArray(firstSidList.getNamedSegmentList().getSegments()); + createRequest.sids.weight = firstSidList.getWeight().intValue(); + + LOG.info("Writing policy {}", createRequest); + getReplyForWrite(getApi().srPolicyAdd(createRequest).toCompletableFuture(), identifier); + + if (segments.size() > 1) { + LOG.info("Multiple segments detected for policy, modifying"); + segments.stream() + .skip(1) + .map(policySegments -> { + SrPolicyMod modifyRequest = new SrPolicyMod(); + modifyRequest.bsidAddr = createRequest.bsidAddr; + modifyRequest.operation = ADD_NEW;// add new segment list + modifyRequest.fibTable = fibTableIndex; + modifyRequest.sids = new Srv6SidList(); + modifyRequest.sids.numSids = + (byte) policySegments.getNamedSegmentList().getSegments().getSegment().size(); + modifyRequest.sids.sids = + convertSegmentsToByteArray(policySegments.getNamedSegmentList().getSegments()); + modifyRequest.sids.weight = policySegments.getWeight().intValue(); + return modifyRequest; + }) + .peek(modifyRequest -> LOG.info("Adding additional segment list for policy {} / request {}", + bindingSidAddress.getValue(), modifyRequest)) + .forEach(modifyRequest -> { + try { + getReplyForWrite(getApi().srPolicyMod(modifyRequest).toCompletableFuture(), identifier); + } catch (WriteFailedException e) { + throw new IllegalStateException(e); + } + }); + } + } + + @Override + public void checkValid() { + checkNotNull(bindingSidAddress, "Binding sid address not set"); + checkNotNull(policyBehavior, "Policy behavior not set"); + checkNotNull(policyType, "Policy type not set"); + if (policyBehavior != SegmentRoutingPolicyBehavior.Encapsulation) { + checkNotNull(segments, "Segments not set"); + checkState(!segments.isEmpty(), "No segments set"); + } + } + + public void setBindingSidAddress( + final Ipv6Address bindingSidAddress) { + this.bindingSidAddress = bindingSidAddress; + } + + public void setPolicyBehavior( + final SegmentRoutingPolicyBehavior policyBehavior) { + this.policyBehavior = policyBehavior; + } + + public void setPolicyType( + final SegmentRoutingPolicyType policyType) { + this.policyType = policyType; + } + + public void setFibTableIndex(final int fibTableIndex) { + this.fibTableIndex = fibTableIndex; + } + + public void setSegments(final List segments) { + this.segments = segments; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java new file mode 100644 index 000000000..129c20e2d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.policy.request.dto; + +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList; + +public class SidList { + private Long weight; + private NamedSegmentList namedSegmentList; + + private SidList(final SidListBuilder builder) { + weight = builder.weight; + namedSegmentList = builder.namedSegmentList; + } + + public static SidListBuilder builder() { + return new SidListBuilder(); + } + + public Long getWeight() { + return weight; + } + + public NamedSegmentList getNamedSegmentList() { + return namedSegmentList; + } + + public static final class SidListBuilder { + private Long weight; + private NamedSegmentList namedSegmentList; + + private SidListBuilder() { + } + + public SidListBuilder setWeight(final Long weight) { + this.weight = weight; + return this; + } + + public SidListBuilder setNamedSegmentList(final NamedSegmentList namedSegmentList) { + this.namedSegmentList = namedSegmentList; + return this; + } + + public SidList build() { + return new SidList(this); + } + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java new file mode 100644 index 000000000..67ad9d56c --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.steering.request.L2SteeringRequest; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class InterfacesConfigCustomizer extends FutureJVppCustomizer implements + ListWriterCustomizer { + private final NamingContext interfaceContext; + + public InterfacesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore); + this.interfaceContext = interfaceContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (anInterface.getConfig() != null) { + writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, true); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (anInterface.getConfig() != null) { + writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, false); + } + } + + private void writeInterfaces(final @Nonnull InstanceIdentifier instanceIdentifier, + final @Nonnull Config config, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, config, + new Throwable("Failed to extract BSID from policy for prefix")); + } + if (config.getInputInterface() != null) { + // forward all traffic to policy for current interface + int index = interfaceContext.getIndex(config.getInputInterface(), writeContext.getMappingContext()); + sendL2Steering(instanceIdentifier, bsid, index, getFutureJVpp(), isWrite); + } + } + + private void sendL2Steering(final InstanceIdentifier instanceIdentifier, final Ipv6Address bsid, + final int inputInterface, final FutureJVppCore api, final boolean isWrite) + throws WriteFailedException { + L2SteeringRequest request = new L2SteeringRequest(api); + request.setBindingSid(bsid); + request.setInputInterfaceIndex(inputInterface); + if (isWrite) { + request.write(instanceIdentifier); + } else { + request.delete(instanceIdentifier); + } + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java new file mode 100644 index 000000000..7973c3203 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.steering.request.L3SteeringRequest; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PrefixCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer { + + public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Prefix prefix, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, prefix, writeContext, true).write(instanceIdentifier); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Prefix prefix, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, prefix, writeContext, false).delete(instanceIdentifier); + } + + private L3SteeringRequest writePrefixes(final @Nonnull InstanceIdentifier instanceIdentifier, + final @Nonnull Prefix prefix, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, prefix, + new Throwable("Failed to extract BSID from policy for prefix")); + } + // forward only desired traffic to policy + L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp()); + request.setBindingSid(bsid); + request.setPrefix(prefix.getIpPrefix()); + request.setFibTableIndex(vrfFib); + return request; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java new file mode 100644 index 000000000..e366db3a3 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.steering.request.L3SteeringRequest; +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PrefixesConfigCustomizer extends FutureJVppCustomizer implements WriterCustomizer { + + private static final IpPrefix + DEFAULT_IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("::/0")); + private static final IpPrefix + DEFAULT_IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("0.0.0.0/0")); + + public PrefixesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + private void writePrefixes(final @Nonnull InstanceIdentifier instanceIdentifier, + final @Nonnull Config config, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, config, + new Throwable("Failed to extract BSID from policy for prefix")); + } + if (config.isPrefixesAll()) { + // forward all traffic to policy + writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV6_PREFIX, bsid, getFutureJVpp(), isWrite); + writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV4_PREFIX, bsid, getFutureJVpp(), isWrite); + } + } + + private void writeL3Steering(int vrfFib, InstanceIdentifier instanceIdentifier, IpPrefix ipPrefix, + final Ipv6Address bsid, FutureJVppCore api, boolean isWrite) + throws WriteFailedException { + L3SteeringRequest request = new L3SteeringRequest(api); + request.setBindingSid(bsid); + request.setPrefix(ipPrefix); + request.setFibTableIndex(vrfFib); + if (isWrite) { + request.write(instanceIdentifier); + } else { + request.delete(instanceIdentifier); + } + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Config config, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, config, writeContext, true); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier instanceIdentifier, + @Nonnull final Config config, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, config, writeContext, false); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java new file mode 100644 index 000000000..960d17bb9 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.steering.request; + +import io.fd.hc2vpp.srv6.write.DeleteRequest; +import io.fd.hc2vpp.srv6.write.WriteRequest; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Request for steering of L2 traffic + */ +public class L2SteeringRequest extends SteeringRequest implements WriteRequest, DeleteRequest { + + private static final int L2_TRAFFIC_TYPE = 2; + + /** + * Incoming interface for traffic + */ + private int inputInterfaceIndex; + + public L2SteeringRequest(final FutureJVppCore api) { + super(api); + } + + + @Override + public void delete(final InstanceIdentifier identifier) throws WriteFailedException { + getReplyForDelete(getApi().srSteeringAddDel(bindRequest(true)).toCompletableFuture(), identifier); + } + + @Override + public void write(final InstanceIdentifier identifier) throws WriteFailedException { + getReplyForWrite(getApi().srSteeringAddDel(bindRequest(false)).toCompletableFuture(), identifier); + } + + private SrSteeringAddDel bindRequest(final boolean isDel) { + final SrSteeringAddDel request = new SrSteeringAddDel(); + request.isDel = booleanToByte(isDel); + request.bsidAddr = ipv6AddressNoZoneToArray(getBindingSid()); + request.swIfIndex = inputInterfaceIndex; + request.trafficType = L2_TRAFFIC_TYPE; + return request; + } + + public void setInputInterfaceIndex(final int inputInterfaceIndex) { + this.inputInterfaceIndex = inputInterfaceIndex; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java new file mode 100644 index 000000000..850234c41 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.steering.request; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.hc2vpp.srv6.write.DeleteRequest; +import io.fd.hc2vpp.srv6.write.WriteRequest; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Request for steering of L3 traffic + */ +public class L3SteeringRequest extends SteeringRequest implements WriteRequest, DeleteRequest { + + public static final byte VPP_IPV4_TYPE = 4; + public static final byte VPP_IPV6_TYPE = 6; + public static final byte VPP_UNRESOLVED_TYPE = 0; + /** + * Where to install FIB entry for this steering + */ + private int fibTableIndex; + + /** + * V4/V6 address for traffic type + */ + private IpPrefix prefix; + + public L3SteeringRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + super.checkValid(); + checkNotNull(prefix, "Prefix is null"); + checkArgument(resolveTrafficType(prefix) == 4 || resolveTrafficType(prefix) == 6, + "IpPrefix format not recognized"); + } + + @Override + public void delete(final InstanceIdentifier identifier) throws WriteFailedException { + checkValid(); + getReplyForDelete(getApi().srSteeringAddDel(bindRequest(true)).toCompletableFuture(), identifier); + } + + @Override + public void write(final InstanceIdentifier identifier) throws WriteFailedException { + checkValid(); + getReplyForWrite(getApi().srSteeringAddDel(bindRequest(false)).toCompletableFuture(), identifier); + } + + private SrSteeringAddDel bindRequest(final boolean isDel) { + final SrSteeringAddDel request = new SrSteeringAddDel(); + request.isDel = booleanToByte(isDel); + request.bsidAddr = ipv6AddressNoZoneToArray(getBindingSid()); + request.tableId = fibTableIndex; + request.trafficType = resolveTrafficType(prefix); + request.prefixAddr = ipPrefixToArray(prefix); + request.maskWidth = extractPrefix(prefix); + return request; + } + + public void setFibTableIndex(final int fibTableIndex) { + this.fibTableIndex = fibTableIndex; + } + + private byte resolveTrafficType(IpPrefix prefix) { + if (prefix.getIpv4Prefix() != null) { + return VPP_IPV4_TYPE; + } else if (prefix.getIpv6Prefix() != null) { + return VPP_IPV6_TYPE; + } + return VPP_UNRESOLVED_TYPE; + } + + public void setPrefix(final IpPrefix prefix) { + this.prefix = prefix; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java new file mode 100644 index 000000000..2078ade5b --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.steering.request; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; + +/** + * General template for steering requests + */ +public abstract class SteeringRequest extends JVppRequest { + + /** + * Binding SID of policy that should be applied for this traffic + */ + private Ipv6Address bindingSid; + + SteeringRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + checkNotNull(bindingSid, "Binding SID is null"); + } + + Ipv6Address getBindingSid() { + return bindingSid; + } + + public void setBindingSid( + final Ipv6Address bindingSid) { + this.bindingSid = bindingSid; + } +} -- cgit 1.2.3-korg