HONEYCOMB-58 - Routing Api
[honeycomb.git] / nat / nat2vpp / src / main / java / io / fd / honeycomb / nat / read / MappingEntryCustomizer.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
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:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package io.fd.honeycomb.nat.read;
18
19 import io.fd.honeycomb.nat.util.MappingEntryContext;
20 import io.fd.honeycomb.translate.read.ReadContext;
21 import io.fd.honeycomb.translate.read.ReadFailedException;
22 import io.fd.honeycomb.translate.spi.read.Initialized;
23 import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
24 import io.fd.honeycomb.translate.util.RWUtils;
25 import io.fd.honeycomb.translate.util.read.cache.DumpCacheManager;
26 import io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor;
27 import io.fd.honeycomb.translate.vpp.util.Ipv4Translator;
28 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
29 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetails;
30 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDetailsReplyDump;
31 import io.fd.vpp.jvpp.snat.dto.SnatStaticMappingDump;
32 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
33 import java.util.List;
34 import java.util.stream.Collectors;
35 import javax.annotation.Nonnull;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.ExternalSrcPortBuilder;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.mapping.entry.InternalSrcPortBuilder;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.MappingTable;
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.nat.instance.MappingTableBuilder;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntry;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntryBuilder;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.state.nat.instances.nat.instance.mapping.table.MappingEntryKey;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.port.number.port.type.SinglePortNumberBuilder;
47 import org.opendaylight.yangtools.concepts.Builder;
48 import org.opendaylight.yangtools.yang.binding.DataObject;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 final class MappingEntryCustomizer implements Ipv4Translator,
54         InitializingListReaderCustomizer<MappingEntry, MappingEntryKey, MappingEntryBuilder> {
55
56     private static final Logger LOG = LoggerFactory.getLogger(MappingEntryCustomizer.class);
57
58     private final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager;
59     private final MappingEntryContext mappingEntryContext;
60
61     MappingEntryCustomizer(
62             final DumpCacheManager<SnatStaticMappingDetailsReplyDump, Void> dumpCacheManager,
63             final MappingEntryContext mappingEntryContext) {
64         this.dumpCacheManager = dumpCacheManager;
65         this.mappingEntryContext = mappingEntryContext;
66     }
67
68     @Nonnull
69     @Override
70     public MappingEntryBuilder getBuilder(@Nonnull final InstanceIdentifier<MappingEntry> id) {
71         return new MappingEntryBuilder();
72     }
73
74     @Override
75     public void readCurrentAttributes(@Nonnull final InstanceIdentifier<MappingEntry> id,
76                                       @Nonnull final MappingEntryBuilder builder, @Nonnull final ReadContext ctx)
77             throws ReadFailedException {
78         LOG.trace("Reading current attributes for mapping-entry: {}", id);
79
80         final int idx = id.firstKeyOf(MappingEntry.class).getIndex().intValue();
81         final int natInstanceId = id.firstKeyOf(NatInstance.class).getId().intValue();
82         final List<SnatStaticMappingDetails> details =
83                 dumpCacheManager.getDump(id, ctx.getModificationCache(), null)
84                         .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails;
85         final SnatStaticMappingDetails snatStaticMappingDetails =
86                 mappingEntryContext.findDetails(details, natInstanceId, idx, ctx.getMappingContext());
87
88         builder.setIndex((long) idx);
89         builder.setType(
90                 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static);
91         // Snat only supports ipv4 for now
92         builder.setExternalSrcAddress(arrayToIpv4AddressNoZoneReversed(snatStaticMappingDetails.externalIpAddress));
93         builder.setInternalSrcAddress(
94                 new IpAddress(arrayToIpv4AddressNoZoneReversed(snatStaticMappingDetails.localIpAddress)));
95
96         if (snatStaticMappingDetails.addrOnly == 0) {
97             builder.setExternalSrcPort(new ExternalSrcPortBuilder()
98                     .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber(
99                             (int) snatStaticMappingDetails.externalPort))
100                             .build())
101                     .build());
102             builder.setInternalSrcPort(new InternalSrcPortBuilder()
103                     .setPortType(new SinglePortNumberBuilder().setSinglePortNumber(new PortNumber(
104                             (int) snatStaticMappingDetails.localPort))
105                             .build())
106                     .build());
107         }
108
109         LOG.trace("Mapping-entry read as: {}", builder);
110     }
111
112     @Nonnull
113     @Override
114     public List<MappingEntryKey> getAllIds(@Nonnull final InstanceIdentifier<MappingEntry> id,
115                                            @Nonnull final ReadContext context) throws ReadFailedException {
116         final Long natInstanceId = id.firstKeyOf(NatInstance.class).getId();
117         LOG.trace("Listing IDs for all mapping-entries within nat-instance(vrf):{}", natInstanceId);
118
119         final List<MappingEntryKey> entryKeys =
120                 dumpCacheManager.getDump(id, context.getModificationCache(), null)
121                         .or(new SnatStaticMappingDetailsReplyDump()).snatStaticMappingDetails.stream()
122                         .filter(detail -> natInstanceId == detail.vrfId)
123                         .map(detail -> mappingEntryContext
124                                 .getStoredOrArtificialIndex(natInstanceId, detail, context.getMappingContext()))
125                         .map(MappingEntryKey::new)
126                         .collect(Collectors.toList());
127         LOG.debug("List of mapping-entry keys within nat-instance(vrf):{} : {}", natInstanceId, entryKeys);
128
129         return entryKeys;
130     }
131
132     @Override
133     public void merge(@Nonnull final Builder<? extends DataObject> builder,
134                       @Nonnull final List<MappingEntry> readData) {
135         ((MappingTableBuilder) builder).setMappingEntry(readData);
136     }
137
138     @Override
139     public Initialized<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> init(@Nonnull final InstanceIdentifier<MappingEntry> id,
140                                                                                                                                                                           @Nonnull final MappingEntry readValue,
141                                                                                                                                                                           @Nonnull final ReadContext ctx) {
142         return Initialized.create(getCfgId(id),
143                 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder(readValue)
144                         .build());
145     }
146
147     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry> getCfgId(final @Nonnull InstanceIdentifier<MappingEntry> id) {
148         return NatInstanceCustomizer.getCfgId(RWUtils.cutId(id, NatInstance.class))
149                 .child(MappingTable.class)
150                 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry.class,
151                         new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryKey(id.firstKeyOf(MappingEntry.class).getIndex()));
152     }
153
154     static final class MappingEntryDumpExecutor
155             implements EntityDumpExecutor<SnatStaticMappingDetailsReplyDump, Void>, JvppReplyConsumer {
156
157         private final FutureJVppSnatFacade jvppSnat;
158
159         MappingEntryDumpExecutor(final FutureJVppSnatFacade jvppSnat) {
160             this.jvppSnat = jvppSnat;
161         }
162
163         @Nonnull
164         @Override
165         public SnatStaticMappingDetailsReplyDump executeDump(final InstanceIdentifier<?> identifier, final Void params)
166                 throws ReadFailedException {
167             return getReplyForRead(jvppSnat.snatStaticMappingDump(new SnatStaticMappingDump()).toCompletableFuture(),
168                     identifier);
169         }
170     }
171 }