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.v3po.translate.v3po.interfaces.ip;
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
22 import com.google.common.base.Optional;
23 import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer;
24 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
25 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
26 import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException;
27 import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils;
28 import io.fd.honeycomb.v3po.translate.write.WriteContext;
29 import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
30 import java.util.concurrent.CompletionStage;
31 import javax.annotation.Nonnull;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.Subnet;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.Netmask;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength;
39 import org.opendaylight.yangtools.yang.binding.DataObject;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import org.openvpp.jvpp.dto.SwInterfaceAddDelAddress;
42 import org.openvpp.jvpp.dto.SwInterfaceAddDelAddressReply;
43 import org.openvpp.jvpp.future.FutureJVpp;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public class Ipv4Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Ipv4> {
49 private static final Logger LOG = LoggerFactory.getLogger(Ipv4Customizer.class);
50 private final NamingContext interfaceContext;
52 public Ipv4Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext) {
54 this.interfaceContext = interfaceContext;
57 // TODO replace guava's Optionals with Java8
60 public Optional<Ipv4> extract(@Nonnull final InstanceIdentifier<Ipv4> currentId,
61 @Nonnull final DataObject parentData) {
62 return Optional.fromNullable(((Interface1) parentData).getIpv4());
66 public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Ipv4> id,
67 @Nonnull final Ipv4 dataAfter, @Nonnull final WriteContext writeContext)
68 throws WriteFailedException {
70 final String ifcName = id.firstKeyOf(Interface.class).getName();
71 setIpv4(id, ifcName, dataAfter, writeContext);
72 } catch (VppApiInvocationException e) {
73 LOG.warn("Create of Ipv4 failed", e);
74 throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
79 public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Ipv4> id,
80 @Nonnull final Ipv4 dataBefore, @Nonnull final Ipv4 dataAfter,
81 @Nonnull final WriteContext writeContext)
82 throws WriteFailedException {
83 final String ifcName = id.firstKeyOf(Interface.class).getName();
85 // TODO handle update in a better way
87 setIpv4(id, ifcName, dataAfter, writeContext);
88 } catch (VppApiInvocationException e) {
89 LOG.warn("Update of Ipv4 failed", e);
90 throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
95 public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Ipv4> id,
96 @Nonnull final Ipv4 dataBefore, @Nonnull final WriteContext writeContext) {
97 // TODO implement delete
100 private void setIpv4(final InstanceIdentifier<Ipv4> id, final String name, final Ipv4 ipv4,
101 final WriteContext writeContext)
102 throws WriteFailedException, VppApiInvocationException {
103 final int swIfc = interfaceContext.getIndex(name, writeContext.getMappingContext());
105 for (Address ipv4Addr : ipv4.getAddress()) {
106 Subnet subnet = ipv4Addr.getSubnet();
108 if (subnet instanceof PrefixLength) {
109 setPrefixLengthSubnet(name, swIfc, ipv4Addr, (PrefixLength) subnet);
110 } else if (subnet instanceof Netmask) {
113 // FIXME how does choice extensibility work
114 // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject
115 // FIXME we might need a choice customizer
116 // THis choice is already from augment, so its probably not possible to augment augmented choice
117 LOG.error("Unable to handle subnet of type {}", subnet.getClass());
118 throw new WriteFailedException(id, "Unable to handle subnet of type " + subnet.getClass());
123 private void setNetmaskSubnet() {
125 throw new UnsupportedOperationException("Unimplemented");
128 private void setPrefixLengthSubnet(final String name, final int swIfc, final Address ipv4Addr,
129 final PrefixLength subnet) throws VppApiInvocationException {
130 Short plen = subnet.getPrefixLength();
131 LOG.debug("Setting Subnet(prefix-length) for interface: {}, {}. Subnet: {}, Ipv4: {}", name, swIfc, subnet,
134 byte[] addr = V3poUtils.ipv4AddressNoZoneToArray(ipv4Addr.getIp());
136 checkArgument(plen > 0, "Invalid length");
137 checkNotNull(addr, "Null address");
139 final CompletionStage<SwInterfaceAddDelAddressReply> swInterfaceAddDelAddressReplyCompletionStage =
140 getFutureJVpp().swInterfaceAddDelAddress(getSwInterfaceAddDelAddressRequest(
141 swIfc, (byte) 1 /* isAdd */, (byte) 0 /* isIpv6 */, (byte) 0 /* delAll */, plen.byteValue(), addr));
143 final SwInterfaceAddDelAddressReply reply =
144 V3poUtils.getReply(swInterfaceAddDelAddressReplyCompletionStage.toCompletableFuture());
146 if (reply.retval < 0) {
147 LOG.warn("Failed to set Subnet(prefix-length) for interface: {}, {}, Subnet: {}, Ipv4: {}", name, swIfc,
149 throw new VppApiInvocationException("swInterfaceAddDelAddress", reply.context, reply.retval);
151 LOG.debug("Subnet(prefix-length) set successfully for interface: {}, {}, Subnet: {}, Ipv4: {}", name,
152 swIfc, subnet, ipv4Addr);
156 private SwInterfaceAddDelAddress getSwInterfaceAddDelAddressRequest(final int swIfc, final byte isAdd, final byte ipv6,
157 final byte deleteAll,
158 final byte length, final byte[] addr) {
159 final SwInterfaceAddDelAddress swInterfaceAddDelAddress = new SwInterfaceAddDelAddress();
160 swInterfaceAddDelAddress.swIfIndex = swIfc;
161 swInterfaceAddDelAddress.isAdd = isAdd;
162 swInterfaceAddDelAddress.isIpv6 = ipv6;
163 swInterfaceAddDelAddress.delAll = deleteAll;
164 swInterfaceAddDelAddress.address = addr;
165 swInterfaceAddDelAddress.addressLength = length;
166 return swInterfaceAddDelAddress;