/* * 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.nat.read.ifc; import static java.util.Objects.requireNonNull; 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.honeycomb.translate.spi.read.InitializingReaderCustomizer; import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager; import io.fd.jvpp.nat.dto.Nat44InterfaceDetailsReplyDump; import io.fd.jvpp.nat.dto.Nat44InterfaceDump; import io.fd.jvpp.nat.dto.Nat44InterfaceOutputFeatureDetailsReplyDump; import io.fd.jvpp.nat.dto.Nat44InterfaceOutputFeatureDump; import io.fd.jvpp.nat.dto.Nat64InterfaceDetailsReplyDump; import io.fd.jvpp.nat.dto.Nat64InterfaceDump; import io.fd.jvpp.nat.future.FutureJVppNatFacade; import io.fd.jvpp.nat.types.NatConfigFlags; import java.util.Optional; import javax.annotation.Nonnull; 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; abstract class AbstractInterfaceNatCustomizer> implements InitializingReaderCustomizer, JvppReplyConsumer { private final DumpCacheManager preRoutingNat44DumpMgr; private final DumpCacheManager preRoutingNat64DumpMgr; private final DumpCacheManager postRoutingNat44DumpMgr; private final NamingContext ifcContext; private final VppAttributesBuilder vppAttributesBuilder; AbstractInterfaceNatCustomizer(@Nonnull final FutureJVppNatFacade jvppNat, @Nonnull final NamingContext ifcContext, @Nonnull final VppAttributesBuilder vppAttributesBuilder) { requireNonNull(jvppNat, "jvppNat should not be null"); this.ifcContext = requireNonNull(ifcContext, "ifcContext should not be null"); this.vppAttributesBuilder = requireNonNull(vppAttributesBuilder, "ifcContext should not be null"); this.preRoutingNat44DumpMgr = new DumpCacheManager.DumpCacheManagerBuilder() .withExecutor((id, params) -> getReplyForRead( jvppNat.nat44InterfaceDump(new Nat44InterfaceDump()).toCompletableFuture(), id)) .acceptOnly(Nat44InterfaceDetailsReplyDump.class) .build(); this.preRoutingNat64DumpMgr = new DumpCacheManager.DumpCacheManagerBuilder() .withExecutor((id, params) -> getReplyForRead( jvppNat.nat64InterfaceDump(new Nat64InterfaceDump()).toCompletableFuture(), id)) .acceptOnly(Nat64InterfaceDetailsReplyDump.class) .build(); this.postRoutingNat44DumpMgr = new DumpCacheManager.DumpCacheManagerBuilder() .withExecutor((id, params) -> getReplyForRead( jvppNat.nat44InterfaceOutputFeatureDump(new Nat44InterfaceOutputFeatureDump()) .toCompletableFuture(), id)) .acceptOnly(Nat44InterfaceOutputFeatureDetailsReplyDump.class) .build(); } @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final B builder, @Nonnull final ReadContext ctx) throws ReadFailedException { final String ifcName = getName(id); getLog().debug("Reading NAT features on interface: {}", ifcName); final int index = ifcContext.getIndex(ifcName, ctx.getMappingContext()); // Each of the following cases uses different VPP API, but we store them under single node. // Not all combinations are possible, but we don't validate on read and rely on VPP. readPreRoutingNat44(id, index, builder, ctx); readPreRoutingNat64(id, index, builder, ctx); readPostRoutingNat44(id, index, builder, ctx); } private void readPreRoutingNat44(final InstanceIdentifier id, final int index, final B builder, final ReadContext ctx) throws ReadFailedException { final Optional dump = preRoutingNat44DumpMgr.getDump(id, ctx.getModificationCache()); dump.orElse(new Nat44InterfaceDetailsReplyDump()).nat44InterfaceDetails.stream() .filter(natIfcDetail -> natIfcDetail.swIfIndex.interfaceindex == index) .filter(natIfcDetail -> isExpectedNatType(natIfcDetail.flags)) .findAny() .ifPresent(natIfcDetail -> vppAttributesBuilder.enableNat44(builder)); // do not modify builder is feature is absent (inbound/outbound are presence containers) } private void readPreRoutingNat64(final InstanceIdentifier id, final int index, final B builder, final ReadContext ctx) throws ReadFailedException { final Optional dump = preRoutingNat64DumpMgr.getDump(id, ctx.getModificationCache()); dump.orElse(new Nat64InterfaceDetailsReplyDump()).nat64InterfaceDetails.stream() .filter(natIfcDetail -> natIfcDetail.swIfIndex.interfaceindex == index) .filter(natIfcDetail -> isExpectedNatType(natIfcDetail.flags)) .findAny() .ifPresent(natIfcDetail -> vppAttributesBuilder.enableNat64(builder)); // do not modify builder is feature is absent (inbound/outbound are presence containers) } private void readPostRoutingNat44(final InstanceIdentifier id, final int index, final B builder, final ReadContext ctx) throws ReadFailedException { final Optional dump = postRoutingNat44DumpMgr.getDump(id, ctx.getModificationCache()); dump.orElse(new Nat44InterfaceOutputFeatureDetailsReplyDump()).nat44InterfaceOutputFeatureDetails .stream() .filter(natIfcDetail -> natIfcDetail.swIfIndex.interfaceindex == index) .filter(natIfcDetail -> isExpectedNatType(natIfcDetail.flags)) .findAny() .ifPresent(natIfcDetail -> vppAttributesBuilder.enablePostRouting(builder)); // do not modify builder is feature is absent (inbound/outbound are presence containers) } protected String getName(final InstanceIdentifier id) { return id.firstKeyOf(Interface.class).getName(); } abstract Logger getLog(); abstract boolean isExpectedNatType(final NatConfigFlags flags); }