diff options
Diffstat (limited to 'v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read')
28 files changed, 3279 insertions, 0 deletions
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/AfPacketCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/AfPacketCustomizer.java new file mode 100644 index 000000000..0022015ec --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/AfPacketCustomizer.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2018 Cisco 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.v3po.read; + +import static java.lang.String.format; + +import com.google.common.annotations.VisibleForTesting; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.StaticCacheKeyFactory; +import io.fd.jvpp.core.dto.AfPacketDetails; +import io.fd.jvpp.core.dto.AfPacketDetailsReplyDump; +import io.fd.jvpp.core.dto.AfPacketDump; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacketBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AfPacketCustomizer implements InitializingReaderCustomizer<AfPacket, AfPacketBuilder>, + InterfaceDataTranslator, JvppReplyConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(AfPacketCustomizer.class); + private NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; + private final DumpCacheManager<AfPacketDetailsReplyDump, Void> afPacketDumpManager; + + public AfPacketCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; + this.afPacketDumpManager = + new DumpCacheManager.DumpCacheManagerBuilder<AfPacketDetailsReplyDump, Void>() + .withCacheKeyFactory(new StaticCacheKeyFactory(AfPacketCustomizer.class.getName() + "_dump", + AfPacketDetailsReplyDump.class)) + .withExecutor((identifier, params) -> { + final CompletionStage<AfPacketDetailsReplyDump> cs = jvpp.afPacketDump(new AfPacketDump()); + return getReplyForRead(cs.toCompletableFuture(), identifier); + }).build(); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull AfPacket readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setAfPacket(readValue); + } + + @Nonnull + @Override + public AfPacketBuilder getBuilder(@Nonnull InstanceIdentifier<AfPacket> id) { + return new AfPacketBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<AfPacket> id, + @Nonnull final AfPacketBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + final InterfaceKey key = id.firstKeyOf(Interface.class); + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + + if (!isInterfaceOfType( + org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.AfPacket.class, + ifcDetails)) { + return; + } + + final AfPacketDetailsReplyDump dump = afPacketDumpManager.getDump(id, ctx.getModificationCache()) + .orElse(new AfPacketDetailsReplyDump()); + // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping + final AfPacketDetails afPacketDetails = dump.afPacketDetails.stream() + .filter(detail -> detail.swIfIndex == index) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(format("AfPacket interface %s not found", key.getName()))); + LOG.trace("AfPacket interface: {} attributes returned from VPP: {}", key.getName(), afPacketDetails); + + builder.setMac(new PhysAddress(vppPhysAddrToYang(ifcDetails.l2Address))); + builder.setHostInterfaceName(toString(afPacketDetails.hostIfName)); + + LOG.debug("AfPacket interface: {}, id: {} attributes read as: {}", key.getName(), index, builder); + } + + @Nonnull + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket> init( + @Nonnull final InstanceIdentifier<AfPacket> id, + @Nonnull final AfPacket readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacketBuilder() + .setHostInterfaceName(readValue.getHostInterfaceName()) + .setMac(readValue.getMac()) + .build()); + } + + @VisibleForTesting + static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket> getCfgId( + final InstanceIdentifier<AfPacket> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child( + org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/EthernetCustomizer.java new file mode 100644 index 000000000..bdad55b21 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/EthernetCustomizer.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.EthernetBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + + +public class EthernetCustomizer + implements InitializingReaderCustomizer<Ethernet, EthernetBuilder>, InterfaceDataTranslator { + + private final InterfaceCacheDumpManager dumpManager; + + public EthernetCustomizer(@Nonnull final InterfaceCacheDumpManager dumpManager) { + this.dumpManager = dumpManager; + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, + @Nonnull final Ethernet readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setEthernet(readValue); + } + + @Nonnull + @Override + public EthernetBuilder getBuilder(@Nonnull InstanceIdentifier<Ethernet> id) { + return new EthernetBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Ethernet> id, + @Nonnull final EthernetBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + + final InterfaceKey key = id.firstKeyOf(Interface.class); + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + + if (iface.linkMtu != 0) { + // Read physical payload MTU (link_mtu) if given. + // VPP since 18.07 supports also setting MTUs for software interfaces, + // but these are not supported by HC (TODO: HC2VPP-355). + // More details: + // https://git.fd.io/vpp/tree/src/vnet/MTU.md + builder.setMtu((int) iface.linkMtu); + } + + switch (iface.linkDuplex) { + case 1: + builder.setDuplex(Ethernet.Duplex.Half); + break; + case 2: + builder.setDuplex(Ethernet.Duplex.Full); + break; + default: + break; + } + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet> init( + @Nonnull final InstanceIdentifier<Ethernet> id, + @Nonnull final Ethernet readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.EthernetBuilder() + .setMtu(readValue.getMtu()) + .build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet> getCfgId( + final InstanceIdentifier<Ethernet> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/GreCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/GreCustomizer.java new file mode 100644 index 000000000..3bb0cbdf8 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/GreCustomizer.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016 Intel 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.v3po.read; + +import static com.google.common.base.Preconditions.checkState; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.dto.GreTunnelDetails; +import io.fd.jvpp.core.dto.GreTunnelDetailsReplyDump; +import io.fd.jvpp.core.dto.GreTunnelDump; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.GreTunnel; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.GreBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GreCustomizer extends FutureJVppCustomizer + implements InitializingReaderCustomizer<Gre, GreBuilder>, InterfaceDataTranslator, Ipv4Translator, + Ipv6Translator { + + private static final Logger LOG = LoggerFactory.getLogger(GreCustomizer.class); + private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; + + public GreCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + super(jvpp); + this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, + @Nonnull Gre readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setGre(readValue); + } + + @Nonnull + @Override + public GreBuilder getBuilder(@Nonnull InstanceIdentifier<Gre> id) { + return new GreBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Gre> id, + @Nonnull final GreBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + final InterfaceKey key = id.firstKeyOf(Interface.class); + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!isInterfaceOfType(dumpManager, id, ctx, GreTunnel.class)) { + return; + } + + LOG.debug("Reading attributes for gre tunnel: {}", key.getName()); + // Dump just a single + final GreTunnelDump request = new GreTunnelDump(); + request.swIfIndex = index; + + final CompletionStage<GreTunnelDetailsReplyDump> swInterfaceGreDetailsReplyDumpCompletionStage = + getFutureJVpp().greTunnelDump(request); + final GreTunnelDetailsReplyDump reply = + getReplyForRead(swInterfaceGreDetailsReplyDumpCompletionStage.toCompletableFuture(), id); + + // VPP keeps gre tunnel interfaces even after they were deleted (optimization) + // However there ar no longer any gre tunnel specific fields assigned to it and this call + // returns nothing + if (reply == null || reply.greTunnelDetails == null || reply.greTunnelDetails.isEmpty()) { + LOG.debug( + "Gre tunnel {}, id {} has no attributes assigned in VPP. Probably is a leftover interface placeholder" + + "after delete", key.getName(), index); + return; + } + + checkState(reply.greTunnelDetails.size() == 1, + "Unexpected number of returned gre tunnels: {} for tunnel: {}", reply.greTunnelDetails, + key.getName()); + LOG.trace("Gre tunnel: {} attributes returned from VPP: {}", key.getName(), reply); + + final GreTunnelDetails swInterfaceGreDetails = reply.greTunnelDetails.get(0); + if (swInterfaceGreDetails.tunnel.isIpv6 == 1) { + builder.setDst(new IpAddressNoZone( + arrayToIpv4AddressNoZone(swInterfaceGreDetails.tunnel.dst.un.getIp6().ip6Address))); + builder.setSrc(new IpAddressNoZone( + arrayToIpv6AddressNoZone(swInterfaceGreDetails.tunnel.src.un.getIp6().ip6Address))); + } else { + builder.setDst(new IpAddressNoZone( + arrayToIpv4AddressNoZone(swInterfaceGreDetails.tunnel.dst.un.getIp4().ip4Address))); + builder.setSrc(new IpAddressNoZone( + arrayToIpv4AddressNoZone(swInterfaceGreDetails.tunnel.src.un.getIp4().ip4Address))); + } + builder.setOuterFibId((long) swInterfaceGreDetails.tunnel.outerFibId); + LOG.debug("Gre tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre> init( + @Nonnull final InstanceIdentifier<Gre> id, @Nonnull final Gre readValue, @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.GreBuilder() + .setDst(readValue.getDst()) + .setSrc(readValue.getSrc()) + .setOuterFibId(readValue.getOuterFibId()) + .build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre> getCfgId( + final InstanceIdentifier<Gre> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterconnectionReadUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterconnectionReadUtils.java new file mode 100644 index 000000000..ab6072615 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterconnectionReadUtils.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; + +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.jvpp.core.dto.BridgeDomainDetails; +import io.fd.jvpp.core.dto.BridgeDomainDetailsReplyDump; +import io.fd.jvpp.core.dto.BridgeDomainDump; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import io.fd.jvpp.core.future.FutureJVppCore; +import io.fd.jvpp.core.types.BridgeDomainSwIf; +import java.util.Arrays; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.Interconnection; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBasedBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class providing Interconnection read support. + */ +final class InterconnectionReadUtils implements InterfaceDataTranslator { + + private static final Logger LOG = LoggerFactory.getLogger(InterconnectionReadUtils.class); + + private final NamingContext interfaceContext; + private final NamingContext bridgeDomainContext; + private final InterfaceCacheDumpManager dumpManager; + private final DumpCacheManager<BridgeDomainDetailsReplyDump,Void> bdDumpManager; + + InterconnectionReadUtils(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext, + @Nonnull final NamingContext bridgeDomainContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + requireNonNull(futureJVppCore, "futureJVppCore should not be null"); + this.interfaceContext = requireNonNull(interfaceContext, "interfaceContext should not be null"); + this.bridgeDomainContext = requireNonNull(bridgeDomainContext, "bridgeDomainContext should not be null"); + this.dumpManager = requireNonNull(dumpManager, "dumpManager should not be null"); + this.bdDumpManager = new DumpCacheManager.DumpCacheManagerBuilder<BridgeDomainDetailsReplyDump, Void>() + .acceptOnly(BridgeDomainDetailsReplyDump.class) + .withExecutor((id, params) -> { + final BridgeDomainDump request = new BridgeDomainDump(); + request.bdId = -1; + + final CompletableFuture<BridgeDomainDetailsReplyDump> bdCompletableFuture = + futureJVppCore.bridgeDomainDump(request).toCompletableFuture(); + return getReplyForRead(bdCompletableFuture, id); + }) + .build(); + } + + @Nullable + Interconnection readInterconnection(@Nonnull final InstanceIdentifier<?> id, @Nonnull final String ifaceName, + @Nonnull final ReadContext ctx) + throws ReadFailedException { + final int ifaceId = interfaceContext.getIndex(ifaceName, ctx.getMappingContext()); + + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, ifaceName); + LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface); + + final BridgeDomainDetailsReplyDump dumpReply = bdDumpManager.getDump(id, ctx.getModificationCache()) + .orElse(new BridgeDomainDetailsReplyDump()); + for (final BridgeDomainDetails bd : dumpReply.bridgeDomainDetails) { + final Optional<BridgeDomainSwIf> bdIfAssignment = getBridgeDomainSwIf(ifaceId, bd); + if (bdIfAssignment.isPresent()) { + final BridgeDomainSwIf bridgeDomainSwIf = bdIfAssignment.get(); + final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder(); + bbBuilder.setBridgeDomain(bridgeDomainContext.getName(bd.bdId, ctx.getMappingContext())); + + // Set BVI if the bridgeDomainDetails.bviSwIfIndex == current sw if index + final Optional<BridgeDomainDetails> bridgeDomainForInterface = + getBridgeDomainForInterface(dumpReply, bd.bdId); + // Since we already found an interface assigned to a bridge domain, the details for BD must be present + checkState(bridgeDomainForInterface.isPresent()); + if (bridgeDomainForInterface.get().bviSwIfIndex == ifaceId) { + bbBuilder.setBridgedVirtualInterface(true); + } else { + bbBuilder.setBridgedVirtualInterface(false); + } + + if (bridgeDomainSwIf.shg != 0) { + bbBuilder.setSplitHorizonGroup((short) bridgeDomainSwIf.shg); + } + return bbBuilder.build(); + } + } + // TODO HONEYCOMB-190 is there a way to check if interconnection is XconnectBased? + + return null; + } + + private Optional<BridgeDomainSwIf> getBridgeDomainSwIf(final int ifaceId, @Nonnull final BridgeDomainDetails bd) { + if (null == bd.swIfDetails) { + return Optional.empty(); + } + // interface can be added to only one BD only + return Arrays.stream(bd.swIfDetails).filter(el -> el.swIfIndex == ifaceId).findFirst(); + } + + private Optional<BridgeDomainDetails> getBridgeDomainForInterface(final BridgeDomainDetailsReplyDump reply, + int bdId) { + return reply.bridgeDomainDetails.stream().filter(a -> a.bdId == bdId).findFirst(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceCustomizer.java new file mode 100644 index 000000000..3e0a1dc41 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceCustomizer.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.DisabledInterfacesManager; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.spi.read.Initialized; +import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfacesBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface.AdminStatus; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface.OperStatus; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading ietf-interfaces:interfaces/interface. + */ +public class InterfaceCustomizer + implements InitializingListReaderCustomizer<Interface, InterfaceKey, InterfaceBuilder>, ByteDataTranslator, + InterfaceDataTranslator { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class); + private final NamingContext interfaceNamingContext; + private final DisabledInterfacesManager interfaceDisableContext; + private final InterfaceCacheDumpManager dumpManager; + + public InterfaceCustomizer(@Nonnull final NamingContext interfaceNamingContext, + @Nonnull final DisabledInterfacesManager interfaceDisableContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + this.interfaceNamingContext = interfaceNamingContext; + this.interfaceDisableContext = interfaceDisableContext; + this.dumpManager = dumpManager; + } + + @Nonnull + @Override + public InterfaceBuilder getBuilder(@Nonnull InstanceIdentifier<Interface> id) { + return new InterfaceBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull InstanceIdentifier<Interface> id, @Nonnull InterfaceBuilder builder, + @Nonnull ReadContext ctx) throws ReadFailedException { + LOG.debug("Reading attributes for interface: {}", id); + final String ifaceName = id.firstKeyOf(id.getTargetType()).getName(); + + final int index = interfaceNamingContext.getIndex(ifaceName, ctx.getMappingContext()); + + // Ignore disabled interface (such as deleted VXLAN tunnels) + if (interfaceDisableContext.isInterfaceDisabled(index, ctx.getMappingContext())) { + LOG.debug("Skipping disabled interface: {}", id); + return; + } + + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, ifaceName); + LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface); + + if (!isRegularInterface(iface)) { + LOG.debug("Interface: {} is a sub-interface. Ignoring read request.", ifaceName); + return; + } + + builder.setName(ifaceName); + builder.setType(getInterfaceType(new String(iface.interfaceName).intern())); + builder.setIfIndex(vppIfIndexToYang(iface.swIfIndex)); + builder.setAdminStatus(1 == iface.adminUpDown + ? AdminStatus.Up + : AdminStatus.Down); + builder.setOperStatus(1 == iface.linkUpDown + ? OperStatus.Up + : OperStatus.Down); + if (0 != iface.linkSpeed) { + builder.setSpeed(vppInterfaceSpeedToYang(iface.linkSpeed)); + } + if (iface.l2AddressLength == 6) { + builder.setPhysAddress(new PhysAddress(vppPhysAddrToYang(iface.l2Address))); + } + LOG.trace("Base attributes read for interface: {} as: {}", ifaceName, builder); + } + + @Nonnull + @Override + public List<InterfaceKey> getAllIds(@Nonnull final InstanceIdentifier<Interface> id, + @Nonnull final ReadContext context) throws ReadFailedException { + final List<InterfaceKey> interfacesKeys; + LOG.trace("Dumping all interfaces to get all IDs"); + final MappingContext mappingCtx = context.getMappingContext(); + final Set<Integer> interfacesIdxs = dumpManager.getInterfaces(id, context) + .filter(elt -> elt != null) + // Filter out disabled interfaces, dont read them + // This also prevents child readers in being invoked such as vxlan (which relies on disabling interfaces) + .filter(elt -> !interfaceDisableContext + .isInterfaceDisabled(elt.swIfIndex, mappingCtx)) + // filter out sub-interfaces + .filter(InterfaceDataTranslator.INSTANCE::isRegularInterface) + .map(elt -> elt.swIfIndex) + .collect(Collectors.toSet()); + + // Clean disabled interfaces list + interfaceDisableContext.getDisabledInterfaces(mappingCtx).stream() + // Find indices not currently in VPP + .filter(interfacesIdxs::contains) + // Remove from disabled list ... not disabled if not existing + .forEach(idx -> interfaceDisableContext.removeDisabledInterface(idx, mappingCtx)); + + // Transform indices to keys + interfacesKeys = interfacesIdxs.stream() + .map(index -> new InterfaceKey(interfaceNamingContext.getName(index, context.getMappingContext()))) + .collect(Collectors.toList()); + + LOG.debug("Interfaces found in VPP: {}", interfacesKeys); + return interfacesKeys; + } + + @Override + public void merge(@Nonnull final org.opendaylight.yangtools.concepts.Builder<? extends DataObject> builder, + @Nonnull final List<Interface> readData) { + ((InterfacesBuilder) builder).setInterface(readData); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface> init( + @Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder() + .setName(readValue.getName()) + .setType(readValue.getType()) + .setEnabled(AdminStatus.Up.equals(readValue.getAdminStatus())) + // Not present in interfaces + // .setLinkUpDownTrapEnable() + .build()); + } + + public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface> getCfgId( + final InstanceIdentifier<Interface> id) { + return InstanceIdentifier.create(Interfaces.class).child( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface.class, + new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey( + id.firstKeyOf(Interface.class).getName())); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceDataTranslator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceDataTranslator.java new file mode 100644 index 000000000..b916431f3 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceDataTranslator.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static com.google.common.base.Preconditions.checkArgument; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import java.math.BigInteger; +import java.util.Objects; +import java.util.stream.Collector; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.AfPacket; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.GreTunnel; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.Loopback; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.TapV2; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUser; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeTunnel; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanTunnel; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev180703.EthernetCsmacd; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.InterfaceType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Gauge64; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public interface InterfaceDataTranslator extends ByteDataTranslator, JvppReplyConsumer { + + InterfaceDataTranslator INSTANCE = new InterfaceDataTranslator() { + }; + + int PHYSICAL_ADDRESS_LENGTH = 6; + + Collector<SwInterfaceDetails, ?, SwInterfaceDetails> SINGLE_ITEM_COLLECTOR = + RWUtils.singleItemCollector(); + + /** + * Convert VPP's link speed in kbits per second to Yang type. + * + * @param vppLinkSpeed Link speed in kbits per second from VPP. + * @return Converted value from VPP link speed + */ + default Gauge64 vppInterfaceSpeedToYang(int vppLinkSpeed) { + return new Gauge64(BigInteger.valueOf(Integer.toUnsignedLong(vppLinkSpeed) * 1000)); + } + + /** + * Reads first 6 bytes of supplied byte array and converts to string as Yang dictates <p> Replace later with + * https://git.opendaylight.org/gerrit/#/c/34869/10/model/ietf/ietf-type- util/src/main/ + * java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfYangUtil.java + * + * @param vppPhysAddress byte array of bytes in big endian order, constructing the network IF physical address. + * @return String like "aa:bb:cc:dd:ee:ff" + * @throws NullPointerException if vppPhysAddress is null + * @throws IllegalArgumentException if vppPhysAddress.length < 6 + */ + default String vppPhysAddrToYang(@Nonnull final byte[] vppPhysAddress) { + Objects.requireNonNull(vppPhysAddress, "Empty physical address bytes"); + final int endIndex = PHYSICAL_ADDRESS_LENGTH; + checkArgument(endIndex <= vppPhysAddress.length, + "Invalid physical address size (%s), expected >= %s", vppPhysAddress.length, endIndex); + // Extended (64-bit) MAC addresses are currently not supported , so use first 48-bits. + // Adding support for extended MAC addresses might require yang model change. + // Also VPP is not consistent (e.g. for TAP it allows to configure MAC of 6 bytes, but sw_interface_details + // contains 8 bytes. + return printHexBinary(vppPhysAddress, 0, PHYSICAL_ADDRESS_LENGTH); + } + + /** + * VPP's interface index is counted from 0, whereas ietf-interface's if-index is from 1. This function converts from + * VPP's interface index to YANG's interface index. + * + * @param vppIfIndex the sw interface index VPP reported. + * @return VPP's interface index incremented by one + */ + default int vppIfIndexToYang(int vppIfIndex) { + return vppIfIndex + 1; + } + + /** + * This function does the opposite of what {@link #vppIfIndexToYang(int)} does. + * + * @param yangIfIndex if-index from ietf-interfaces. + * @return VPP's representation of the if-index + */ + default int yangIfIndexToVpp(int yangIfIndex) { + checkArgument(yangIfIndex >= 1, "YANG if-index has invalid value %s", yangIfIndex); + return yangIfIndex - 1; + } + + /** + * Determine interface type based on its VPP name (relying on VPP's interface naming conventions) + * + * @param interfaceName VPP generated interface name + * @return Interface type + */ + @Nonnull + default Class<? extends InterfaceType> getInterfaceType(@Nonnull final String interfaceName) { + + if (interfaceName.startsWith("tap")) { + return TapV2.class; + } + + if (interfaceName.startsWith("vxlan_gpe")) { + return VxlanGpeTunnel.class; + } + + if (interfaceName.startsWith("vxlan")) { + return VxlanTunnel.class; + } + + if (interfaceName.startsWith("gre")) { + return GreTunnel.class; + } + + if (interfaceName.startsWith("VirtualEthernet")) { + return VhostUser.class; + } + + if (interfaceName.startsWith("host-")) { + return AfPacket.class; + } + + if (interfaceName.startsWith("loop")) { + return Loopback.class; + } + + return EthernetCsmacd.class; + } + + /** + * Check interface type. Uses interface details from VPP to determine. + */ + default boolean isInterfaceOfType(@Nonnull final InterfaceCacheDumpManager dumpManager, + @Nonnull final InstanceIdentifier<?> id, + @Nonnull final ReadContext ctx, + @Nonnull final Class<? extends InterfaceType> ifcType) + throws ReadFailedException { + final String name = id.firstKeyOf(Interface.class).getName(); + final SwInterfaceDetails vppInterfaceDetails = dumpManager.getInterfaceDetail(id, ctx, name); + + return isInterfaceOfType(ifcType, vppInterfaceDetails); + } + + default boolean isInterfaceOfType(@Nonnull final Class<? extends InterfaceType> ifcType, + @Nullable final SwInterfaceDetails cachedDetails) { + if (cachedDetails == null) { + return false; + } else { + return ifcType.equals(getInterfaceType(toString(cachedDetails.interfaceName))); + } + } + + /** + * Checks whether provided {@link SwInterfaceDetails} is detail of sub-interface<br> + * <ul> + * <li>subId == unique number of sub-interface within set of sub-interfaces of single interface</li> + * <li>swIfIndex == unique index of interface/sub-interface within all interfaces</li> + * <li>supSwIfIndex == unique index of parent interface</li> + * <li>in case of interface , swIfIndex value equals supSwIfIndex</li> + * <li>in case of subinterface, supSwIfIndex equals index of parent interface, swIfIndex is index of + * subinterface itselt</li> + * </ul> + */ + default boolean isSubInterface(@Nonnull final SwInterfaceDetails elt) { + //cant check by subId != 0, because you can pick 0 as value + return elt.supSwIfIndex != elt.swIfIndex; + } + + /** + * Checks whether provided {@link SwInterfaceDetails} is detail of interface<br> + * <ul> + * <li>subId == unique number of subinterface within set of subinterfaces of single interface</li> + * <li>swIfIndex == unique index of interface/subinterface within all interfaces</li> + * <li>supSwIfIndex == unique index of parent interface</li> + * <li>in case of interface , swIfIndex value equals supSwIfIndex</li> + * <li>in case of subinterface, supSwIfIndex equals index of parent interface, swIfIndex is index + * of subinterface itselt</li> + * </ul> + */ + default boolean isRegularInterface(@Nonnull final SwInterfaceDetails elt) { + return !isSubInterface(elt); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceRoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceRoutingCustomizer.java new file mode 100644 index 000000000..b87228edf --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceRoutingCustomizer.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read; + +import io.fd.hc2vpp.common.translate.util.NamingContext; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.RoutingBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InterfaceRoutingCustomizer extends RoutingCustomizer implements + InitializingReaderCustomizer<Routing, RoutingBuilder> { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceRoutingCustomizer.class); + + public InterfaceRoutingCustomizer(@Nonnull final FutureJVppCore vppApi, + @Nonnull final NamingContext interfaceContext) { + super(vppApi, interfaceContext); + } + + @Nonnull + @Override + public RoutingBuilder getBuilder(@Nonnull final InstanceIdentifier<Routing> id) { + return new RoutingBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> id, + @Nonnull final RoutingBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + LOG.debug("Reading attributes for Routing: {}", id); + final String ifName = id.firstKeyOf(Interface.class).getName(); + readInterfaceRouting(id, builder::setIpv4VrfId, builder::setIpv6VrfId, ctx, ifName); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final Routing readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setRouting(readValue); + } + + @Nonnull + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing> init( + @Nonnull final InstanceIdentifier<Routing> id, + @Nonnull final Routing readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.RoutingBuilder() + .setIpv4VrfId(readValue.getIpv4VrfId()) + .setIpv6VrfId(readValue.getIpv6VrfId()) + .build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing> getCfgId( + final InstanceIdentifier<Routing> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child( + org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceStatisticsCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceStatisticsCustomizer.java new file mode 100644 index 000000000..bfcb3ee52 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/InterfaceStatisticsCustomizer.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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.v3po.read; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceStatisticsManager; +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.jvpp.stats.dto.InterfaceStatistics; +import io.fd.jvpp.stats.dto.InterfaceStatisticsDetails; +import io.fd.jvpp.stats.dto.InterfaceStatisticsDetailsReplyDump; +import io.fd.jvpp.stats.dto.InterfaceStatisticsDump; +import io.fd.jvpp.stats.future.FutureJVppStatsFacade; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Optional; +import java.util.concurrent.Future; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces._interface.Statistics; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces._interface.StatisticsBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter32; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InterfaceStatisticsCustomizer implements ReaderCustomizer<Statistics, StatisticsBuilder> { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceStatisticsCustomizer.class); + + private final NamingContext ifcNamingCtx; + private final FutureJVppStatsFacade jvppStats; + private final InterfaceStatisticsManager statisticsManager; + + public InterfaceStatisticsCustomizer(final NamingContext ifcNamingCtx, + final FutureJVppStatsFacade jvppStats, + final InterfaceStatisticsManager statisticsManager) { + this.ifcNamingCtx = checkNotNull(ifcNamingCtx, "Naming context should not be null"); + this.jvppStats = checkNotNull(jvppStats, "JVpp Stats facade should not be null"); + this.statisticsManager = checkNotNull(statisticsManager, "Statistics Manager should not be null"); + } + + @Nonnull + @Override + public StatisticsBuilder getBuilder(@Nonnull final InstanceIdentifier<Statistics> instanceIdentifier) { + return new StatisticsBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Statistics> instanceIdentifier, + @Nonnull final StatisticsBuilder statisticsBuilder, + @Nonnull final ReadContext readContext) + throws ReadFailedException { + if (!statisticsManager.isStatisticsEnabled()) return; + + final InterfaceKey key = instanceIdentifier.firstKeyOf(Interface.class); + final int index = ifcNamingCtx.getIndex(key.getName(), readContext.getMappingContext()); + InterfaceStatisticsDetails stats = getStatisticsDump(instanceIdentifier); + if (stats != null) { + Optional<InterfaceStatistics> statsDetail = + Arrays.asList(stats.interfaceStatistics).stream().filter(elt -> elt.swIfIndex == index).findFirst(); + if (statsDetail.isPresent()) { + InterfaceStatistics detail = statsDetail.get(); + statisticsBuilder.setOutOctets(new Counter64(BigInteger.valueOf(detail.outBytes))) + .setOutUnicastPkts(new Counter64(BigInteger.valueOf(detail.outUnicastPkts))) + .setOutMulticastPkts(new Counter64(BigInteger.valueOf(detail.outMulticastPkts))) + .setOutBroadcastPkts(new Counter64(BigInteger.valueOf(detail.outBroadcastPkts))) + .setOutErrors(new Counter32(new Long(detail.outErrors))) + .setInOctets(new Counter64(BigInteger.valueOf(detail.inBytes))) + .setInUnicastPkts(new Counter64(BigInteger.valueOf(detail.inUnicastPkts))) + .setInMulticastPkts(new Counter64(BigInteger.valueOf(detail.inMulticastPkts))) + .setInBroadcastPkts(new Counter64(BigInteger.valueOf(detail.inBroadcastPkts))) + .setInErrors(new Counter32(new Long(detail.inErrors))); + } + } + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final Statistics statistics) { + ((InterfaceBuilder) builder).setStatistics(statistics); + } + + private InterfaceStatisticsDetails getStatisticsDump(InstanceIdentifier<Statistics> id) throws ReadFailedException { + LOG.debug("Sending InterfaceStatisticsDump request..."); + final InterfaceStatisticsDump request = new InterfaceStatisticsDump(); + + final Future<InterfaceStatisticsDetailsReplyDump> replyFuture = + jvppStats.interfaceStatisticsDump(request).toCompletableFuture(); + final InterfaceStatisticsDetailsReplyDump reply; + try { + reply = replyFuture.get(); + } catch (Exception e) { + throw new ReadFailedException(id, e); + } + + if (reply == null || reply.interfaceStatisticsDetails == null) { + throw new ReadFailedException(id, + new IllegalStateException("Received null response for empty dump: " + reply)); + } + return reply.interfaceStatisticsDetails; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/L2Customizer.java new file mode 100644 index 000000000..13440ef63 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/L2Customizer.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2Builder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.Interconnection; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBased; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBasedBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.XconnectBased; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.XconnectBasedBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading ietf-interfaces:interfaces/interface/iface_name/v3po:l2 + */ +public class L2Customizer extends FutureJVppCustomizer implements InitializingReaderCustomizer<L2, L2Builder> { + + private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class); + private final InterconnectionReadUtils icReadUtils; + + public L2Customizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext, + @Nonnull final NamingContext bridgeDomainContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + super(futureJVppCore); + this.icReadUtils = + new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext, dumpManager); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final L2 readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setL2(readValue); + } + + @Nonnull + @Override + public L2Builder getBuilder(@Nonnull final InstanceIdentifier<L2> id) { + return new L2Builder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2Builder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + + LOG.debug("Reading attributes for L2: {}", id); + final InterfaceKey key = id.firstKeyOf(Interface.class); + final String ifaceName = key.getName(); + builder.setInterconnection(icReadUtils.readInterconnection(id, ifaceName, ctx)); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2> init( + @Nonnull final InstanceIdentifier<L2> id, + @Nonnull final L2 readValue, + @Nonnull final ReadContext ctx) { + final org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2Builder + l2Builder = + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2Builder(); + + final Interconnection interconnection = readValue.getInterconnection(); + if (interconnection != null) { + if (interconnection instanceof XconnectBased) { + final XconnectBasedBuilder xconnectBasedBuilder = new XconnectBasedBuilder(); + xconnectBasedBuilder.setXconnectOutgoingInterface( + ((XconnectBased) interconnection).getXconnectOutgoingInterface()); + l2Builder.setInterconnection(xconnectBasedBuilder.build()); + } else if (interconnection instanceof BridgeBased) { + final BridgeBasedBuilder bridgeBasedBuilder = new BridgeBasedBuilder(); + bridgeBasedBuilder.setBridgeDomain(((BridgeBased) interconnection).getBridgeDomain()); + bridgeBasedBuilder + .setBridgedVirtualInterface(((BridgeBased) interconnection).isBridgedVirtualInterface()); + bridgeBasedBuilder.setSplitHorizonGroup(((BridgeBased) interconnection).getSplitHorizonGroup()); + l2Builder.setInterconnection(bridgeBasedBuilder.build()); + } + } + + return Initialized.create(getCfgId(id), l2Builder.build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2> getCfgId( + final InstanceIdentifier<L2> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.L2.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/RewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/RewriteCustomizer.java new file mode 100644 index 000000000..54164cc10 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/RewriteCustomizer.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import io.fd.hc2vpp.common.translate.util.TagRewriteOperation; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +import io.fd.hc2vpp.v3po.util.SubInterfaceUtils; +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.jvpp.core.dto.SwInterfaceDetails; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319._802dot1ad; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319._802dot1q; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.rewrite.attributes.Rewrite; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.rewrite.attributes.RewriteBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2Builder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.tag.rewrite.PushTags; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.tag.rewrite.PushTagsBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.tag.rewrite.PushTagsKey; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qTagVlanType; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTagBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading vlan tag-rewrite configuration state form the VPP. + */ +public class RewriteCustomizer + implements ReaderCustomizer<Rewrite, RewriteBuilder>, InterfaceDataTranslator { + + // No initialization necessary since its parent Subinterface L2 customzier sets the entire subtree during + // initialization + + private static final Logger LOG = LoggerFactory.getLogger(RewriteCustomizer.class); + private final InterfaceCacheDumpManager dumpManager; + + public RewriteCustomizer(@Nonnull final InterfaceCacheDumpManager dumpManager) { + this.dumpManager = checkNotNull(dumpManager, "dumpManager should not be null"); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, + @Nonnull final Rewrite readValue) { + ((L2Builder) parentBuilder).setRewrite(readValue); + } + + @Nonnull + @Override + public RewriteBuilder getBuilder(@Nonnull final InstanceIdentifier<Rewrite> id) { + return new RewriteBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Rewrite> id, + @Nonnull final RewriteBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + final String subInterfaceName = getSubInterfaceName(id); + LOG.debug("Reading attributes for sub interface: {}", subInterfaceName); + + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, subInterfaceName); + LOG.debug("VPP sub-interface details: {}", iface); + + checkState(isSubInterface(iface), "Interface returned by the VPP is not a sub-interface"); + + final TagRewriteOperation operation = TagRewriteOperation.get(iface.vtrOp); + if (TagRewriteOperation.disabled == operation) { + LOG.debug("Tag rewrite operation is disabled for "); + return; + } + + builder.setVlanType(iface.vtrPushDot1Q == 1 + ? _802dot1q.class + : _802dot1ad.class); + + setPushTags(builder, iface); + setPopTags(builder, operation); + } + + private static String getSubInterfaceName(final InstanceIdentifier<Rewrite> id) { + return SubInterfaceUtils.getSubInterfaceName(id.firstKeyOf(Interface.class).getName(), + Math.toIntExact(id.firstKeyOf(SubInterface.class).getIdentifier())); + } + + private void setPopTags(final RewriteBuilder builder, final TagRewriteOperation operation) { + final byte numberOfTagsToPop = operation.getPopTags(); + if (numberOfTagsToPop != 0) { + builder.setPopTags(Short.valueOf(numberOfTagsToPop)); + } + } + + private void setPushTags(final RewriteBuilder builder, final SwInterfaceDetails iface) { + final List<PushTags> tags = new ArrayList<>(); + if (iface.vtrTag1 != 0) { + tags.add(buildTag((short) 0, SVlan.class, iface.vtrTag1)); + } + if (iface.vtrTag2 != 0) { + tags.add(buildTag((short) 1, CVlan.class, iface.vtrTag2)); + } + if (tags.size() > 0) { + builder.setPushTags(tags); + } + } + + private PushTags buildTag(final short index, final Class<? extends Dot1qTagVlanType> tagType, final int vlanId) { + final PushTagsBuilder tag = new PushTagsBuilder(); + tag.setIndex(index); + tag.withKey(new PushTagsKey(index)); + final Dot1qTagBuilder dtag = new Dot1qTagBuilder(); + dtag.setTagType(tagType); + dtag.setVlanId(new Dot1qVlanId(vlanId)); + tag.setDot1qTag(dtag.build()); + return tag.build(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/RoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/RoutingCustomizer.java new file mode 100644 index 000000000..2ac172af6 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/RoutingCustomizer.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read; + +import com.google.common.primitives.UnsignedInts; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.jvpp.core.dto.SwInterfaceGetTable; +import io.fd.jvpp.core.dto.SwInterfaceGetTableReply; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.function.Consumer; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.RoutingBaseAttributes; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +abstract class RoutingCustomizer extends FutureJVppCustomizer implements JvppReplyConsumer { + private final NamingContext interfaceContext; + + protected RoutingCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore); + this.interfaceContext = interfaceContext; + } + + protected void readInterfaceRouting(@Nonnull final InstanceIdentifier<? extends RoutingBaseAttributes> id, + @Nonnull final Consumer<VniReference> v4VrfConsumer, + @Nonnull final Consumer<VniReference> v6VrfConsumer, + @Nonnull final ReadContext ctx, final String interfaceName) + throws ReadFailedException { + final SwInterfaceGetTable request = new SwInterfaceGetTable(); + request.swIfIndex = interfaceContext.getIndex(interfaceName, ctx.getMappingContext()); + request.isIpv6 = 0; + final SwInterfaceGetTableReply + ip4Reply = getReplyForRead(getFutureJVpp().swInterfaceGetTable(request).toCompletableFuture(), id); + + request.isIpv6 = 1; + final SwInterfaceGetTableReply ip6Reply = + getReplyForRead(getFutureJVpp().swInterfaceGetTable(request).toCompletableFuture(), id); + + if (ip4Reply.vrfId != 0) { + v4VrfConsumer.accept(new VniReference(UnsignedInts.toLong(ip4Reply.vrfId))); + } + if (ip6Reply.vrfId != 0) { + v6VrfConsumer.accept(new VniReference(UnsignedInts.toLong(ip6Reply.vrfId))); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceCustomizer.java new file mode 100644 index 000000000..f4bba6d2c --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceCustomizer.java @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +import io.fd.hc2vpp.v3po.util.SubInterfaceUtils; +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.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubInterfaceStatus; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfacesBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.DefaultBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.UntaggedBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.vlan.tagged.VlanTaggedBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.Match; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.MatchBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.Tags; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.TagsBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.tags.Tag; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.tags.TagBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.tags.TagKey; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qTagVlanType; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTagBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading sub interfaces form the VPP. + */ +public class SubInterfaceCustomizer extends FutureJVppCustomizer + implements InitializingListReaderCustomizer<SubInterface, SubInterfaceKey, SubInterfaceBuilder>, + ByteDataTranslator, + InterfaceDataTranslator { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class); + private static final Dot1qTag.VlanId ANY_VLAN_ID = new Dot1qTag.VlanId(Dot1qTag.VlanId.Enumeration.Any); + private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; + + public SubInterfaceCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + super(jvpp); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + this.dumpManager = checkNotNull(dumpManager, "dumpManager should not be null"); + } + + private static String getSubInterfaceName(final InstanceIdentifier<SubInterface> id) { + return SubInterfaceUtils.getSubInterfaceName(id.firstKeyOf(Interface.class).getName(), + Math.toIntExact(id.firstKeyOf(id.getTargetType()).getIdentifier())); + } + + private static Tag buildTag(final short index, final Class<? extends Dot1qTagVlanType> tagType, + final Dot1qTag.VlanId vlanId) { + TagBuilder tag = new TagBuilder(); + tag.setIndex(index); + tag.withKey(new TagKey(index)); + final Dot1qTagBuilder dtag = new Dot1qTagBuilder(); + dtag.setTagType(tagType); + dtag.setVlanId(vlanId); + tag.setDot1qTag(dtag.build()); + return tag.build(); + } + + private static Dot1qTag.VlanId buildVlanId(final short vlanId) { + // treat vlanId as unsigned value: + return new Dot1qTag.VlanId(new Dot1qVlanId(0xffff & vlanId)); + } + + @Nonnull + @Override + public List<SubInterfaceKey> getAllIds(@Nonnull final InstanceIdentifier<SubInterface> id, + @Nonnull final ReadContext context) throws ReadFailedException { + // Relying here that parent InterfaceCustomizer was invoked first (PREORDER) + // to fill in the context with initial ifc mapping + final InterfaceKey key = id.firstKeyOf(Interface.class); + final String ifaceName = key.getName(); + final int ifaceId = interfaceContext.getIndex(ifaceName, context.getMappingContext()); + + final List<SubInterfaceKey> interfacesKeys = dumpManager.getInterfaces(id,context) + .filter(Objects::nonNull) + // accept only sub-interfaces for current iface: + .filter(elt -> isSubInterface(elt) && elt.supSwIfIndex == ifaceId) + .map(details -> new SubInterfaceKey(new Long(details.subId))) + .collect(Collectors.toList()); + + LOG.debug("Sub-interfaces of {} found in VPP: {}", ifaceName, interfacesKeys); + return interfacesKeys; + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> builder, + @Nonnull final List<SubInterface> readData) { + ((SubInterfacesBuilder) builder).setSubInterface(readData); + } + + @Nonnull + @Override + public SubInterfaceBuilder getBuilder(@Nonnull final InstanceIdentifier<SubInterface> id) { + return new SubInterfaceBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id, + @Nonnull final SubInterfaceBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + final String subInterfaceName = getSubInterfaceName(id); + LOG.debug("Reading attributes for sub interface: {}", subInterfaceName); + + final SwInterfaceDetails iface = dumpManager.getInterfaceDetail(id, ctx, subInterfaceName); + LOG.debug("VPP sub-interface details: {}", iface); + + checkState(isSubInterface(iface), "Interface returned by the VPP is not a sub-interface"); + + builder.setIdentifier((long) iface.subId); + builder.withKey(new SubInterfaceKey(builder.getIdentifier())); + + // sub-interface-base-attributes: + builder.setTags(readTags(iface)); + builder.setMatch(readMatch(iface)); + + // sub-interface-operational-attributes: + builder.setAdminStatus(1 == iface.adminUpDown + ? SubInterfaceStatus.Up + : SubInterfaceStatus.Down); + builder.setOperStatus(1 == iface.linkUpDown + ? SubInterfaceStatus.Up + : SubInterfaceStatus.Down); + builder.setIfIndex(vppIfIndexToYang(iface.swIfIndex)); + if (iface.l2AddressLength == 6) { + builder.setPhysAddress(new PhysAddress(vppPhysAddrToYang(iface.l2Address))); + } + if (0 != iface.linkSpeed) { + builder.setSpeed(vppInterfaceSpeedToYang(iface.linkSpeed)); + } + } + + private Tags readTags(final SwInterfaceDetails iface) { + final TagsBuilder tags = new TagsBuilder(); + final List<Tag> list = new ArrayList<>(); + if (iface.subNumberOfTags > 0) { + if (iface.subOuterVlanIdAny == 1) { + list.add(buildTag((short) 0, SVlan.class, ANY_VLAN_ID)); + } else { + list.add(buildTag((short) 0, SVlan.class, buildVlanId(iface.subOuterVlanId))); + } + // inner tag (customer tag): + if (iface.subNumberOfTags == 2) { + if (iface.subInnerVlanIdAny == 1) { + list.add(buildTag((short) 1, CVlan.class, ANY_VLAN_ID)); + } else { + list.add(buildTag((short) 1, CVlan.class, buildVlanId(iface.subInnerVlanId))); + } + } + } + tags.setTag(list); + return tags.build(); + } + + private Match readMatch(final SwInterfaceDetails iface) { + final MatchBuilder match = new MatchBuilder(); + if (iface.subDefault == 1) { + match.setMatchType(new DefaultBuilder().build()); + } else if (iface.subNumberOfTags == 0) { + match.setMatchType(new UntaggedBuilder().build()); + } else { + final VlanTaggedBuilder tagged = new VlanTaggedBuilder(); + tagged.setMatchExactTags(byteToBoolean(iface.subExactMatch)); + match.setMatchType( + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.VlanTaggedBuilder() + .setVlanTagged(tagged.build()).build()); + } + return match.build(); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface> init( + @Nonnull final InstanceIdentifier<SubInterface> id, @Nonnull final SubInterface readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder() + .setEnabled(SubInterfaceStatus.Up.equals(readValue.getAdminStatus())) + .setIdentifier(readValue.getIdentifier()) + .setMatch(readValue.getMatch()) + .setTags(readValue.getTags()) + .setVlanType(readValue.getVlanType()) + .build()); + } + + public static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface> getCfgId( + final InstanceIdentifier<SubInterface> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(SubinterfaceAugmentation.class) + .child(SubInterfaces.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface.class, + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey( + id.firstKeyOf(SubInterface.class).getIdentifier())); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceL2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceL2Customizer.java new file mode 100644 index 000000000..598f3d5ac --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceL2Customizer.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.getSubInterfaceName; + +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBased; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.XconnectBased; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading vlan sub interface L2 operational state + */ +public class SubInterfaceL2Customizer + implements InitializingReaderCustomizer<L2, L2Builder> { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceL2Customizer.class); + private final InterconnectionReadUtils icReadUtils; + + public SubInterfaceL2Customizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext, + @Nonnull final NamingContext bridgeDomainContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + this.icReadUtils = + new InterconnectionReadUtils(futureJVppCore, interfaceContext, bridgeDomainContext, dumpManager); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final L2 readValue) { + ((SubInterfaceBuilder) parentBuilder).setL2(readValue); + } + + @Nonnull + @Override + public L2Builder getBuilder(@Nonnull final InstanceIdentifier<L2> id) { + return new L2Builder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2Builder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + LOG.debug("Reading attributes for sub-interface L2: {}", id); + final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); + final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); + final String subInterfaceName = + getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); + + builder.setInterconnection(icReadUtils.readInterconnection(id, subInterfaceName, ctx)); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2> init( + @Nonnull final InstanceIdentifier<L2> id, + @Nonnull final L2 readValue, + @Nonnull final ReadContext ctx) { + + org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2Builder + builder = + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2Builder(); + + if (readValue.getInterconnection() instanceof XconnectBased) { + XconnectBased state = (XconnectBased) readValue.getInterconnection(); + builder.setInterconnection( + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.XconnectBasedBuilder() + .setXconnectOutgoingInterface(state.getXconnectOutgoingInterface()) + .build()); + } else { + BridgeBased state = (BridgeBased) readValue.getInterconnection(); + builder.setInterconnection( + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.l2.config.attributes.interconnection.BridgeBasedBuilder() + .setBridgeDomain(state.getBridgeDomain()) + .setBridgedVirtualInterface(state.isBridgedVirtualInterface()) + .setSplitHorizonGroup(state.getSplitHorizonGroup()) + .build()); + } + + return Initialized.create(getCfgId(id), builder.setRewrite(readValue.getRewrite()).build()); + } + + static InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2> getCfgId( + final InstanceIdentifier<L2> id) { + return SubInterfaceCustomizer.getCfgId(RWUtils.cutId(id, SubInterface.class)) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceRoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceRoutingCustomizer.java new file mode 100644 index 000000000..831da821c --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/SubInterfaceRoutingCustomizer.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read; + +import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.subInterfaceFullNameOperational; + +import io.fd.hc2vpp.common.translate.util.NamingContext; +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.InitializingReaderCustomizer; +import io.fd.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.RoutingBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + + +public class SubInterfaceRoutingCustomizer extends RoutingCustomizer implements + InitializingReaderCustomizer<Routing, RoutingBuilder> { + public SubInterfaceRoutingCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext interfaceContext) { + super(futureJVppCore, interfaceContext); + } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier, + @Nonnull final Routing routing, + @Nonnull final ReadContext readContext) { + return Initialized.create(instanceIdentifier, routing); + } + + @Nonnull + @Override + public RoutingBuilder getBuilder(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier) { + return new RoutingBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier, + @Nonnull final RoutingBuilder routingBuilder, + @Nonnull final ReadContext readContext) + throws ReadFailedException { + readInterfaceRouting(instanceIdentifier, routingBuilder::setIpv4VrfId, routingBuilder::setIpv6VrfId, + readContext, subInterfaceFullNameOperational(instanceIdentifier)); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final Routing routing) { + ((SubInterfaceBuilder)builder).setRouting(routing); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/TapV2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/TapV2Customizer.java new file mode 100644 index 000000000..902440a34 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/TapV2Customizer.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2018 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.v3po.read; + +import static com.google.common.base.Preconditions.checkState; +import static java.lang.String.format; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.MacTranslator; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.StaticCacheKeyFactory; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import io.fd.jvpp.core.dto.SwInterfaceTapV2Details; +import io.fd.jvpp.core.dto.SwInterfaceTapV2DetailsReplyDump; +import io.fd.jvpp.core.dto.SwInterfaceTapV2Dump; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.Optional; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2Builder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class TapV2Customizer extends FutureJVppCustomizer + implements InitializingReaderCustomizer<TapV2, TapV2Builder>, InterfaceDataTranslator, JvppReplyConsumer, + MacTranslator, Ipv4Translator, Ipv6Translator{ + + private static final Logger LOG = LoggerFactory.getLogger(TapV2Customizer.class); + private NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; + private final DumpCacheManager<SwInterfaceTapV2DetailsReplyDump, Void> tapV2DumpManager; + + public TapV2Customizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + super(jvpp); + this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; + this.tapV2DumpManager = new DumpCacheManager.DumpCacheManagerBuilder<SwInterfaceTapV2DetailsReplyDump, Void>() + .withCacheKeyFactory(new StaticCacheKeyFactory(TapV2Customizer.class.getName() + "_dump", + SwInterfaceTapV2DetailsReplyDump.class)) + .withExecutor((identifier, params) -> { + // Full TapV2 dump has to be performed here, no filter or anything is here to help so at least we cache it + return getReplyForRead(getFutureJVpp() + .swInterfaceTapV2Dump(new SwInterfaceTapV2Dump()).toCompletableFuture(), identifier); + }).build(); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull TapV2 readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setTapV2(readValue); + } + + @Nonnull + @Override + public TapV2Builder getBuilder(@Nonnull InstanceIdentifier<TapV2> id) { + return new TapV2Builder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<TapV2> id, + @Nonnull final TapV2Builder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + + final InterfaceKey key = id.firstKeyOf(Interface.class); + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!isInterfaceOfType(dumpManager, id, ctx, + org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.TapV2.class)) { + return; + } + + LOG.debug("Reading attributes for tapV2 interface: {}", key.getName()); + final SwInterfaceTapV2DetailsReplyDump reply = tapV2DumpManager.getDump(id, ctx.getModificationCache()) + .orElse(new SwInterfaceTapV2DetailsReplyDump()); + + final Optional<SwInterfaceTapV2Details> detail = reply.swInterfaceTapV2Details.stream() + .filter(d -> d.swIfIndex == index) + .findAny(); + + checkState(detail.isPresent(), "TapV2 interface for index %s not found", index); + final SwInterfaceTapV2Details swInterfaceTapV2Details = detail.get(); + + LOG.trace("TapV2 interface: {} attributes returned from VPP: {}", key.getName(), swInterfaceTapV2Details); + if (swInterfaceTapV2Details.devName != null && swInterfaceTapV2Details.devName[0] != 0) { + builder.setDeviceName(toString(swInterfaceTapV2Details.devName)); + } else { + builder.setDeviceName(null); + } + + if (swInterfaceTapV2Details.hostBridge != null && swInterfaceTapV2Details.hostBridge[0] != 0) { + builder.setHostBridge(toString(swInterfaceTapV2Details.hostBridge)); + } else { + builder.setHostBridge(null); + } + + if (swInterfaceTapV2Details.hostMacAddr != null && + !ByteDataTranslator.INSTANCE.isArrayZeroed(swInterfaceTapV2Details.hostMacAddr)) { + builder.setHostMac(toPhysAddress(swInterfaceTapV2Details.hostMacAddr)); + } else { + builder.setHostMac(null); + } + + if (swInterfaceTapV2Details.hostIfName != null && swInterfaceTapV2Details.hostIfName[0] != 0) { + builder.setHostInterfaceName(toString(swInterfaceTapV2Details.hostIfName)); + } else { + builder.setHostInterfaceName(null); + } + + if (swInterfaceTapV2Details.hostIp4Addr != null && swInterfaceTapV2Details.hostIp4PrefixLen != 0) { + builder.setHostIpv4Address( + toIpv4Prefix(swInterfaceTapV2Details.hostIp4Addr, swInterfaceTapV2Details.hostIp4PrefixLen)); + } else { + builder.setHostIpv4Address(null); + } + + if (swInterfaceTapV2Details.hostIp6Addr != null && swInterfaceTapV2Details.hostIp6PrefixLen != 0) { + builder.setHostIpv6Address( + toIpv6Prefix(swInterfaceTapV2Details.hostIp6Addr, + Byte.toUnsignedInt(swInterfaceTapV2Details.hostIp6PrefixLen))); + } else { + builder.setHostIpv6Address(null); + } + + if (swInterfaceTapV2Details.hostNamespace != null && swInterfaceTapV2Details.hostNamespace[0] != 0) { + builder.setHostNamespace(toString(swInterfaceTapV2Details.hostNamespace)); + } else { + builder.setHostNamespace(null); + } + + + builder.setRxRingSize(Short.toUnsignedInt(swInterfaceTapV2Details.rxRingSz)); + builder.setTxRingSize(Short.toUnsignedInt(swInterfaceTapV2Details.txRingSz)); + final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + + if (ifcDetails.tag[0] != 0) { // tag supplied + builder.setTag(toString(ifcDetails.tag)); + } + LOG.debug("TapV2 interface: {}, id: {} attributes read as: {}", key.getName(), index, builder); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2> init( + @Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 readValue, + @Nonnull final ReadContext ctx) { + // The MAC address & tag is set from interface details, those details are retrieved from cache + final InterfaceKey key = id.firstKeyOf(Interface.class); + + final SwInterfaceDetails ifcDetails; + try { + ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + } catch (ReadFailedException e) { + throw new IllegalStateException(format("Unable to read interface %s", key.getName()), e); + } + + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2Builder() + .setMac(new PhysAddress(vppPhysAddrToYang(ifcDetails.l2Address))) + .setHostInterfaceName(readValue.getHostInterfaceName()) + .setTag(ifcDetails.tag[0] == 0 + ? null + : toString(ifcDetails.tag)) + .setHostBridge(readValue.getHostBridge()) + .setHostIpv4Address(readValue.getHostIpv4Address()) + .setHostIpv6Address(readValue.getHostIpv6Address()) + .setRxRingSize(readValue.getRxRingSize()) + .setTxRingSize(readValue.getTxRingSize()) + .setHostMac(readValue.getHostMac()) + .setHostNamespace(readValue.getHostNamespace()) + .build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2> getCfgId( + final InstanceIdentifier<TapV2> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.TapV2.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VhostUserCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VhostUserCustomizer.java new file mode 100644 index 000000000..58f395511 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VhostUserCustomizer.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static java.lang.String.format; + +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; +import io.fd.honeycomb.translate.util.read.cache.StaticCacheKeyFactory; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import io.fd.jvpp.core.dto.SwInterfaceVhostUserDetails; +import io.fd.jvpp.core.dto.SwInterfaceVhostUserDetailsReplyDump; +import io.fd.jvpp.core.dto.SwInterfaceVhostUserDump; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.math.BigInteger; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUserRole; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUserBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VhostUserCustomizer implements InitializingReaderCustomizer<VhostUser, VhostUserBuilder>, + InterfaceDataTranslator, JvppReplyConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(VhostUserCustomizer.class); + private NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; + private final DumpCacheManager<SwInterfaceVhostUserDetailsReplyDump, Void> vhostDumpManager; + + public VhostUserCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; + this.vhostDumpManager = + new DumpCacheManager.DumpCacheManagerBuilder<SwInterfaceVhostUserDetailsReplyDump, Void>() + .withCacheKeyFactory(new StaticCacheKeyFactory(VhostUserCustomizer.class.getName() + "_dump", + SwInterfaceVhostUserDetailsReplyDump.class)) + .withExecutor((identifier, params) -> { + final CompletionStage<SwInterfaceVhostUserDetailsReplyDump> + swInterfaceVhostUserDetailsReplyDumpCompletionStage = + jvpp.swInterfaceVhostUserDump(new SwInterfaceVhostUserDump()); + return getReplyForRead( + swInterfaceVhostUserDetailsReplyDumpCompletionStage.toCompletableFuture(), + identifier); + }).build(); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull VhostUser readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setVhostUser(readValue); + } + + @Nonnull + @Override + public VhostUserBuilder getBuilder(@Nonnull InstanceIdentifier<VhostUser> id) { + return new VhostUserBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<VhostUser> id, + @Nonnull final VhostUserBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + + final InterfaceKey key = id.firstKeyOf(Interface.class); + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + final SwInterfaceDetails ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + + + if (!isInterfaceOfType( + org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VhostUser.class, + ifcDetails)) { + return; + } + + LOG.debug("Reading attributes for vhpost user interface: {}", key.getName()); + + + final SwInterfaceVhostUserDetailsReplyDump dump = + vhostDumpManager.getDump(id, ctx.getModificationCache()) + .orElse(new SwInterfaceVhostUserDetailsReplyDump()); + + // Relying here that parent InterfaceCustomizer was invoked first to fill in the context with initial ifc mapping + final SwInterfaceVhostUserDetails swInterfaceVhostUserDetails = dump.swInterfaceVhostUserDetails.stream() + .filter(detail -> detail.swIfIndex == index) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException( + format("Vhost user for interface %s not found", key.getName()))); + LOG.trace("Vhost user interface: {} attributes returned from VPP: {}", key.getName(), + swInterfaceVhostUserDetails); + + builder.setRole(swInterfaceVhostUserDetails.isServer == 1 + ? VhostUserRole.Server + : VhostUserRole.Client); + builder.setFeatures(BigInteger.valueOf(swInterfaceVhostUserDetails.features)); + builder.setNumMemoryRegions((long) swInterfaceVhostUserDetails.numRegions); + builder.setSocket(toString(swInterfaceVhostUserDetails.sockFilename)); + builder.setVirtioNetHdrSize((long) swInterfaceVhostUserDetails.virtioNetHdrSz); + // TODO: map error code to meaningful message after VPP-436 is done + builder.setConnectError(Integer.toString(swInterfaceVhostUserDetails.sockErrno)); + if (ifcDetails.tag[0] != 0) { // tag supplied + builder.setTag(toString(ifcDetails.tag)); + } + + LOG.debug("Vhost user interface: {}, id: {} attributes read as: {}", key.getName(), index, builder); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser> init( + @Nonnull final InstanceIdentifier<VhostUser> id, + @Nonnull final VhostUser readValue, + @Nonnull final ReadContext ctx) { + // The tag is set from interface details, those details are retrieved from cache + final InterfaceKey key = id.firstKeyOf(Interface.class); + final SwInterfaceDetails ifcDetails; + try { + ifcDetails = dumpManager.getInterfaceDetail(id, ctx, key.getName()); + } catch (ReadFailedException e) { + throw new IllegalStateException(format("Unable to find VHost interface %s", key.getName()), e); + } + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUserBuilder() + .setRole(readValue.getRole()) + .setSocket(readValue.getSocket()) + .setTag(ifcDetails.tag[0] == 0 + ? null + : toString(ifcDetails.tag)) + .build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser> getCfgId( + final InstanceIdentifier<VhostUser> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VxlanCustomizer.java new file mode 100644 index 000000000..f2376bb45 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VxlanCustomizer.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.primitives.UnsignedInts; +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.dto.VxlanTunnelDetails; +import io.fd.jvpp.core.dto.VxlanTunnelDetailsReplyDump; +import io.fd.jvpp.core.dto.VxlanTunnelDump; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.L2Input; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.NshProxy; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanTunnel; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanVni; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VxlanCustomizer extends FutureJVppCustomizer + implements InitializingReaderCustomizer<Vxlan, VxlanBuilder>, InterfaceDataTranslator, JvppReplyConsumer, + Ipv4Translator, Ipv6Translator { + + private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class); + private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; + + public VxlanCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + super(jvpp); + this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, + @Nonnull Vxlan readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setVxlan(readValue); + } + + @Nonnull + @Override + public VxlanBuilder getBuilder(@Nonnull InstanceIdentifier<Vxlan> id) { + return new VxlanBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Vxlan> id, + @Nonnull final VxlanBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + + final InterfaceKey key = id.firstKeyOf(Interface.class); + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!isInterfaceOfType(dumpManager, id, ctx, VxlanTunnel.class)) { + return; + } + + LOG.debug("Reading attributes for vxlan tunnel: {}", key.getName()); + // Dump just a single + final VxlanTunnelDump request = new VxlanTunnelDump(); + request.swIfIndex = index; + + final CompletionStage<VxlanTunnelDetailsReplyDump> swInterfaceVxlanDetailsReplyDumpCompletionStage = + getFutureJVpp().vxlanTunnelDump(request); + final VxlanTunnelDetailsReplyDump reply = + getReplyForRead(swInterfaceVxlanDetailsReplyDumpCompletionStage.toCompletableFuture(), id); + + // VPP keeps vxlan tunnel interfaces even after they were deleted (optimization) + // However there ar no longer any vxlan tunnel specific fields assigned to it and this call + // returns nothing + if (reply == null || reply.vxlanTunnelDetails == null || reply.vxlanTunnelDetails.isEmpty()) { + LOG.debug( + "Vxlan tunnel {}, id {} has no attributes assigned in VPP. Probably is a leftover interface placeholder" + + "after delete", key.getName(), index); + return; + } + + checkState(reply.vxlanTunnelDetails.size() == 1, + "Unexpected number of returned vxlan tunnels: {} for tunnel: {}", reply.vxlanTunnelDetails, + key.getName()); + LOG.trace("Vxlan tunnel: {} attributes returned from VPP: {}", key.getName(), reply); + + final VxlanTunnelDetails swInterfaceVxlanDetails = reply.vxlanTunnelDetails.get(0); + if (swInterfaceVxlanDetails.isIpv6 == 1) { + builder.setDst(new IpAddressNoZone(arrayToIpv6AddressNoZone(swInterfaceVxlanDetails.dstAddress))); + builder.setSrc(new IpAddressNoZone(arrayToIpv6AddressNoZone(swInterfaceVxlanDetails.srcAddress))); + } else { + builder.setDst(new IpAddressNoZone(arrayToIpv4AddressNoZone(swInterfaceVxlanDetails.dstAddress))); + builder.setSrc(new IpAddressNoZone(arrayToIpv4AddressNoZone(swInterfaceVxlanDetails.srcAddress))); + } + builder.setEncapVrfId(new VniReference(UnsignedInts.toLong(swInterfaceVxlanDetails.encapVrfId))); + builder.setVni(new VxlanVni(UnsignedInts.toLong(swInterfaceVxlanDetails.vni))); + switch (swInterfaceVxlanDetails.decapNextIndex) { + case 1: + builder.setDecapNext(L2Input.class); + break; + case 2: + builder.setDecapNext(NshProxy.class); + break; + default: + LOG.trace("Unsupported decap next index for vxlan: {}", swInterfaceVxlanDetails.decapNextIndex); + return; + } + LOG.debug("Vxlan tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan> init( + @Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanBuilder() + .setDst(readValue.getDst()) + .setSrc(readValue.getSrc()) + .setEncapVrfId(readValue.getEncapVrfId()) + .setVni(new VxlanVni(readValue.getVni())) + .setDecapNext(readValue.getDecapNext()) + .build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan> getCfgId( + final InstanceIdentifier<Vxlan> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VxlanGpeCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VxlanGpeCustomizer.java new file mode 100644 index 000000000..eb7269c4b --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/VxlanGpeCustomizer.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read; + +import static com.google.common.base.Preconditions.checkState; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.Ipv4Translator; +import io.fd.hc2vpp.common.translate.util.Ipv6Translator; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.cache.InterfaceCacheDumpManager; +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.InitializingReaderCustomizer; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.dto.VxlanGpeTunnelDetails; +import io.fd.jvpp.core.dto.VxlanGpeTunnelDetailsReplyDump; +import io.fd.jvpp.core.dto.VxlanGpeTunnelDump; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeNextProtocol; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeTunnel; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeVni; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpeBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VxlanGpeCustomizer extends FutureJVppCustomizer + implements InitializingReaderCustomizer<VxlanGpe, VxlanGpeBuilder>, InterfaceDataTranslator, JvppReplyConsumer, + Ipv4Translator, Ipv6Translator { + + private static final Logger LOG = LoggerFactory.getLogger(VxlanGpeCustomizer.class); + private final NamingContext interfaceContext; + private final InterfaceCacheDumpManager dumpManager; + + public VxlanGpeCustomizer(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final InterfaceCacheDumpManager dumpManager) { + super(jvpp); + this.interfaceContext = interfaceContext; + this.dumpManager = dumpManager; + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, + @Nonnull VxlanGpe readValue) { + ((VppInterfaceAugmentationBuilder) parentBuilder).setVxlanGpe(readValue); + } + + @Nonnull + @Override + public VxlanGpeBuilder getBuilder(@Nonnull InstanceIdentifier<VxlanGpe> id) { + return new VxlanGpeBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<VxlanGpe> id, + @Nonnull final VxlanGpeBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + + final InterfaceKey key = id.firstKeyOf(Interface.class); + final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); + if (!isInterfaceOfType(dumpManager, id, ctx, VxlanGpeTunnel.class)) { + return; + } + + LOG.debug("Reading attributes for VxlanGpe tunnel: {}", key.getName()); + // Dump just a single + final VxlanGpeTunnelDump request = new VxlanGpeTunnelDump(); + request.swIfIndex = index; + + final CompletionStage<VxlanGpeTunnelDetailsReplyDump> swInterfaceVxlanGpeDetailsReplyDumpCompletionStage = + getFutureJVpp().vxlanGpeTunnelDump(request); + final VxlanGpeTunnelDetailsReplyDump reply = + getReplyForRead(swInterfaceVxlanGpeDetailsReplyDumpCompletionStage.toCompletableFuture(), + id); + + // VPP keeps VxlanGpe tunnel interfaces even after they were deleted (optimization) + // However there are no longer any VxlanGpe tunnel specific fields assigned to it and this call + // returns nothing + if (reply == null || reply.vxlanGpeTunnelDetails == null || reply.vxlanGpeTunnelDetails.isEmpty()) { + LOG.debug( + "VxlanGpe tunnel {}, id {} has no attributes assigned in VPP. Probably is a leftover interface placeholder" + + "after delete", key.getName(), index); + return; + } + + checkState(reply.vxlanGpeTunnelDetails.size() == 1, + "Unexpected number of returned VxlanGpe tunnels: {} for tunnel: {}", reply.vxlanGpeTunnelDetails, + key.getName()); + LOG.trace("VxlanGpe tunnel: {} attributes returned from VPP: {}", key.getName(), reply); + + final VxlanGpeTunnelDetails swInterfaceVxlanGpeDetails = reply.vxlanGpeTunnelDetails.get(0); + if (swInterfaceVxlanGpeDetails.isIpv6 == 1) { + builder.setRemote(new IpAddressNoZone(arrayToIpv6AddressNoZone(swInterfaceVxlanGpeDetails.remote))); + builder.setLocal(new IpAddressNoZone(arrayToIpv6AddressNoZone(swInterfaceVxlanGpeDetails.local))); + } else { + builder.setRemote(new IpAddressNoZone(arrayToIpv4AddressNoZone(swInterfaceVxlanGpeDetails.remote))); + builder.setLocal(new IpAddressNoZone(arrayToIpv4AddressNoZone(swInterfaceVxlanGpeDetails.local))); + } + builder.setVni(new VxlanGpeVni((long) swInterfaceVxlanGpeDetails.vni)); + builder.setNextProtocol(VxlanGpeNextProtocol.forValue(swInterfaceVxlanGpeDetails.protocol)); + builder.setEncapVrfId((long) swInterfaceVxlanGpeDetails.encapVrfId); + builder.setDecapVrfId((long) swInterfaceVxlanGpeDetails.decapVrfId); + LOG.debug("VxlanGpe tunnel: {}, id: {} attributes read as: {}", key.getName(), index, builder); + } + + @Override + public Initialized<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe> init( + @Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe readValue, + @Nonnull final ReadContext ctx) { + return Initialized.create(getCfgId(id), + new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpeBuilder() + .setLocal(readValue.getLocal()) + .setRemote(readValue.getRemote()) + .setVni(new VxlanGpeVni(readValue.getVni())) + .setNextProtocol(readValue.getNextProtocol()) + .setEncapVrfId(readValue.getEncapVrfId()) + .setDecapVrfId(readValue.getDecapVrfId()) + .build()); + } + + private InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe> getCfgId( + final InstanceIdentifier<VxlanGpe> id) { + return InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe.class); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManager.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManager.java new file mode 100644 index 000000000..3d8df7e6c --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManager.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read.cache; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import java.util.stream.Stream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Manager for dump data of interfaces. The main purpose of this manager is to cache common interface data between + * various classes that process this kind of data. If reader does not use this utility, it introduces a big overhead + * because of size/complexity of interfaces dump + */ +public interface InterfaceCacheDumpManager { + + /** + * Provides stream of all currently configured vpp interfaces + * + * @param identifier id of currently processed data + * @param ctx context of current transaction + * @return {@link Stream} of currently configured interfaces + * @throws ReadFailedException if dumping of data was unsuccessful + */ + @Nonnull + Stream<SwInterfaceDetails> getInterfaces(@Nonnull final InstanceIdentifier<?> identifier, + @Nonnull final ReadContext ctx) throws ReadFailedException; + + /** + * Provides details of interface + * + * @param identifier id of currently processed data + * @param ctx context of current transaction + * @param interfaceName name of requested interface + * @return {@link SwInterfaceDetails} of requested interface + * @throws ReadFailedException if dumping of data was unsuccessful + */ + @Nullable + SwInterfaceDetails getInterfaceDetail(@Nonnull final InstanceIdentifier<?> identifier, + @Nonnull final ReadContext ctx, + @Nonnull final String interfaceName) throws ReadFailedException; +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerImpl.java new file mode 100644 index 000000000..0aee8e459 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerImpl.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read.cache; + +import static io.fd.hc2vpp.common.translate.util.JvppReplyConsumer.INSTANCE; +import static java.util.stream.Collectors.toMap; + +import io.fd.hc2vpp.common.translate.util.ByteDataTranslator; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.honeycomb.translate.ModificationCache; +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.honeycomb.translate.util.read.cache.EntityDumpExecutor; +import io.fd.honeycomb.translate.util.read.cache.StaticCacheKeyFactory; +import io.fd.jvpp.core.dto.SwInterfaceDetails; +import io.fd.jvpp.core.dto.SwInterfaceDetailsReplyDump; +import io.fd.jvpp.core.dto.SwInterfaceDump; +import io.fd.jvpp.core.future.FutureJVppCore; +import io.fd.jvpp.core.types.InterfaceIndex; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Manager for dump data of interfaces/sub-interfaces + */ +final class InterfaceCacheDumpManagerImpl implements InterfaceCacheDumpManager { + + private static final Logger LOG = LoggerFactory.getLogger(InterfaceCacheDumpManagerImpl.class); + + // byNameIndex must be cached, not held as reference here, to have it destroyed with cache after transaction + static final String BY_NAME_INDEX_KEY = InterfaceCacheDumpManagerImpl.class.getName() + "_byNameIndex"; + private NamingContext namingContext; + private final DumpCacheManager<SwInterfaceDetailsReplyDump, String> specificDumpManager; + private final DumpCacheManager<SwInterfaceDetailsReplyDump, Void> fullDumpManager; + + InterfaceCacheDumpManagerImpl(@Nonnull final FutureJVppCore jvpp, + @Nonnull final NamingContext namingContext) { + this.namingContext = namingContext; + specificDumpManager = specificInterfaceDumpManager(jvpp); + fullDumpManager = fullInterfaceDumpManager(jvpp, + new StaticCacheKeyFactory(InterfaceCacheDumpManagerImpl.class.getName() + "_dump", SwInterfaceDetailsReplyDump.class)); + } + + @Override + @Nonnull + public synchronized Stream<SwInterfaceDetails> getInterfaces(@Nonnull final InstanceIdentifier<?> identifier, + @Nonnull final ReadContext ctx) + throws ReadFailedException { + LOG.debug("Reading all interfaces[{}]", identifier); + return initMapAndGet(identifier, ctx).entrySet().stream().map(Map.Entry::getValue); + } + + @Override + @Nullable + public synchronized SwInterfaceDetails getInterfaceDetail(@Nonnull final InstanceIdentifier<?> identifier, + @Nonnull final ReadContext ctx, + @Nonnull final String interfaceName) + throws ReadFailedException { + final Map<String, SwInterfaceDetails> interfaceIndex = getMap(ctx); + + // does not attempt to cover cases with concurrent updates, as tx should be atomic + if (interfaceIndex != null) { + // tries to find interface in map + return interfaceIndex.get(interfaceName); + } else { + // if map is not present, use specific dump(it will be cached standard way, under key constructed from IID) + return dumpSpecificDetail(identifier, ctx, interfaceName); + } + } + + private SwInterfaceDetails dumpSpecificDetail(@Nonnull final InstanceIdentifier<?> identifier, + @Nonnull final ReadContext ctx, + @Nonnull final String interfaceName) + throws ReadFailedException { + LOG.debug("Interface {} not present in cached data, performing specific dump[{}]", interfaceName, + identifier); + final SwInterfaceDetailsReplyDump reply = + specificDumpManager.getDump(identifier, ctx.getModificationCache(), interfaceName) + .orElse(new SwInterfaceDetailsReplyDump()); + + if (reply.swInterfaceDetails.isEmpty()) { + return null; + } + + return reply.swInterfaceDetails.get(0); + } + + private Map<String, SwInterfaceDetails> initMapAndGet(final InstanceIdentifier<?> identifier, final ReadContext ctx) + throws ReadFailedException { + + final ModificationCache cache = ctx.getModificationCache(); + if (!cache.containsKey(BY_NAME_INDEX_KEY)) { + LOG.debug("Performing dump[{}]", identifier); + final SwInterfaceDetailsReplyDump dump = + fullDumpManager.getDump(identifier, cache) + .orElse(new SwInterfaceDetailsReplyDump()); + + // naming context initialization must be done here, as it is uses getName in next step, therefore it would + // create artificial mapping for every interface, because this happens before interface dump is processed + dump.swInterfaceDetails.forEach((elt) -> { + // Store interface name from VPP in context if not yet present + if (!namingContext.containsName(elt.swIfIndex, ctx.getMappingContext())) { + namingContext.addName(elt.swIfIndex, ByteDataTranslator.INSTANCE.toString(elt.interfaceName), + ctx.getMappingContext()); + } + LOG.trace("Interface with name: {}, VPP name: {} and index: {} found in VPP", + getInterfaceName(ctx, elt), + elt.interfaceName, + elt.swIfIndex); + }); + + final Map<String, SwInterfaceDetails> freshIndex = dump.swInterfaceDetails.stream() + .collect(toMap(detail -> getInterfaceName(ctx, detail), + detail -> detail)); + putMap(freshIndex, ctx); + } + + return getMap(ctx); + } + + private String getInterfaceName(final ReadContext ctx, final SwInterfaceDetails elt) { + return namingContext.getName(elt.swIfIndex, ctx.getMappingContext()); + } + + private static Map<String, SwInterfaceDetails> getMap(final ReadContext ctx) { + return (Map<String, SwInterfaceDetails>) ctx.getModificationCache().get(BY_NAME_INDEX_KEY); + } + + private static void putMap(final Map<String, SwInterfaceDetails> map, final ReadContext ctx) { + ctx.getModificationCache().put(BY_NAME_INDEX_KEY, map); + } + + + private static DumpCacheManager<SwInterfaceDetailsReplyDump, Void> fullInterfaceDumpManager( + final FutureJVppCore jvpp, + final StaticCacheKeyFactory cacheKeyFactory) { + return new DumpCacheManager.DumpCacheManagerBuilder<SwInterfaceDetailsReplyDump, Void>() + .withExecutor(fullInterfaceDumpExecutor(jvpp)) + .withCacheKeyFactory(cacheKeyFactory) + .acceptOnly(SwInterfaceDetailsReplyDump.class) + .build(); + } + + private static DumpCacheManager<SwInterfaceDetailsReplyDump, String> specificInterfaceDumpManager( + final FutureJVppCore jvpp) { + return new DumpCacheManager.DumpCacheManagerBuilder<SwInterfaceDetailsReplyDump, String>() + .withExecutor(specificInterfaceDumpExecutor(jvpp)) + .acceptOnly(SwInterfaceDetailsReplyDump.class) + .build(); + } + + private static EntityDumpExecutor<SwInterfaceDetailsReplyDump, Void> fullInterfaceDumpExecutor( + final FutureJVppCore api) { + return (identifier, params) -> { + final SwInterfaceDump request = new SwInterfaceDump(); + request.swIfIndex = new InterfaceIndex(); + request.swIfIndex.interfaceindex = ~0; + request.nameFilter = "".getBytes(); + request.nameFilterValid = 0; + + final CompletableFuture<SwInterfaceDetailsReplyDump> + swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture(); + return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier); + }; + } + + private static EntityDumpExecutor<SwInterfaceDetailsReplyDump, String> specificInterfaceDumpExecutor( + final FutureJVppCore api) { + return (identifier, ifaceName) -> { + final SwInterfaceDump request = new SwInterfaceDump(); + request.swIfIndex = new InterfaceIndex(); + request.swIfIndex.interfaceindex =~0; + request.nameFilter = ifaceName.getBytes(); + request.nameFilterValid = 1; + + final CompletableFuture<SwInterfaceDetailsReplyDump> + swInterfaceDetailsReplyDumpCompletableFuture = api.swInterfaceDump(request).toCompletableFuture(); + return INSTANCE.getReplyForRead(swInterfaceDetailsReplyDumpCompletableFuture, identifier); + }; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerProvider.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerProvider.java new file mode 100644 index 000000000..6fb4f730f --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceCacheDumpManagerProvider.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read.cache; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.jvpp.core.future.FutureJVppCore; +import javax.inject.Named; + +public class InterfaceCacheDumpManagerProvider implements Provider<InterfaceCacheDumpManager> { + + @Inject + private FutureJVppCore jvpp; + + @Inject + @Named("interface-context") + private NamingContext namingContext; + + @Override + public InterfaceCacheDumpManager get() { + return new InterfaceCacheDumpManagerImpl(jvpp, namingContext); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManager.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManager.java new file mode 100644 index 000000000..d23f06eac --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManager.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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.v3po.read.cache; + +public interface InterfaceStatisticsManager { + + boolean isStatisticsEnabled(); + + void enableStatistics(); + + void disableStatistics(); +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerImpl.java new file mode 100644 index 000000000..8450d3484 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerImpl.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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.v3po.read.cache; + +public class InterfaceStatisticsManagerImpl implements InterfaceStatisticsManager { + + private boolean isEnabled; + + @Override + public boolean isStatisticsEnabled() { + return isEnabled; + } + + @Override + public void enableStatistics() { + isEnabled = true; + } + + @Override + public void disableStatistics() { + isEnabled = false; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerProvider.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerProvider.java new file mode 100644 index 000000000..b62487b56 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/cache/InterfaceStatisticsManagerProvider.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019 PANTHEON.tech. + * + * 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.v3po.read.cache; + +import com.google.inject.Provider; + +public class InterfaceStatisticsManagerProvider implements Provider<InterfaceStatisticsManager> { + + @Override + public InterfaceStatisticsManager get() { + return new InterfaceStatisticsManagerImpl(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/pbb/PbbRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/pbb/PbbRewriteCustomizer.java new file mode 100644 index 000000000..a77a7db7d --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/pbb/PbbRewriteCustomizer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read.pbb; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +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.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.PbbRewriteInterfaceAugmentationBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewriteBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class PbbRewriteCustomizer extends FutureJVppCustomizer + implements ReaderCustomizer<PbbRewrite, PbbRewriteBuilder> { + + public PbbRewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Nonnull + @Override + public PbbRewriteBuilder getBuilder(@Nonnull final InstanceIdentifier<PbbRewrite> id) { + return new PbbRewriteBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<PbbRewrite> id, + @Nonnull final PbbRewriteBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + //TODO implement read after https://jira.fd.io/browse/VPP-468 + init + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, + @Nonnull final PbbRewrite readValue) { + ((PbbRewriteInterfaceAugmentationBuilder) parentBuilder).setPbbRewrite(readValue); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/AbstractMirroredInterfacesCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/AbstractMirroredInterfacesCustomizer.java new file mode 100644 index 000000000..12dcbe3cc --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/AbstractMirroredInterfacesCustomizer.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016 Cisco 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.v3po.read.span; + +import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer; +import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer; +import io.fd.hc2vpp.common.translate.util.NamingContext; +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.spi.read.InitializingReaderCustomizer; +import io.fd.jvpp.core.dto.SwInterfaceSpanDetailsReplyDump; +import io.fd.jvpp.core.dto.SwInterfaceSpanDump; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.SpanState; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfacesBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterface; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +abstract class AbstractMirroredInterfacesCustomizer + extends FutureJVppCustomizer + implements InitializingReaderCustomizer<MirroredInterfaces, MirroredInterfacesBuilder>, JvppReplyConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractMirroredInterfacesCustomizer.class); + + private final NamingContext ifcContext; + private final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor; + + protected AbstractMirroredInterfacesCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext ifcContext, + @Nonnull final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor) { + super(futureJVppCore); + this.ifcContext = ifcContext; + this.destinationInterfaceNameExtractor = destinationInterfaceNameExtractor; + } + + @Nonnull + @Override + public MirroredInterfacesBuilder getBuilder(@Nonnull final InstanceIdentifier<MirroredInterfaces> id) { + return new MirroredInterfacesBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<MirroredInterfaces> id, + @Nonnull final MirroredInterfacesBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + LOG.trace("Reading mirrored interfaces under: {}", id); + final int dstId = destinationInterfaceIndex(id, ctx.getMappingContext()); + + final SwInterfaceSpanDetailsReplyDump replyForRead; + if (ctx.getModificationCache().containsKey(getCacheKey())) { + replyForRead = (SwInterfaceSpanDetailsReplyDump) ctx.getModificationCache().get(getCacheKey()); + } else { + replyForRead = getReplyForRead(getFutureJVpp().swInterfaceSpanDump( + new SwInterfaceSpanDump()).toCompletableFuture(), id); + ctx.getModificationCache().put(getCacheKey(), replyForRead); + } + + final List<MirroredInterface> mirroredInterfaces = + replyForRead.swInterfaceSpanDetails.stream() + .filter(detail -> detail.swIfIndexTo == dstId) + .filter(detail -> detail.state != 0) // filters disabled(we use disabled as delete) + .map(detail -> { + final String interfaceName = + ifcContext.getName(detail.swIfIndexFrom, ctx.getMappingContext()); + return new MirroredInterfaceBuilder() + .setIfaceRef(interfaceName) + .withKey(new MirroredInterfaceKey(interfaceName)) + .setState(SpanState.forValue(detail.state)) + .build(); + } + ) + .collect(Collectors.toList()); + + LOG.debug("Mirrored interfaces for: {} read as: {}", id, mirroredInterfaces); + + if (!mirroredInterfaces.isEmpty()) { + builder.setMirroredInterface(mirroredInterfaces); + } + } + + private String getCacheKey() { + return getClass().getName(); + } + + private int destinationInterfaceIndex(@Nonnull final InstanceIdentifier<MirroredInterfaces> id, + @Nonnull final MappingContext mappingContext) { + final String destinationInterfaceName = destinationInterfaceNameExtractor.apply(id); + return ifcContext.getIndex(destinationInterfaceName, mappingContext); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/InterfaceMirroredInterfacesCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/InterfaceMirroredInterfacesCustomizer.java new file mode 100644 index 000000000..841ee85da --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/InterfaceMirroredInterfacesCustomizer.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read.span; + +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.InterfaceCustomizer; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.SpanBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfacesBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Provides interface-specific logic to read/init port mirroring configuration + */ +public class InterfaceMirroredInterfacesCustomizer extends AbstractMirroredInterfacesCustomizer { + + public InterfaceMirroredInterfacesCustomizer(@Nonnull final FutureJVppCore futureJVppCore, + @Nonnull final NamingContext ifcContext) { + super(futureJVppCore, ifcContext, id -> id.firstKeyOf(Interface.class).getName()); + } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull final InstanceIdentifier<MirroredInterfaces> id, + @Nonnull final MirroredInterfaces readValue, + @Nonnull final ReadContext ctx) { + final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces> cfgId = + InterfaceCustomizer.getCfgId(RWUtils.cutId(id, Interface.class)) + .augmentation(VppInterfaceAugmentation.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Span.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces.class); + final org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces + cfgValue = new MirroredInterfacesBuilder() + .setMirroredInterface(Optional.ofNullable(readValue.getMirroredInterface()).orElse(Collections.emptyList()) + .stream() + .map(mirroredInterface -> new MirroredInterfaceBuilder() + .setState(mirroredInterface.getState()) + .withKey(new MirroredInterfaceKey(mirroredInterface.key().getIfaceRef())) + .setIfaceRef(mirroredInterface.getIfaceRef()) + .build()) + .collect(Collectors.toList())) + .build(); + return Initialized.create(cfgId, cfgValue); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull MirroredInterfaces mirroredInterfaces) { + ((SpanBuilder) builder).setMirroredInterfaces(mirroredInterfaces); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/SubInterfaceMirroredInterfacesCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/SubInterfaceMirroredInterfacesCustomizer.java new file mode 100644 index 000000000..308edee8e --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/read/span/SubInterfaceMirroredInterfacesCustomizer.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017 Cisco 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.v3po.read.span; + + +import io.fd.hc2vpp.common.translate.util.NamingContext; +import io.fd.hc2vpp.v3po.read.SubInterfaceCustomizer; +import io.fd.hc2vpp.v3po.util.SubInterfaceUtils; +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.spi.read.Initialized; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.jvpp.core.future.FutureJVppCore; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Collectors; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.subinterface.span.rev170607.VppSubinterfaceSpanAugmentation; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.subinterface.span.rev170607.interfaces._interface.sub.interfaces.sub._interface.Span; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.subinterface.span.rev170607.interfaces._interface.sub.interfaces.sub._interface.SpanBuilder; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces; +import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Provides sub-interface-specific logic to read/init port mirroring configuration + */ +public class SubInterfaceMirroredInterfacesCustomizer extends AbstractMirroredInterfacesCustomizer { + + public SubInterfaceMirroredInterfacesCustomizer(@Nonnull FutureJVppCore futureJVppCore, NamingContext ifcContext) { + super(futureJVppCore, ifcContext, SubInterfaceUtils::subInterfaceFullNameOperational); + } + + @Nonnull + @Override + public Initialized<? extends DataObject> init(@Nonnull InstanceIdentifier<MirroredInterfaces> id, + @Nonnull MirroredInterfaces readValue, + @Nonnull ReadContext readContext) { + final InstanceIdentifier<org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces> cfgId = + SubInterfaceCustomizer.getCfgId(RWUtils.cutId(id, SubInterface.class)) + .augmentation(VppSubinterfaceSpanAugmentation.class) + .child(Span.class) + .child(org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces.class); + + final org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces + cfgValue = new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfacesBuilder() + .setMirroredInterface( + Optional.ofNullable(readValue.getMirroredInterface()).orElse(Collections.emptyList()) + .stream() + .map(mirroredInterface -> new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder() + .withKey(new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceKey(mirroredInterface.key().getIfaceRef())) + .setIfaceRef(mirroredInterface.getIfaceRef()) + .setState(mirroredInterface.getState()) + .build()) + .collect(Collectors.toList())) + .build(); + + return Initialized.create(cfgId, cfgValue); + } + + @Override + public void merge(@Nonnull Builder<? extends DataObject> builder, @Nonnull MirroredInterfaces mirroredInterfaces) { + ((SpanBuilder) builder).setMirroredInterfaces(mirroredInterfaces); + } +} |