diff options
Diffstat (limited to 'srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read')
6 files changed, 615 insertions, 0 deletions
diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/ReadRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/ReadRequest.java new file mode 100644 index 000000000..1b366fd15 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/ReadRequest.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.read; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.Identifiable; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Represents common interface for read requests + * + * @param <T> type class to be read + * @param <K> key class of read type + * @param <B> builder class for read type + */ +public interface ReadRequest<T extends DataObject & Identifiable<K>, K extends Identifier<T>, B extends Builder<T>> { + + /** + * Provide list of keys for specified type + * + * @param identifier identifies path to DataObject class of specified type + * @param ctx read context holds modification cache and mapping context + * @return list of keys for specified type + * @throws ReadFailedException when read error occurs + */ + @Nonnull + List<K> readAllKeys(@Nonnull final InstanceIdentifier<T> identifier, @Nonnull final ReadContext ctx) throws + ReadFailedException; + + /** + * Reads one specific value + * + * @param identifier identifies path to DataObject class of specified type + * @param ctx read context holds modification cache and mapping context + * @param builder builder for particular type which will hold actual data + * @throws ReadFailedException when read error occurs + */ + void readSpecific(@Nonnull final InstanceIdentifier<T> identifier, @Nonnull final ReadContext ctx, + @Nonnull B builder) + throws ReadFailedException; +} 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 new file mode 100644 index 000000000..312280dce --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/Srv6ReaderFactory.java @@ -0,0 +1,63 @@ +/* + * 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.inject.Inject; +import io.fd.hc2vpp.srv6.Srv6IIds; +import io.fd.hc2vpp.srv6.read.sid.LocatorCustomizer; +import io.fd.hc2vpp.srv6.read.sid.SidCustomizer; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistry; +import io.fd.honeycomb.translate.impl.read.GenericInitListReader; +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.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.Locator1Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.routing.srv6.locators.locator.StaticBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.routing.srv6.locators.locator._static.LocalSidsBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.Routing1Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.routing.Srv6Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.LocatorsBuilder; + +public class Srv6ReaderFactory implements ReaderFactory { + + @Inject + private FutureJVppCore vppApi; + + @Inject + private LocalSidFunctionReadBindingRegistry bindingRegistry; + + @Inject + protected LocatorContextManager locatorContext; + + @Override + public void init(@Nonnull final ModifiableReaderRegistryBuilder registry) { + + registry.addStructuralReader(Srv6IIds.RT_RT1_AUG, Routing1Builder.class); + registry.addStructuralReader(Srv6IIds.RT_SRV6, Srv6Builder.class); + registry.addStructuralReader(Srv6IIds.RT_SRV6_LOCATORS, LocatorsBuilder.class); + registry.addStructuralReader(Srv6IIds.RT_SRV6_LOCS_LOC_AUG, Locator1Builder.class); + registry.addStructuralReader(Srv6IIds.RT_SRV6_LOCS_LOC_STATIC, StaticBuilder.class); + registry.addStructuralReader(Srv6IIds.RT_SRV6_LOCS_LOC_ST_LOCALSIDS, LocalSidsBuilder.class); + + registry.add(new GenericInitListReader<>(Srv6IIds.RT_SRV6_LOCS_LOCATOR, + new LocatorCustomizer(vppApi, locatorContext))); + registry.add(new GenericInitListReader<>(Srv6IIds.RT_SRV6_LOCS_LOC_ST_LS_SID, + new SidCustomizer(vppApi, bindingRegistry, locatorContext))); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/LocatorCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/LocatorCustomizer.java new file mode 100644 index 000000000..3fc33988c --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/LocatorCustomizer.java @@ -0,0 +1,81 @@ +/* + * 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.sid; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.read.sid.request.LocatorReadRequest; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.LocatorsBuilder; +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.LocatorBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.locators.LocatorKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class LocatorCustomizer extends FutureJVppCustomizer + implements InitializingListReaderCustomizer<Locator, LocatorKey, LocatorBuilder> { + + private final LocatorContextManager locatorContext; + + public LocatorCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final LocatorContextManager locatorContext) { + super(futureJVppCore); + this.locatorContext = locatorContext; + } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull InstanceIdentifier<Locator> instanceIdentifier, + @Nonnull Locator locator, + @Nonnull ReadContext readContext) { + return Initialized.create(instanceIdentifier, locator); + } + + @Nonnull + @Override + public List<LocatorKey> getAllIds(@Nonnull InstanceIdentifier<Locator> instanceIdentifier, + @Nonnull ReadContext readContext) throws ReadFailedException { + return new LocatorReadRequest(getFutureJVpp(), locatorContext).readAllKeys(instanceIdentifier, readContext); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Locator> locators) { + ((LocatorsBuilder) builder).setLocator(locators); + } + + @Nonnull + @Override + public LocatorBuilder getBuilder(@Nonnull InstanceIdentifier<Locator> instanceIdentifier) { + return new LocatorBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier<Locator> instanceIdentifier, + @Nonnull LocatorBuilder locatorBuilder, + @Nonnull ReadContext readContext) throws ReadFailedException { + new LocatorReadRequest(getFutureJVpp(), locatorContext) + .readSpecific(instanceIdentifier, readContext, locatorBuilder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/SidCustomizer.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/SidCustomizer.java new file mode 100644 index 000000000..58beb9df3 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/SidCustomizer.java @@ -0,0 +1,87 @@ +/* + * 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.sid; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.srv6.read.sid.request.LocalSidReadRequest; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistry; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.routing.srv6.locators.locator._static.LocalSidsBuilder; +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._static.cfg.SidBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6._static.cfg.SidKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class SidCustomizer extends FutureJVppCustomizer + implements InitializingListReaderCustomizer<Sid, SidKey, SidBuilder> { + + private final LocalSidFunctionReadBindingRegistry registry; + private final LocatorContextManager locatorContext; + + public SidCustomizer(@Nonnull final FutureJVppCore futureJVppCore, LocalSidFunctionReadBindingRegistry registry, + @Nonnull final LocatorContextManager locatorContext) { + super(futureJVppCore); + this.registry = registry; + this.locatorContext = locatorContext; + } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull InstanceIdentifier<Sid> instanceIdentifier, + @Nonnull Sid sid, + @Nonnull ReadContext readContext) { + return Initialized.create(instanceIdentifier, sid); + } + + @Nonnull + @Override + public List<SidKey> getAllIds(@Nonnull InstanceIdentifier<Sid> instanceIdentifier, @Nonnull ReadContext readContext) + throws ReadFailedException { + + return new LocalSidReadRequest(getFutureJVpp(), locatorContext, registry) + .readAllKeys(instanceIdentifier, readContext); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull List<Sid> list) { + ((LocalSidsBuilder) builder).setSid(list); + } + + @Nonnull + @Override + public SidBuilder getBuilder(@Nonnull InstanceIdentifier<Sid> instanceIdentifier) { + return new SidBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier<Sid> instanceIdentifier, + @Nonnull SidBuilder sidBuilder, + @Nonnull ReadContext readContext) throws ReadFailedException { + LocalSidReadRequest readRequest = new LocalSidReadRequest(getFutureJVpp(), locatorContext, + registry); + readRequest.readSpecific(instanceIdentifier, readContext, sidBuilder); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/request/LocalSidReadRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/request/LocalSidReadRequest.java new file mode 100644 index 000000000..e1bd8d073 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/request/LocalSidReadRequest.java @@ -0,0 +1,189 @@ +/* + * 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.sid.request; + +import static java.lang.Integer.parseInt; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.googlecode.ipv6.IPv6NetworkMask; +import io.fd.hc2vpp.srv6.read.ReadRequest; +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.hc2vpp.srv6.util.function.LocalSidFunctionReadBindingRegistry; +import io.fd.honeycomb.translate.MappingContext; +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.SrLocalsidsDetails; +import io.fd.vpp.jvpp.core.dto.SrLocalsidsDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.SrLocalsidsDump; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +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.srv6._static.rev180301.srv6._static.cfg.Sid; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6._static.cfg.SidBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6._static.rev180301.srv6._static.cfg.SidKey; +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.LocatorKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.EndDT4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.EndDT6; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.EndDX2; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.EndDX4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.EndDX6; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.Srv6EndpointType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.Srv6FuncOpcodeUnreserved; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class LocalSidReadRequest extends JVppRequest implements ReadRequest<Sid, SidKey, SidBuilder> { + + private static final Map<Integer, Class<? extends Srv6EndpointType>> VPP_END_FUNC_REGISTER; + private static final SrLocalsidsDump STATIC_DUMP_REQUEST = new SrLocalsidsDump(); + private static final SrLocalsidsDetailsReplyDump STATIC_EMPTY_REPLY = new SrLocalsidsDetailsReplyDump(); + + static { + VPP_END_FUNC_REGISTER = ImmutableMap.<Integer, Class<? extends Srv6EndpointType>>builder() + .put(1, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.End.class) + .put(2, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.EndX.class) + .put(3, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.EndT.class) + .put(5, EndDX2.class) + .put(6, EndDX6.class) + .put(7, EndDX4.class) + .put(8, EndDT6.class) + .put(9, EndDT4.class) + .build(); + } + + private final DumpCacheManager<SrLocalsidsDetailsReplyDump, Void> dumpManager; + private final LocatorContextManager locatorContext; + private final LocalSidFunctionReadBindingRegistry registry; + + public LocalSidReadRequest(final FutureJVppCore api, + final LocatorContextManager locatorContext, + final LocalSidFunctionReadBindingRegistry registry) { + super(api); + this.dumpManager = new DumpCacheManager.DumpCacheManagerBuilder<SrLocalsidsDetailsReplyDump, Void>() + .acceptOnly(SrLocalsidsDetailsReplyDump.class) + .withExecutor((identifier, params) -> getReplyForRead( + api.srLocalsidsDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier)) + .build(); + this.locatorContext = locatorContext; + this.registry = registry; + } + + /** + * Extracts Operational code (SRv6 endpoint function) from provided SID value. SID value consists of two parts. + * First part is Locator defined by its IPv6 address and length (stored in mappingContext referenced + * by locator name). Second part is Operational code (endpoint function). Locator length(number of bits) divides SID + * address to bits used for locator value and bits used for endpoint function. + * + * @see <a href="https://tools.ietf.org/html/draft-filsfils-spring-srv6-network-programming-04"> + * SRv6 network programming (SRv6 Segment)</a> + * @see <a href="https://tools.ietf.org/html/draft-raza-spring-srv6-yang-01"> + * * SRv6 Yang (SRv6 Types)</a> + * + * @param sid provided SRv6 SIDs IPv6 address + * @param mappingContext mapping context which stores mapping for locator length + * @param locName locator name used as a key to retrieve locator length from mapping context + * @return operational code (endpoint function) of SRv6 SID address + */ + private Srv6FuncOpcodeUnreserved extractOpCode(Ipv6Address sid, MappingContext mappingContext, + final String locName) { + int locLength = LocatorContextManager.parseLength(locatorContext.getLocator(locName, mappingContext)); + com.googlecode.ipv6.IPv6Address ip = com.googlecode.ipv6.IPv6Address.fromString(sid.getValue()); + IPv6NetworkMask mask = IPv6NetworkMask.fromPrefixLength(locLength); + com.googlecode.ipv6.IPv6Address locator = ip.maskWithNetworkMask(mask); + + long function = ip.toBigInteger().subtract(locator.toBigInteger()).longValue(); + + return new Srv6FuncOpcodeUnreserved(function); + } + + @Override + @Nonnull + public List<SidKey> readAllKeys(@Nonnull InstanceIdentifier<Sid> identifier, @Nonnull ReadContext ctx) + throws ReadFailedException { + final LocatorKey key = Preconditions.checkNotNull(identifier.firstKeyOf(Locator.class), + "Identifier does not have %s ", LocatorKey.class); + String locator = key.getName(); + + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srLocalsidsDetails + .stream() + .filter(detail -> arrayToIpv6AddressNoZone(detail.addr.addr).getValue().contains(locator)) + .map(srLocalsidsDetails -> extractOpCode(arrayToIpv6AddressNoZone(srLocalsidsDetails.addr.addr), + ctx.getMappingContext(), locator)) + .map(SidKey::new) + .collect(Collectors.toList()); + } + + @Override + public void readSpecific(@Nonnull InstanceIdentifier<Sid> identifier, @Nonnull ReadContext ctx, + @Nonnull SidBuilder builder) + throws ReadFailedException { + final SidKey sidKey = Preconditions.checkNotNull(identifier.firstKeyOf(Sid.class), + "Identifier does not contain %s ", SidKey.class); + final LocatorKey locatorKey = Preconditions.checkNotNull(identifier.firstKeyOf(Locator.class), + "Identifier does not contain %s ", Locator.class); + + // VPP stores SID address as whole without defining locator and function parts (or locator length). + // It is necessary to split SID address to locator and function (operational code), because that is how SID + // is identified in model. Currently we use locatorContext to store locator length, so it is possible to split + // SID address back to locator (used as LocatorKey) and function (used as SidKey) or to construct SID from + // from locator and function (opCode) + Integer locLength = LocatorContextManager + .parseLength(locatorContext.getLocator(locatorKey.getName(), ctx.getMappingContext())); + Ipv6Address locator = LocatorContextManager + .parseLocator(locatorContext.getLocator(locatorKey.getName(), ctx.getMappingContext())); + + Ipv6Address sidAddress = + parseSrv6SidAddress(locator.getValue(), locLength.toString(), sidKey.getOpcode().getValue()); + + dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srLocalsidsDetails + .stream() + .filter(detail -> Arrays.equals(detail.addr.addr, ipv6AddressNoZoneToArray(sidAddress))) + .findFirst() + .ifPresent(detail -> bindLocalSid(detail, ctx, locatorKey.getName(), sidAddress, builder)); + } + + private Ipv6Address parseSrv6SidAddress(final String locatorIp, final String locatorLength, final Long opcode) { + com.googlecode.ipv6.IPv6Address ip = + com.googlecode.ipv6.IPv6Address.fromString(locatorIp); + IPv6NetworkMask mask = IPv6NetworkMask.fromPrefixLength(parseInt(locatorLength)); + com.googlecode.ipv6.IPv6Address srv6Sid = ip.maskWithNetworkMask(mask); + return new Ipv6Address(srv6Sid.add(opcode.intValue()).toString()); + } + + private void bindLocalSid(final SrLocalsidsDetails detail, final ReadContext readContext, final String locName, + final Ipv6Address sidAddress, final SidBuilder builder) { + Class<? extends Srv6EndpointType> behaviorType = parseEndBehaviorType(detail.behavior); + Srv6FuncOpcodeUnreserved opcode = extractOpCode(sidAddress, readContext.getMappingContext(), locName); + builder.setEndBehaviorType(behaviorType).setKey(new SidKey(opcode)).setOpcode(opcode); + parseEndFunction(builder, detail, readContext); + } + + private void parseEndFunction(SidBuilder builder, SrLocalsidsDetails detail, ReadContext readContext) { + registry.bind(detail, readContext, builder); + } + + private Class<? extends Srv6EndpointType> parseEndBehaviorType(short behavior) { + return VPP_END_FUNC_REGISTER.get((int) behavior); + } +} diff --git a/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/request/LocatorReadRequest.java b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/request/LocatorReadRequest.java new file mode 100644 index 000000000..ff6316b01 --- /dev/null +++ b/srv6/srv6-impl/src/main/java/io/fd/hc2vpp/srv6/read/sid/request/LocatorReadRequest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2018 Bell Canada, Pantheon Technologies and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.hc2vpp.srv6.read.sid.request; + +import static io.fd.hc2vpp.srv6.Srv6Configuration.DEFAULT_LOCATOR_LENGTH; + +import com.google.common.base.Preconditions; +import com.googlecode.ipv6.IPv6NetworkMask; +import io.fd.hc2vpp.srv6.read.ReadRequest; +import io.fd.hc2vpp.srv6.util.JVppRequest; +import io.fd.hc2vpp.srv6.util.LocatorContextManager; +import io.fd.honeycomb.translate.MappingContext; +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.SrLocalsidsDetails; +import io.fd.vpp.jvpp.core.dto.SrLocalsidsDetailsReplyDump; +import io.fd.vpp.jvpp.core.dto.SrLocalsidsDump; +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.ietf.srv6.base.rev180613.VppSrv6FibLocatorAugment; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.ietf.srv6.base.rev180613.VppSrv6FibLocatorAugmentBuilder; +import org.opendaylight.yang.gen.v1.urn.hc2vpp.params.xml.ns.yang.vpp.ietf.srv6.base.rev180613.vpp.srv6.fib.FibTableBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone; +import org.opendaylight.yang.gen.v1.urn.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.LocatorBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.locators.LocatorKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.base.rev180301.srv6.locators.locators.locator.PrefixBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.srv6.types.rev180301.Srv6LocatorLen; +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; + +public class LocatorReadRequest extends JVppRequest implements ReadRequest<Locator, LocatorKey, LocatorBuilder> { + + private static final SrLocalsidsDump STATIC_DUMP_REQUEST = new SrLocalsidsDump(); + private static final SrLocalsidsDetailsReplyDump STATIC_EMPTY_REPLY = new SrLocalsidsDetailsReplyDump(); + private final DumpCacheManager<SrLocalsidsDetailsReplyDump, Void> dumpManager; + private final LocatorContextManager locatorCtx; + + public LocatorReadRequest(final FutureJVppCore api, LocatorContextManager locatorCtx) { + super(api); + this.dumpManager = new DumpCacheManager.DumpCacheManagerBuilder<SrLocalsidsDetailsReplyDump, Void>() + .acceptOnly(SrLocalsidsDetailsReplyDump.class) + .withExecutor((identifier, params) -> getReplyForRead( + api.srLocalsidsDump(STATIC_DUMP_REQUEST).toCompletableFuture(), identifier)) + .build(); + this.locatorCtx = locatorCtx; + } + + private Ipv6Address extractLocator(Ipv6Address sid, final MappingContext mappingContext, String locName) { + /* + * TODO(HC2VPP-353): VPP does not support locator length, therefore it is necessary to use default value for + * locator length, if there is no other way of getting the value (e.g. hc2vpp starts with configuration already + * present in VPP). + * */ + int locLength = locName == null + ? DEFAULT_LOCATOR_LENGTH + : LocatorContextManager.parseLength(locatorCtx.getLocator(locName, mappingContext)); + com.googlecode.ipv6.IPv6Address ip = com.googlecode.ipv6.IPv6Address.fromString(sid.getValue()); + IPv6NetworkMask mask = IPv6NetworkMask.fromPrefixLength(locLength); + // strip function part if present + ip = ip.maskWithNetworkMask(mask); + return new Ipv6AddressNoZone(ip.toString()); + } + + @Override + @Nonnull + public List<LocatorKey> readAllKeys(@Nonnull final InstanceIdentifier<Locator> identifier, + @Nonnull final ReadContext ctx) + throws ReadFailedException { + return dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srLocalsidsDetails + .stream() + .map(srLocalsidsDetails -> extractLocator(arrayToIpv6AddressNoZone(srLocalsidsDetails.addr.addr), + ctx.getMappingContext(), null).getValue()) + .map(LocatorKey::new) + .distinct() + .collect(Collectors.toList()); + } + + @Override + public void readSpecific(@Nonnull final InstanceIdentifier<Locator> identifier, @Nonnull final ReadContext ctx, + @Nonnull LocatorBuilder builder) throws ReadFailedException { + final LocatorKey key = Preconditions.checkNotNull(identifier.firstKeyOf(Locator.class), + "Identifier does not have %s ", LocatorKey.class); + String locator = key.getName(); + + dumpManager.getDump(identifier, ctx.getModificationCache()).or(STATIC_EMPTY_REPLY).srLocalsidsDetails + .stream() + .filter(detail -> arrayToIpv6AddressNoZone(detail.addr.addr).getValue().contains(locator)) + .findFirst() + .ifPresent(srLocalsidsDetails -> bindLocalSid(srLocalsidsDetails, ctx.getMappingContext(), locator, + builder)); + } + + private void bindLocalSid(final SrLocalsidsDetails detail, final MappingContext mappingContext, + final String locName, LocatorBuilder builder) { + Ipv6Address locator = extractLocator(arrayToIpv6AddressNoZone(detail.addr.addr), mappingContext, locName); + int locLength = LocatorContextManager.parseLength(locatorCtx.getLocator(locName, mappingContext)); + + builder.setKey(new LocatorKey(locator.getValue())) + .setName(locator.getValue()) + .setPrefix( + new PrefixBuilder() + .setAddress(locator) + .setLength(new Srv6LocatorLen((short) locLength)) + .build()) + .setIsDefault(false) + .setEnable(true) + .addAugmentation(VppSrv6FibLocatorAugment.class, new VppSrv6FibLocatorAugmentBuilder() + .setFibTable(new FibTableBuilder() + .setAddressFamily(Ipv6.class) + .setTableId(new VniReference(Integer.toUnsignedLong(detail.fibTable))) + .build()) + .build()); + } +} |