HONEYCOMB-58 - Routing Api
[honeycomb.git] / nat / nat2vpp / src / main / java / io / fd / honeycomb / nat / write / ExternalIpPoolCustomizer.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.write;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20
21 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
22 import io.fd.honeycomb.translate.vpp.util.Ipv4AddressRange;
23 import io.fd.honeycomb.translate.vpp.util.Ipv4Translator;
24 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
25 import io.fd.honeycomb.translate.write.WriteContext;
26 import io.fd.honeycomb.translate.write.WriteFailedException;
27 import io.fd.vpp.jvpp.snat.dto.SnatAddAddressRange;
28 import io.fd.vpp.jvpp.snat.future.FutureJVppSnatFacade;
29 import javax.annotation.Nonnull;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolKey;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 final class ExternalIpPoolCustomizer implements ListWriterCustomizer<ExternalIpAddressPool, ExternalIpAddressPoolKey>,
39         JvppReplyConsumer, Ipv4Translator {
40
41     private static final Logger LOG = LoggerFactory.getLogger(ExternalIpPoolCustomizer.class);
42
43     private final FutureJVppSnatFacade jvppSnat;
44
45     ExternalIpPoolCustomizer(@Nonnull final FutureJVppSnatFacade jvppSnat) {
46         this.jvppSnat = jvppSnat;
47     }
48
49     @Override
50     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<ExternalIpAddressPool> id,
51                                        @Nonnull final ExternalIpAddressPool dataAfter,
52                                        @Nonnull final WriteContext writeContext) throws WriteFailedException {
53         checkArgument(id.firstKeyOf(NatInstance.class).getId() == 0,
54                 "External IP pools are only assignable for nat instance(vrf-id) with ID 0");
55         LOG.trace("Adding address range:{}, as: {}", id, dataAfter);
56         // TODO check overlaps ? VPP-478 maybe no necessary, depending on how VPP handles them
57         getReplyForCreate(jvppSnat.snatAddAddressRange(
58                 getRequest(dataAfter.getExternalIpPool(), true)).toCompletableFuture(), id, dataAfter);
59         LOG.debug("Address range: {} added successfully", id);
60     }
61
62     @Override
63     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<ExternalIpAddressPool> id,
64                                         @Nonnull final ExternalIpAddressPool dataBefore,
65                                         @Nonnull final ExternalIpAddressPool dataAfter,
66                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
67         throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter,
68                 new UnsupportedOperationException("Address range update is not supported"));
69     }
70
71     @Override
72     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<ExternalIpAddressPool> id,
73                                         @Nonnull final ExternalIpAddressPool dataBefore,
74                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
75         LOG.trace("Deleting address range:{}, as: {}", id, dataBefore);
76         getReplyForDelete(jvppSnat.snatAddAddressRange(
77                 getRequest(dataBefore.getExternalIpPool(), false)).toCompletableFuture(), id);
78         LOG.debug("Deleting range: {} added successfully", id);
79     }
80
81     private SnatAddAddressRange getRequest(final Ipv4Prefix externalIpPool, boolean isAdd) {
82         SnatAddAddressRange request = new SnatAddAddressRange();
83         // SNAT supports only IPv4 now, so does the model
84         final Ipv4AddressRange range = Ipv4AddressRange.fromPrefix(externalIpPool);
85         LOG.trace("Handling address range: {}", range);
86         request.isIp4 = 1;
87         request.isAdd = (byte) (isAdd ? 1 : 0);
88         request.firstIpAddress = ipv4AddressNoZoneToArray(range.getStart());
89         request.lastIpAddress = ipv4AddressNoZoneToArray(range.getEnd());
90         return request;
91     }
92 }