bafe788ad4f8d4fd2b28571053105a9a1986cd47
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / v3po / translate / v3po / interfaces / TapCustomizer.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.v3po.translate.v3po.interfaces;
18
19 import com.google.common.base.Optional;
20 import io.fd.honeycomb.v3po.translate.v3po.util.AbstractInterfaceTypeCustomizer;
21 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
22 import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException;
23 import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils;
24 import io.fd.honeycomb.v3po.translate.write.WriteContext;
25 import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
26 import java.util.concurrent.CompletionStage;
27 import javax.annotation.Nonnull;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Tap;
33 import org.opendaylight.yangtools.yang.binding.DataObject;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.openvpp.jvpp.dto.TapConnect;
36 import org.openvpp.jvpp.dto.TapConnectReply;
37 import org.openvpp.jvpp.dto.TapDelete;
38 import org.openvpp.jvpp.dto.TapDeleteReply;
39 import org.openvpp.jvpp.dto.TapModify;
40 import org.openvpp.jvpp.dto.TapModifyReply;
41 import org.openvpp.jvpp.future.FutureJVpp;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 public class TapCustomizer extends AbstractInterfaceTypeCustomizer<Tap> {
46
47     private static final Logger LOG = LoggerFactory.getLogger(TapCustomizer.class);
48     private final NamingContext interfaceContext;
49
50     public TapCustomizer(final FutureJVpp vppApi, final NamingContext interfaceContext) {
51         super(vppApi);
52         this.interfaceContext = interfaceContext;
53     }
54
55     @Nonnull
56     @Override
57     public Optional<Tap> extract(@Nonnull final InstanceIdentifier<Tap> currentId,
58                                    @Nonnull final DataObject parentData) {
59         return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getTap());
60     }
61
62     @Override
63     protected Class<? extends InterfaceType> getExpectedInterfaceType() {
64         return org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap.class;
65     }
66
67     @Override
68     protected final void writeInterface(@Nonnull final InstanceIdentifier<Tap> id, @Nonnull final Tap dataAfter,
69                                        @Nonnull final WriteContext writeContext)
70         throws WriteFailedException.CreateFailedException {
71         try {
72             createTap(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext);
73         } catch (VppApiInvocationException e) {
74             LOG.warn("Write of Tap failed", e);
75             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
76         }
77     }
78
79     @Override
80     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Tap> id, @Nonnull final Tap dataBefore,
81                                         @Nonnull final Tap dataAfter, @Nonnull final WriteContext writeContext)
82         throws WriteFailedException.UpdateFailedException {
83         final String ifcName = id.firstKeyOf(Interface.class).getName();
84
85         final int index;
86         try {
87             index = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
88         } catch (IllegalArgumentException e) {
89             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
90         }
91
92         try {
93             modifyTap(ifcName, index, dataAfter);
94         } catch (VppApiInvocationException e) {
95             LOG.warn("Write of Tap failed", e);
96             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
97         }
98     }
99
100     @Override
101     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Tap> id, @Nonnull final Tap dataBefore,
102                                         @Nonnull final WriteContext writeContext)
103         throws WriteFailedException.DeleteFailedException {
104         final String ifcName = id.firstKeyOf(Interface.class).getName();
105
106         final int index;
107         try {
108             index = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
109         } catch (IllegalArgumentException e) {
110             throw new WriteFailedException.DeleteFailedException(id, e);
111         }
112
113         try {
114             deleteTap(ifcName, index, dataBefore, writeContext);
115         } catch (VppApiInvocationException e) {
116             LOG.warn("Delete of Tap failed", e);
117             throw new WriteFailedException.DeleteFailedException(id, e);
118         }
119     }
120
121     private void createTap(final String swIfName, final Tap tap, final WriteContext writeContext) throws VppApiInvocationException {
122         LOG.debug("Setting tap interface: {}. Tap: {}", swIfName, tap);
123         final CompletionStage<TapConnectReply> tapConnectFuture =
124             getFutureJVpp().tapConnect(getTapConnectRequest(tap.getTapName(), tap.getMac(), tap.getDeviceInstance()));
125         final TapConnectReply reply =
126             V3poUtils.getReply(tapConnectFuture.toCompletableFuture());
127         if (reply.retval < 0) {
128             LOG.warn("Failed to set tap interface: {}, tap: {}", swIfName, tap);
129             throw new VppApiInvocationException("tap_connect", reply.context, reply.retval);
130         } else {
131             LOG.debug("Tap set successfully for: {}, tap: {}", swIfName, tap);
132             // Add new interface to our interface context
133             interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext());
134         }
135     }
136
137     private void modifyTap(final String swIfName, final int index, final Tap tap) throws VppApiInvocationException {
138         LOG.debug("Modifying tap interface: {}. Tap: {}", swIfName, tap);
139         final CompletionStage<TapModifyReply> vxlanAddDelTunnelReplyCompletionStage =
140             getFutureJVpp().tapModify(getTapModifyRequest(tap.getTapName(), index, tap.getMac(), tap.getDeviceInstance()));
141         final TapModifyReply reply =
142             V3poUtils.getReply(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture());
143         if (reply.retval < 0) {
144             LOG.warn("Failed to modify tap interface: {}, tap: {}", swIfName, tap);
145             throw new VppApiInvocationException("tap_modify", reply.context, reply.retval);
146         } else {
147             LOG.debug("Tap modified successfully for: {}, tap: {}", swIfName, tap);
148         }
149     }
150
151     private void deleteTap(final String swIfName, final int index, final Tap dataBefore,
152                            final WriteContext writeContext)
153         throws VppApiInvocationException {
154         LOG.debug("Deleting tap interface: {}. Tap: {}", swIfName, dataBefore);
155         final CompletionStage<TapDeleteReply> vxlanAddDelTunnelReplyCompletionStage =
156             getFutureJVpp().tapDelete(getTapDeleteRequest(index));
157         final TapDeleteReply reply =
158             V3poUtils.getReply(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture());
159         if (reply.retval < 0) {
160             LOG.warn("Failed to delete tap interface: {}, tap: {}", swIfName, dataBefore);
161             throw new VppApiInvocationException("tap_modify", reply.context, reply.retval);
162         } else {
163             LOG.debug("Tap deleted successfully for: {}, tap: {}", swIfName, dataBefore);
164             // Remove deleted interface from interface context
165             interfaceContext.removeName(swIfName, writeContext.getMappingContext());
166         }
167     }
168
169     private TapConnect getTapConnectRequest(final String tapName, final PhysAddress mac, final Long deviceInstance) {
170         final TapConnect tapConnect = new TapConnect();
171         tapConnect.tapName = tapName.getBytes();
172
173         if(mac == null) {
174             tapConnect.useRandomMac = 1;
175             tapConnect.macAddress = new byte[6];
176         } else {
177             tapConnect.useRandomMac = 0;
178             tapConnect.macAddress = V3poUtils.parseMac(mac.getValue());
179         }
180
181         if(deviceInstance == null) {
182             tapConnect.renumber = 0;
183         } else {
184             tapConnect.renumber = 1;
185             tapConnect.customDevInstance = Math.toIntExact(deviceInstance);
186         }
187
188         return tapConnect;
189     }
190
191     private TapModify getTapModifyRequest(final String tapName, final int swIndex, final PhysAddress mac, final Long deviceInstance) {
192         final TapModify tapConnect = new TapModify();
193         tapConnect.tapName = tapName.getBytes();
194         tapConnect.swIfIndex = swIndex;
195
196         if(mac == null) {
197             tapConnect.useRandomMac = 1;
198             tapConnect.macAddress = new byte[6];
199         } else {
200             tapConnect.useRandomMac = 0;
201             tapConnect.macAddress = V3poUtils.parseMac(mac.getValue());
202         }
203
204         if(deviceInstance == null) {
205             tapConnect.renumber = 0;
206         } else {
207             tapConnect.renumber = 1;
208             tapConnect.customDevInstance = Math.toIntExact(deviceInstance);
209         }
210
211         return tapConnect;
212     }
213
214     private TapDelete getTapDeleteRequest(final int swIndex) {
215         final TapDelete tapConnect = new TapDelete();
216         tapConnect.swIfIndex = swIndex;
217         return tapConnect;
218     }
219 }