2 * Copyright (c) 2016 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package io.fd.honeycomb.nat.read;
19 import io.fd.honeycomb.translate.read.ReadContext;
20 import io.fd.honeycomb.translate.read.ReadFailedException;
21 import io.fd.honeycomb.translate.spi.read.Initialized;
22 import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
23 import io.fd.honeycomb.translate.util.RWUtils;
24 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
25 import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
26 import io.fd.honeycomb.translate.vpp.util.Ipv4Translator;
27 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
28 import io.fd.vpp.jvpp.snat.dto.SnatAddressDetails;
29 import io.fd.vpp.jvpp.snat.dto.SnatAddressDetailsReplyDump;
30 import io.fd.vpp.jvpp.snat.dto.SnatAddressDump;
31 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
32 import java.util.Collections;
33 import java.util.List;
34 import java.util.stream.Collectors;
35 import java.util.stream.LongStream;
36 import javax.annotation.Nonnull;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolKey;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstance;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.NatInstanceKey;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.NatCurrentConfigBuilder;
44 import org.opendaylight.yangtools.concepts.Builder;
45 import org.opendaylight.yangtools.yang.binding.DataObject;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 final class ExternalIpPoolCustomizer implements
51 InitializingListReaderCustomizer<ExternalIpAddressPool, ExternalIpAddressPoolKey, ExternalIpAddressPoolBuilder>,
52 JvppReplyConsumer, Ipv4Translator {
54 private static final Logger LOG = LoggerFactory.getLogger(ExternalIpPoolCustomizer.class);
56 private final DumpCacheManager<SnatAddressDetailsReplyDump, Void> dumpMgr;
58 ExternalIpPoolCustomizer(final DumpCacheManager<SnatAddressDetailsReplyDump, Void> dumpMgr) {
59 this.dumpMgr = dumpMgr;
64 public ExternalIpAddressPoolBuilder getBuilder(@Nonnull final InstanceIdentifier<ExternalIpAddressPool> id) {
65 return new ExternalIpAddressPoolBuilder();
69 public void readCurrentAttributes(@Nonnull final InstanceIdentifier<ExternalIpAddressPool> id,
70 @Nonnull final ExternalIpAddressPoolBuilder builder,
71 @Nonnull final ReadContext ctx) throws ReadFailedException {
72 LOG.trace("Reading current attributes for external IP pool: {}", id);
74 final Long poolId = id.firstKeyOf(ExternalIpAddressPool.class).getPoolId();
75 final SnatAddressDetails details =
76 dumpMgr.getDump(id, ctx.getModificationCache(), null)
77 .or(new SnatAddressDetailsReplyDump()).snatAddressDetails.get(Math.toIntExact(poolId));
79 builder.setExternalIpPool(
80 new Ipv4Prefix(arrayToIpv4AddressNoZoneReversed(details.ipAddress).getValue() + "/32"));
81 builder.setPoolId(poolId);
83 LOG.trace("External IP pool: {}. Read as: {}", id, builder);
88 public List<ExternalIpAddressPoolKey> getAllIds(@Nonnull final InstanceIdentifier<ExternalIpAddressPool> id,
89 @Nonnull final ReadContext ctx) throws ReadFailedException {
90 final NatInstanceKey natKey = id.firstKeyOf(NatInstance.class);
91 if (!natKey.equals(NatInstanceCustomizer.DEFAULT_VRF_ID)) {
92 // IP Pools are not vrf aware ... so they are only visible under default vrf (nat-instance)
93 return Collections.emptyList();
96 LOG.trace("Listing IDs for all external IP pools within nat-instance(vrf):{}", natKey);
98 // Since VPP returns every single (unordered) address instead of address range,
99 // there is no way to determine what the original ranges were when writing the data into VPP.
101 // That's why the write and read is not symmetrical in terms of data structure, instead,
102 // this customizer also returns every single address as a 32 prefix and assigns an artificial key to them
104 final long addressCount = dumpMgr.getDump(id, ctx.getModificationCache(), null)
105 .or(new SnatAddressDetailsReplyDump()).snatAddressDetails.stream()
108 final List<ExternalIpAddressPoolKey> ids = LongStream.range(0, addressCount)
109 .mapToObj(ExternalIpAddressPoolKey::new)
110 .collect(Collectors.toList());
112 LOG.trace("List of external IP pool ids: {}", ids);
117 public void merge(@Nonnull final Builder<? extends DataObject> builder,
118 @Nonnull final List<ExternalIpAddressPool> readData) {
119 ((NatCurrentConfigBuilder) builder).setExternalIpAddressPool(readData);
123 public Initialized<ExternalIpAddressPool> init(
124 @Nonnull final InstanceIdentifier<ExternalIpAddressPool> id,
125 @Nonnull final ExternalIpAddressPool readValue,
126 @Nonnull final ReadContext ctx) {
127 return Initialized.create(getCfgId(id), readValue);
130 static InstanceIdentifier<ExternalIpAddressPool> getCfgId(final @Nonnull InstanceIdentifier<ExternalIpAddressPool> id) {
131 return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class))
132 .child(ExternalIpAddressPool.class, id.firstKeyOf(ExternalIpAddressPool.class));
135 static final class AddressRangeDumpExecutor implements EntityDumpExecutor<SnatAddressDetailsReplyDump, Void>,
137 private final FutureJVppSnatFacade jvppSnat;
139 AddressRangeDumpExecutor(final FutureJVppSnatFacade jvppSnat) {
140 this.jvppSnat = jvppSnat;
145 public SnatAddressDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
146 throws ReadFailedException {
147 return getReplyForRead(jvppSnat.snatAddressDump(new SnatAddressDump()).toCompletableFuture(), identifier);