c99fcd29f9f2f52c96dcbeb2bfd19a951d03e48c
[hc2vpp.git] /
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 package io.fd.honeycomb.v3po.translate.v3po.interfaces.ip;
17
18 import static com.google.common.base.Preconditions.checkArgument;
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import com.google.common.base.Optional;
22 import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer;
23 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
24 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
25 import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils;
26 import io.fd.honeycomb.v3po.translate.write.WriteContext;
27 import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
28 import java.util.List;
29 import java.util.concurrent.CompletionStage;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Address;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.AddressKey;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.Subnet;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.Netmask;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength;
37 import org.opendaylight.yangtools.yang.binding.DataObject;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.openvpp.jvpp.VppBaseCallException;
40 import org.openvpp.jvpp.dto.SwInterfaceAddDelAddress;
41 import org.openvpp.jvpp.dto.SwInterfaceAddDelAddressReply;
42 import org.openvpp.jvpp.future.FutureJVpp;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 /**
47  * Customizer for writing {@link Address}
48  *
49  * @author jsrnicek
50  */
51 public class AddressCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer<Address, AddressKey> {
52
53     private static final Logger LOG = LoggerFactory.getLogger(AddressCustomizer.class);
54     private final NamingContext interfaceContext;
55
56     public AddressCustomizer(FutureJVpp futureJvpp, NamingContext interfaceContext) {
57         super(futureJvpp);
58         this.interfaceContext = interfaceContext;
59     }
60
61     @Override
62     public void writeCurrentAttributes(InstanceIdentifier<Address> id, Address dataAfter, WriteContext writeContext)
63             throws WriteFailedException {
64         setAddress(true, id, dataAfter, writeContext);
65     }
66
67     @Override
68     public void updateCurrentAttributes(InstanceIdentifier<Address> id, Address dataBefore, Address dataAfter,
69             WriteContext writeContext) throws WriteFailedException {
70         throw new WriteFailedException.UpdateFailedException(id,dataBefore,dataAfter,new UnsupportedOperationException("Operation not supported"));
71     }
72
73     @Override
74     public void deleteCurrentAttributes(InstanceIdentifier<Address> id, Address dataBefore, WriteContext writeContext)
75             throws WriteFailedException {
76         setAddress(false, id, dataBefore, writeContext);
77     }
78
79     @Override
80     public Optional<List<Address>> extract(InstanceIdentifier<Address> currentId, DataObject parentData) {
81         return Optional.fromNullable((((Ipv4)parentData).getAddress()));
82     }
83
84     private void setAddress(boolean add,final InstanceIdentifier<Address> id,  final Address address,
85             final WriteContext writeContext) throws WriteFailedException {
86
87         final String interfaceName = id.firstKeyOf(Interface.class).getName();
88         final int swIfc = interfaceContext.getIndex(interfaceName, writeContext.getMappingContext());
89
90         Subnet subnet = address.getSubnet();
91
92         if (subnet instanceof PrefixLength) {
93             setPrefixLengthSubnet(add,id, interfaceName, swIfc, address, (PrefixLength) subnet);
94         } else if (subnet instanceof Netmask) {
95             setNetmaskSubnet();
96         } else {
97             // FIXME how does choice extensibility work
98             // FIXME it is not even possible to create a dedicated
99             // customizer for Interconnection, since it's not a DataObject
100             // FIXME we might need a choice customizer
101             // THis choice is already from augment, so its probably not
102             // possible to augment augmented choice
103             LOG.error("Unable to handle subnet of type {}", subnet.getClass());
104             throw new WriteFailedException(id, "Unable to handle subnet of type " + subnet.getClass());
105         }
106     }
107
108     private void setNetmaskSubnet() {
109         // FIXME
110         throw new UnsupportedOperationException("Unimplemented");
111     }
112
113     private void setPrefixLengthSubnet(boolean add,final InstanceIdentifier<Address> id, final String name, final int swIfc,
114             final Address address, final PrefixLength subnet) throws WriteFailedException {
115         try {
116             Short plen = subnet.getPrefixLength();
117             LOG.debug("Setting Subnet(prefix-length) for interface: {}, {}. Subnet: {}, Address: {}", name, swIfc,
118                     subnet, address);
119
120             byte[] addr = TranslateUtils.ipv4AddressNoZoneToArray(address.getIp());
121
122             checkArgument(plen > 0, "Invalid length");
123             checkNotNull(addr, "Null address");
124
125             final CompletionStage<SwInterfaceAddDelAddressReply> swInterfaceAddDelAddressReplyCompletionStage = getFutureJVpp()
126                     .swInterfaceAddDelAddress(getSwInterfaceAddDelAddressRequest(swIfc, TranslateUtils.booleanToByte(add) /* isAdd */,
127                             (byte) 0 /* isIpv6 */, (byte) 0 /* delAll */, plen.byteValue(), addr));
128
129             TranslateUtils.getReply(swInterfaceAddDelAddressReplyCompletionStage.toCompletableFuture());
130
131             LOG.debug("Subnet(prefix-length) set successfully for interface: {}, {},  Subnet: {}, Address: {}", name,
132                     swIfc, subnet, address);
133         } catch (VppBaseCallException e) {
134             LOG.warn("Failed to set Subnet(prefix-length) for interface: {}, {},  Subnet: {}, Address: {}", name, swIfc,
135                     subnet, address);
136             throw new WriteFailedException(id, "Unable to handle subnet of type " + subnet.getClass(), e);
137         }
138     }
139
140     private SwInterfaceAddDelAddress getSwInterfaceAddDelAddressRequest(final int swIfc, final byte isAdd,
141             final byte ipv6, final byte deleteAll, final byte length, final byte[] addr) {
142         final SwInterfaceAddDelAddress swInterfaceAddDelAddress = new SwInterfaceAddDelAddress();
143         swInterfaceAddDelAddress.swIfIndex = swIfc;
144         swInterfaceAddDelAddress.isAdd = isAdd;
145         swInterfaceAddDelAddress.isIpv6 = ipv6;
146         swInterfaceAddDelAddress.delAll = deleteAll;
147         swInterfaceAddDelAddress.address = addr;
148         swInterfaceAddDelAddress.addressLength = length;
149         return swInterfaceAddDelAddress;
150     }
151
152 }