diff options
Diffstat (limited to 'srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write')
12 files changed, 1072 insertions, 1 deletions
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java new file mode 100644 index 000000000..87e07d216 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6PolicyWriterFactory.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write; + +import com.google.common.collect.ImmutableSet; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.srv6.Srv6PolicyIIds; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.hc2vpp.srv6.util.NoopCustomizer; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.hc2vpp.srv6.write.policy.PolicyCustomizer; +import io.fd.hc2vpp.srv6.write.steering.InterfacesConfigCustomizer; +import io.fd.hc2vpp.srv6.write.steering.PrefixCustomizer; +import io.fd.hc2vpp.srv6.write.steering.PrefixesConfigCustomizer; +import io.fd.honeycomb.translate.impl.write.GenericListWriter; +import io.fd.honeycomb.translate.impl.write.GenericWriter; +import io.fd.honeycomb.translate.write.WriterFactory; +import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; + +public class Srv6PolicyWriterFactory implements WriterFactory { + + @Inject + private FutureJVppCore futureJVppCore; + @Inject + @Named("interface-context") + private NamingContext interfaceContext; + @Inject + private LocatorContextManager locatorContext; + @Inject + private PolicyContextManager policyContext; + @Inject + private CandidatePathContextManager candidateContext; + + @Override + public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_IID, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_CFG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS_SG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_NSLS_NSL_SGS_SG_CFG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_BSID, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_BSID_CFG, new NoopCustomizer<>())); + registry.add(new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_CFG, new NoopCustomizer<>())); + + registry.subtreeAdd(ImmutableSet + .of(Srv6PolicyIIds.SR_POLICY_BSID, Srv6PolicyIIds.SR_POLICY_BSID_CFG, + Srv6PolicyIIds.SR_POLICY_VPP, Srv6PolicyIIds.SR_POLICY_VPP_SR, + Srv6PolicyIIds.SR_POLICY_VPP_SR_CFG, Srv6PolicyIIds.SR_POLICY_CFG, + Srv6PolicyIIds.SR_POLICY_CPS, Srv6PolicyIIds.SR_POLICY_CPS_CP, + Srv6PolicyIIds.SR_POLICY_CPS_CP_CFG, Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID, + Srv6PolicyIIds.SR_POLICY_CPS_CP_BSID_CFG, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS, + Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL, Srv6PolicyIIds.SR_POLICY_CPS_CP_SLS_SL_CFG), + new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL, + new PolicyCustomizer(futureJVppCore, policyContext, candidateContext))); + + registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_CFG), + new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_PF_IID, + new PrefixCustomizer(futureJVppCore))); + registry.add( + new GenericWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_PFS_CFG, + new PrefixesConfigCustomizer(futureJVppCore))); + registry.subtreeAdd(ImmutableSet.of(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_CFG), + new GenericListWriter<>(Srv6PolicyIIds.SR_TE_PLS_POL_AI_IFCS_IFC_IID, + new InterfacesConfigCustomizer(futureJVppCore, interfaceContext))); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java index d9f022970..bb2619755 100644 --- a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/Srv6WriterFactory.java @@ -38,7 +38,7 @@ public class Srv6WriterFactory implements WriterFactory { @Inject private LocalSidFunctionWriteBindingRegistry bindingRegistry; @Inject - protected LocatorContextManager locatorContext; + private LocatorContextManager locatorContext; @Override public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) { diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java new file mode 100644 index 000000000..d8e09e84d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/PolicyCustomizer.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.policy; + +import com.google.common.base.Preconditions; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.fib.management.FibManagementIIds; +import io.fd.hc2vpp.srv6.Srv6PolicyIIds; +import io.fd.hc2vpp.srv6.util.CandidatePathContextManager; +import io.fd.hc2vpp.srv6.util.PolicyContextManager; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.policy.request.PolicyDeleteRequest; +import io.fd.hc2vpp.srv6.write.policy.request.PolicyWriteRequest; +import io.fd.hc2vpp.srv6.write.policy.request.dto.SidList; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.BindingSidAllocMode; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.DataplaneType; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.ProvisioningMethodConfig; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.candidate.paths.candidate.paths.CandidatePath; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentListKey; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.path.segment.list.properties.segment.lists.SegmentList; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.Policy; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.policies.policies.PolicyKey; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.VppSrPolicyAugmentation; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.policy.Config; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.VniReference; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.Table; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.fib.table.management.rev180521.vpp.fib.table.management.fib.tables.TableKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +public class PolicyCustomizer extends FutureJVppCustomizer + implements ListWriterCustomizer<Policy, PolicyKey> { + + private final PolicyContextManager policyContext; + private final CandidatePathContextManager candidateContext; + + public PolicyCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final PolicyContextManager policyContext, + @Nonnull final CandidatePathContextManager candidateContext) { + super(futureJVppCore); + this.policyContext = policyContext; + this.candidateContext = candidateContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> instanceIdentifier, + @Nonnull final Policy policy, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + try { + // Fib table must be created beforehand. First we check if all data is present, then we verify the existence + // of FIB table in current configuration + VppSrPolicyAugmentation policyAugmentation = policy.getAugmentation(VppSrPolicyAugmentation.class); + + if (policyAugmentation != null && policyAugmentation.getVppSrPolicy() != null && + policyAugmentation.getVppSrPolicy().getConfig() != null) { + Config config = policyAugmentation.getVppSrPolicy().getConfig(); + TableKey tableKey = new TableKey(config.getAddressFamily(), new VniReference(config.getTableId())); + KeyedInstanceIdentifier<Table, TableKey> vrfIid = + FibManagementIIds.FM_FIB_TABLES.child(Table.class, tableKey); + if (!writeContext.readAfter(vrfIid).isPresent()) { + throw new IllegalArgumentException( + String.format("VRF table: %s not found. Create table before writing policy.", tableKey)); + } + if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) { + bindWriteRequest(config, policy.getCandidatePaths().getCandidatePath(), writeContext) + .write(instanceIdentifier); + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, true); + policyContext.addPolicy(policy.getName(), policy.getColor(), policy.getEndpoint().getIpv6Address(), + bsid, writeContext.getMappingContext()); + } + } else { + throw new ReadFailedException(instanceIdentifier, + new Throwable("VppSrPolicyAugmentation and/or VppSrPolicy missing.")); + } + } catch (ReadFailedException e) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, policy, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policy> instanceIdentifier, + @Nonnull final Policy policy, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (policy.getCandidatePaths() != null && !policy.getCandidatePaths().getCandidatePath().isEmpty()) { + bindDeleteRequest(policy.getCandidatePaths().getCandidatePath(), writeContext).delete(instanceIdentifier); + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, false); + Preconditions.checkNotNull(bsid, "BSID must not be null"); + policyContext.removePolicy(bsid, writeContext.getMappingContext()); + } + } + + private PolicyDeleteRequest bindDeleteRequest(final @Nonnull List<CandidatePath> candidatePaths, + final @Nonnull WriteContext writeContext) { + final PolicyDeleteRequest request = new PolicyDeleteRequest(getFutureJVpp()); + + Optional<CandidatePath> candidatePathOptional = parseBestCandidate(candidatePaths); + Preconditions.checkArgument(candidatePathOptional.isPresent(), + "Could not parse best Candidate path from list: {}", candidatePaths); + + CandidatePath selectedPath = candidatePathOptional.get(); + if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + sidConfig = selectedPath.getBindingSid().getConfig(); + + if (sidConfig.getType() == DataplaneType.Srv6 && + sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null && + sidConfig.getValue().getIpAddress() != null && + sidConfig.getValue().getIpAddress().getIpv6Address() != null) { + Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address(); + request.setBindingSidAddress(bsid); + candidateContext.removeCandidatePath(bsid, writeContext.getMappingContext()); + } + } + return request; + } + + private PolicyWriteRequest bindWriteRequest(@Nonnull final Config config, + final List<CandidatePath> candidatePaths, + final WriteContext writeContext) { + final PolicyWriteRequest request = new PolicyWriteRequest(getFutureJVpp()); + request.setFibTableIndex(config.getTableId().getValue().intValue()); + request.setPolicyBehavior(config.getPolicyBehavior()); + request.setPolicyType(config.getPolicyType()); + + Optional<CandidatePath> candidatePathOptional = parseBestCandidate(candidatePaths); + Preconditions.checkArgument(candidatePathOptional.isPresent(), + "Could not parse best Candidate path from list: {}", candidatePaths); + + CandidatePath selectedPath = candidatePathOptional.get(); + if (selectedPath.getBindingSid() != null && selectedPath.getBindingSid().getConfig() != null) { + org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.binding.sid.properties.binding.sid.Config + sidConfig = selectedPath.getBindingSid().getConfig(); + + if (sidConfig.getType() == DataplaneType.Srv6 && + sidConfig.getAllocMode() == BindingSidAllocMode.Explicit && sidConfig.getValue() != null && + sidConfig.getValue().getIpAddress() != null && + sidConfig.getValue().getIpAddress().getIpv6Address() != null) { + Ipv6Address bsid = selectedPath.getBindingSid().getConfig().getValue().getIpAddress().getIpv6Address(); + request.setBindingSidAddress(bsid); + candidateContext.addCandidatePath(bsid, selectedPath.getName(), selectedPath.getProvisioningMethod(), + selectedPath.getPreference(), selectedPath.getDistinguisher(), + writeContext.getMappingContext()); + } + } + if (selectedPath.getSegmentLists() != null && selectedPath.getSegmentLists().getSegmentList() != null) { + request.setSegments(readSegmentLists(selectedPath.getSegmentLists().getSegmentList(), writeContext)); + } + + return request; + } + + private List<SidList> readSegmentLists(final List<SegmentList> segmentLists, final WriteContext writeContext) { + List<SidList> sidLists = new ArrayList<>(); + + segmentLists.forEach(segmentList -> { + com.google.common.base.Optional<NamedSegmentList> namedSegmentListOptional = writeContext.readAfter( + Srv6PolicyIIds.SR_TE_NSLS.child(NamedSegmentList.class, + new NamedSegmentListKey(segmentList.getName()))); + + if (namedSegmentListOptional.isPresent()) { + sidLists.add(SidList.builder() + .setNamedSegmentList(namedSegmentListOptional.get()) + .setWeight(segmentList.getConfig().getWeight()) + .build()); + } + }); + return sidLists; + } + + /** + * Selects best Candidate based on Preference value (the higher preference the better), + * only static configuration is supported for now (provisioning-method must be equal to provisioning-method-config). + * + * Based on Segment Routing Policy for Traffic Engineering + * https://tools.ietf.org/html/draft-filsfils-spring-segment-routing-policy-00 + * + * @param candidatePaths List of available CandidatePaths + * @return Optional of CandidatePath + */ + private Optional<CandidatePath> parseBestCandidate(final List<CandidatePath> candidatePaths) { + return candidatePaths.stream() + .filter(candidatePath -> candidatePath.getProvisioningMethod().equals(ProvisioningMethodConfig.class)) + .max(Comparator.comparingLong(CandidatePath::getPreference)); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java new file mode 100644 index 000000000..71b9d72e8 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyDeleteRequest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.policy.request; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.hc2vpp.srv6.write.DeleteRequest; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrPolicyDel; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import io.fd.vpp.jvpp.core.types.Srv6Sid; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PolicyDeleteRequest extends JVppRequest implements DeleteRequest { + + /** + * Binding SID of the policy + */ + private Ipv6Address bindingSidAddress; + + public PolicyDeleteRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + checkNotNull(bindingSidAddress, "Binding sid address not set"); + } + + @Override + public void delete(final InstanceIdentifier<?> identifier) throws WriteFailedException { + checkValid(); + final SrPolicyDel request = new SrPolicyDel(); + Srv6Sid bsid = new Srv6Sid(); + bsid.addr = ipv6AddressNoZoneToArray(bindingSidAddress); + request.bsidAddr = bsid; + getReplyForDelete(getApi().srPolicyDel(request).toCompletableFuture(), identifier); + } + + public void setBindingSidAddress( + final Ipv6Address bindingSidAddress) { + this.bindingSidAddress = bindingSidAddress; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java new file mode 100644 index 000000000..6dc3e867d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/PolicyWriteRequest.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.policy.request; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import io.fd.hc2vpp.common.translate.util.AddressTranslator; +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.hc2vpp.srv6.write.WriteRequest; +import io.fd.hc2vpp.srv6.write.policy.request.dto.SidList; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrPolicyAdd; +import io.fd.vpp.jvpp.core.dto.SrPolicyMod; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import io.fd.vpp.jvpp.core.types.Srv6Sid; +import io.fd.vpp.jvpp.core.types.Srv6SidList; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.Segments; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.named.segment.list.segments.Segment; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyBehavior; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.SegmentRoutingPolicyType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PolicyWriteRequest extends JVppRequest implements WriteRequest { + + /** + * Types of modification operations + */ + private static final int ADD_NEW = 1; + private static final int DELETE_EXISTING = 2; + private static final int MODIFY_WEIGHT = 3; + + private static final Logger LOG = LoggerFactory.getLogger(PolicyWriteRequest.class); + + /** + * Binding SID of the policy + */ + private Ipv6Address bindingSidAddress; + + /** + * Behavior used by this policy. Either inserts to existing header or encapsulate to new one + */ + private SegmentRoutingPolicyBehavior policyBehavior; + + /** + * Revelant if multiple segment lists are used. Default is load-balancing, spray will send traffic to every segment + */ + private SegmentRoutingPolicyType policyType; + + /** + * FIB table where entry should be installed + */ + private int fibTableIndex; + + /** + * List of SidList + */ + private List<SidList> segments; + + public PolicyWriteRequest(final FutureJVppCore api) { + super(api); + } + + private static Srv6Sid[] convertSegmentsToByteArray(final Segments segments) { + List<Srv6Sid> sidList = new ArrayList<>(); + segments.getSegment().stream().sorted(Comparator.comparingLong(Segment::getIndex)) + .map(segment -> segment.getConfig().getSidValue().getIpAddress().getIpv6Address()) + .forEach(ipv6Address -> { + Srv6Sid sid = new Srv6Sid(); + sid.addr = AddressTranslator.INSTANCE.ipv6AddressNoZoneToArray(ipv6Address); + sidList.add(sid); + }); + return sidList.toArray(new Srv6Sid[0]); + } + + @Override + public void write(final InstanceIdentifier<?> identifier) throws WriteFailedException { + checkValid(); + + final SrPolicyAdd createRequest = new SrPolicyAdd(); + createRequest.bsidAddr = ipv6AddressNoZoneToArray(bindingSidAddress); + createRequest.isEncap = (byte) policyBehavior.getIntValue(); + createRequest.type = (byte) policyType.getIntValue(); + createRequest.fibTable = fibTableIndex; + + SidList firstSidList = segments.get(0); + + createRequest.sids = new Srv6SidList(); + createRequest.sids.numSids = (byte) firstSidList.getNamedSegmentList().getSegments().getSegment().size(); + createRequest.sids.sids = convertSegmentsToByteArray(firstSidList.getNamedSegmentList().getSegments()); + createRequest.sids.weight = firstSidList.getWeight().intValue(); + + LOG.info("Writing policy {}", createRequest); + getReplyForWrite(getApi().srPolicyAdd(createRequest).toCompletableFuture(), identifier); + + if (segments.size() > 1) { + LOG.info("Multiple segments detected for policy, modifying"); + segments.stream() + .skip(1) + .map(policySegments -> { + SrPolicyMod modifyRequest = new SrPolicyMod(); + modifyRequest.bsidAddr = createRequest.bsidAddr; + modifyRequest.operation = ADD_NEW;// add new segment list + modifyRequest.fibTable = fibTableIndex; + modifyRequest.sids = new Srv6SidList(); + modifyRequest.sids.numSids = + (byte) policySegments.getNamedSegmentList().getSegments().getSegment().size(); + modifyRequest.sids.sids = + convertSegmentsToByteArray(policySegments.getNamedSegmentList().getSegments()); + modifyRequest.sids.weight = policySegments.getWeight().intValue(); + return modifyRequest; + }) + .peek(modifyRequest -> LOG.info("Adding additional segment list for policy {} / request {}", + bindingSidAddress.getValue(), modifyRequest)) + .forEach(modifyRequest -> { + try { + getReplyForWrite(getApi().srPolicyMod(modifyRequest).toCompletableFuture(), identifier); + } catch (WriteFailedException e) { + throw new IllegalStateException(e); + } + }); + } + } + + @Override + public void checkValid() { + checkNotNull(bindingSidAddress, "Binding sid address not set"); + checkNotNull(policyBehavior, "Policy behavior not set"); + checkNotNull(policyType, "Policy type not set"); + if (policyBehavior != SegmentRoutingPolicyBehavior.Encapsulation) { + checkNotNull(segments, "Segments not set"); + checkState(!segments.isEmpty(), "No segments set"); + } + } + + public void setBindingSidAddress( + final Ipv6Address bindingSidAddress) { + this.bindingSidAddress = bindingSidAddress; + } + + public void setPolicyBehavior( + final SegmentRoutingPolicyBehavior policyBehavior) { + this.policyBehavior = policyBehavior; + } + + public void setPolicyType( + final SegmentRoutingPolicyType policyType) { + this.policyType = policyType; + } + + public void setFibTableIndex(final int fibTableIndex) { + this.fibTableIndex = fibTableIndex; + } + + public void setSegments(final List<SidList> segments) { + this.segments = segments; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java new file mode 100644 index 000000000..129c20e2d --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/policy/request/dto/SidList.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.policy.request.dto; + +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.named.segment.lists.named.segment.lists.NamedSegmentList; + +public class SidList { + private Long weight; + private NamedSegmentList namedSegmentList; + + private SidList(final SidListBuilder builder) { + weight = builder.weight; + namedSegmentList = builder.namedSegmentList; + } + + public static SidListBuilder builder() { + return new SidListBuilder(); + } + + public Long getWeight() { + return weight; + } + + public NamedSegmentList getNamedSegmentList() { + return namedSegmentList; + } + + public static final class SidListBuilder { + private Long weight; + private NamedSegmentList namedSegmentList; + + private SidListBuilder() { + } + + public SidListBuilder setWeight(final Long weight) { + this.weight = weight; + return this; + } + + public SidListBuilder setNamedSegmentList(final NamedSegmentList namedSegmentList) { + this.namedSegmentList = namedSegmentList; + return this; + } + + public SidList build() { + return new SidList(this); + } + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java new file mode 100644 index 000000000..67ad9d56c --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/InterfacesConfigCustomizer.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.steering.request.L2SteeringRequest; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.oc.srte.policy.rev180514.sr.interfaces._interface.Config; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class InterfacesConfigCustomizer extends FutureJVppCustomizer implements + ListWriterCustomizer<Interface, InterfaceKey> { + private final NamingContext interfaceContext; + + public InterfacesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore); + this.interfaceContext = interfaceContext; + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> instanceIdentifier, + @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (anInterface.getConfig() != null) { + writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, true); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Interface> instanceIdentifier, + @Nonnull final Interface anInterface, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + if (anInterface.getConfig() != null) { + writeInterfaces(instanceIdentifier, anInterface.getConfig(), writeContext, false); + } + } + + private void writeInterfaces(final @Nonnull InstanceIdentifier<Interface> instanceIdentifier, + final @Nonnull Config config, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, config, + new Throwable("Failed to extract BSID from policy for prefix")); + } + if (config.getInputInterface() != null) { + // forward all traffic to policy for current interface + int index = interfaceContext.getIndex(config.getInputInterface(), writeContext.getMappingContext()); + sendL2Steering(instanceIdentifier, bsid, index, getFutureJVpp(), isWrite); + } + } + + private void sendL2Steering(final InstanceIdentifier<Interface> instanceIdentifier, final Ipv6Address bsid, + final int inputInterface, final FutureJVppCore api, final boolean isWrite) + throws WriteFailedException { + L2SteeringRequest request = new L2SteeringRequest(api); + request.setBindingSid(bsid); + request.setInputInterfaceIndex(inputInterface); + if (isWrite) { + request.write(instanceIdentifier); + } else { + request.delete(instanceIdentifier); + } + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java new file mode 100644 index 000000000..7973c3203 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixCustomizer.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.steering.request.L3SteeringRequest; +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Prefix; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.PrefixKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PrefixCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer<Prefix, PrefixKey> { + + public PrefixCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> instanceIdentifier, + @Nonnull final Prefix prefix, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, prefix, writeContext, true).write(instanceIdentifier); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Prefix> instanceIdentifier, + @Nonnull final Prefix prefix, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, prefix, writeContext, false).delete(instanceIdentifier); + } + + private L3SteeringRequest writePrefixes(final @Nonnull InstanceIdentifier<Prefix> instanceIdentifier, + final @Nonnull Prefix prefix, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, prefix, + new Throwable("Failed to extract BSID from policy for prefix")); + } + // forward only desired traffic to policy + L3SteeringRequest request = new L3SteeringRequest(getFutureJVpp()); + request.setBindingSid(bsid); + request.setPrefix(prefix.getIpPrefix()); + request.setFibTableIndex(vrfFib); + return request; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java new file mode 100644 index 000000000..e366db3a3 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/PrefixesConfigCustomizer.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package io.fd.hc2vpp.srv6.write.steering; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.util.Srv6Util; +import io.fd.hc2vpp.srv6.write.steering.request.L3SteeringRequest; +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.cisco.com.ns.yang.oc.srte.policy.rev170918.prefixes.properties.prefixes.Config; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PrefixesConfigCustomizer extends FutureJVppCustomizer implements WriterCustomizer<Config> { + + private static final IpPrefix + DEFAULT_IPV6_PREFIX = new IpPrefix(new Ipv6Prefix("::/0")); + private static final IpPrefix + DEFAULT_IPV4_PREFIX = new IpPrefix(new Ipv4Prefix("0.0.0.0/0")); + + public PrefixesConfigCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + private void writePrefixes(final @Nonnull InstanceIdentifier<Config> instanceIdentifier, + final @Nonnull Config config, final @Nonnull WriteContext writeContext, + final boolean isWrite) + throws WriteFailedException { + Ipv6Address bsid = Srv6Util.extractBsid(instanceIdentifier, writeContext, isWrite); + int vrfFib = Srv6Util.extractVrfFib(instanceIdentifier, writeContext, isWrite); + + if (bsid == null) { + throw new WriteFailedException.CreateFailedException(instanceIdentifier, config, + new Throwable("Failed to extract BSID from policy for prefix")); + } + if (config.isPrefixesAll()) { + // forward all traffic to policy + writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV6_PREFIX, bsid, getFutureJVpp(), isWrite); + writeL3Steering(vrfFib, instanceIdentifier, DEFAULT_IPV4_PREFIX, bsid, getFutureJVpp(), isWrite); + } + } + + private void writeL3Steering(int vrfFib, InstanceIdentifier instanceIdentifier, IpPrefix ipPrefix, + final Ipv6Address bsid, FutureJVppCore api, boolean isWrite) + throws WriteFailedException { + L3SteeringRequest request = new L3SteeringRequest(api); + request.setBindingSid(bsid); + request.setPrefix(ipPrefix); + request.setFibTableIndex(vrfFib); + if (isWrite) { + request.write(instanceIdentifier); + } else { + request.delete(instanceIdentifier); + } + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Config> instanceIdentifier, + @Nonnull final Config config, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, config, writeContext, true); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Config> instanceIdentifier, + @Nonnull final Config config, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + writePrefixes(instanceIdentifier, config, writeContext, false); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java new file mode 100644 index 000000000..960d17bb9 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L2SteeringRequest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.steering.request; + +import io.fd.hc2vpp.srv6.write.DeleteRequest; +import io.fd.hc2vpp.srv6.write.WriteRequest; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Request for steering of L2 traffic + */ +public class L2SteeringRequest extends SteeringRequest implements WriteRequest, DeleteRequest { + + private static final int L2_TRAFFIC_TYPE = 2; + + /** + * Incoming interface for traffic + */ + private int inputInterfaceIndex; + + public L2SteeringRequest(final FutureJVppCore api) { + super(api); + } + + + @Override + public void delete(final InstanceIdentifier<?> identifier) throws WriteFailedException { + getReplyForDelete(getApi().srSteeringAddDel(bindRequest(true)).toCompletableFuture(), identifier); + } + + @Override + public void write(final InstanceIdentifier<?> identifier) throws WriteFailedException { + getReplyForWrite(getApi().srSteeringAddDel(bindRequest(false)).toCompletableFuture(), identifier); + } + + private SrSteeringAddDel bindRequest(final boolean isDel) { + final SrSteeringAddDel request = new SrSteeringAddDel(); + request.isDel = booleanToByte(isDel); + request.bsidAddr = ipv6AddressNoZoneToArray(getBindingSid()); + request.swIfIndex = inputInterfaceIndex; + request.trafficType = L2_TRAFFIC_TYPE; + return request; + } + + public void setInputInterfaceIndex(final int inputInterfaceIndex) { + this.inputInterfaceIndex = inputInterfaceIndex; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java new file mode 100644 index 000000000..850234c41 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/L3SteeringRequest.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.steering.request; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.hc2vpp.srv6.write.DeleteRequest; +import io.fd.hc2vpp.srv6.write.WriteRequest; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.SrSteeringAddDel; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Request for steering of L3 traffic + */ +public class L3SteeringRequest extends SteeringRequest implements WriteRequest, DeleteRequest { + + public static final byte VPP_IPV4_TYPE = 4; + public static final byte VPP_IPV6_TYPE = 6; + public static final byte VPP_UNRESOLVED_TYPE = 0; + /** + * Where to install FIB entry for this steering + */ + private int fibTableIndex; + + /** + * V4/V6 address for traffic type + */ + private IpPrefix prefix; + + public L3SteeringRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + super.checkValid(); + checkNotNull(prefix, "Prefix is null"); + checkArgument(resolveTrafficType(prefix) == 4 || resolveTrafficType(prefix) == 6, + "IpPrefix format not recognized"); + } + + @Override + public void delete(final InstanceIdentifier<?> identifier) throws WriteFailedException { + checkValid(); + getReplyForDelete(getApi().srSteeringAddDel(bindRequest(true)).toCompletableFuture(), identifier); + } + + @Override + public void write(final InstanceIdentifier<?> identifier) throws WriteFailedException { + checkValid(); + getReplyForWrite(getApi().srSteeringAddDel(bindRequest(false)).toCompletableFuture(), identifier); + } + + private SrSteeringAddDel bindRequest(final boolean isDel) { + final SrSteeringAddDel request = new SrSteeringAddDel(); + request.isDel = booleanToByte(isDel); + request.bsidAddr = ipv6AddressNoZoneToArray(getBindingSid()); + request.tableId = fibTableIndex; + request.trafficType = resolveTrafficType(prefix); + request.prefixAddr = ipPrefixToArray(prefix); + request.maskWidth = extractPrefix(prefix); + return request; + } + + public void setFibTableIndex(final int fibTableIndex) { + this.fibTableIndex = fibTableIndex; + } + + private byte resolveTrafficType(IpPrefix prefix) { + if (prefix.getIpv4Prefix() != null) { + return VPP_IPV4_TYPE; + } else if (prefix.getIpv6Prefix() != null) { + return VPP_IPV6_TYPE; + } + return VPP_UNRESOLVED_TYPE; + } + + public void setPrefix(final IpPrefix prefix) { + this.prefix = prefix; + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java new file mode 100644 index 000000000..2078ade5b --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/write/steering/request/SteeringRequest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.write.steering.request; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; + +/** + * General template for steering requests + */ +public abstract class SteeringRequest extends JVppRequest { + + /** + * Binding SID of policy that should be applied for this traffic + */ + private Ipv6Address bindingSid; + + SteeringRequest(final FutureJVppCore api) { + super(api); + } + + @Override + public void checkValid() { + checkNotNull(bindingSid, "Binding SID is null"); + } + + Ipv6Address getBindingSid() { + return bindingSid; + } + + public void setBindingSid( + final Ipv6Address bindingSid) { + this.bindingSid = bindingSid; + } +} |