5aea5de2b4a4274e2bcefd9b678605f443158a8d
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / v3po / translate / v3po / interfaces / L2Customizer.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 static com.google.common.base.Preconditions.checkArgument;
20
21 import com.google.common.base.Optional;
22 import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer;
23 import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext;
24 import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer;
25 import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException;
26 import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils;
27 import io.fd.honeycomb.v3po.translate.write.WriteContext;
28 import io.fd.honeycomb.v3po.translate.write.WriteFailedException;
29 import java.util.concurrent.CompletionStage;
30 import javax.annotation.Nonnull;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.Interconnection;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBased;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.XconnectBased;
37 import org.opendaylight.yangtools.yang.binding.DataObject;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.openvpp.jvpp.dto.SwInterfaceSetL2Bridge;
40 import org.openvpp.jvpp.dto.SwInterfaceSetL2BridgeReply;
41 import org.openvpp.jvpp.dto.SwInterfaceSetL2Xconnect;
42 import org.openvpp.jvpp.dto.SwInterfaceSetL2XconnectReply;
43 import org.openvpp.jvpp.future.FutureJVpp;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer<L2> {
48
49     private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class);
50     private final NamingContext interfaceContext;
51     private final NamingContext bridgeDomainContext;
52
53     public L2Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext,
54                         final NamingContext bridgeDomainContext) {
55         super(vppApi);
56         this.interfaceContext = interfaceContext;
57         this.bridgeDomainContext = bridgeDomainContext;
58     }
59
60     @Nonnull
61     @Override
62     public Optional<L2> extract(@Nonnull final InstanceIdentifier<L2> currentId, @Nonnull final DataObject parentData) {
63         return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getL2());
64     }
65
66     @Override
67     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter,
68                                        @Nonnull final WriteContext writeContext)
69         throws WriteFailedException {
70
71         final String ifcName = id.firstKeyOf(Interface.class).getName();
72         final int swIfc = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
73         try {
74             setL2(id, swIfc, ifcName, dataAfter, writeContext);
75         } catch (VppApiInvocationException e) {
76             LOG.warn("Write of L2 failed", e);
77             throw new WriteFailedException.CreateFailedException(id, dataAfter, e);
78         }
79     }
80
81     @Override
82     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
83                                         @Nonnull final L2 dataAfter, @Nonnull final WriteContext writeContext)
84         throws WriteFailedException {
85
86         final String ifcName = id.firstKeyOf(Interface.class).getName();
87         final int swIfc = interfaceContext.getIndex(ifcName, writeContext.getMappingContext());
88         // TODO handle update properly (if possible)
89         try {
90             setL2(id, swIfc, ifcName, dataAfter, writeContext);
91         } catch (VppApiInvocationException e) {
92             LOG.warn("Update of L2 failed", e);
93             throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);
94         }
95     }
96
97     @Override
98     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
99                                         @Nonnull final WriteContext writeContext) {
100         // TODO implement delete (if possible)
101     }
102
103     private void setL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 vppL2,
104                        final WriteContext writeContext)
105         throws VppApiInvocationException, WriteFailedException {
106         LOG.debug("Setting L2 for interface: {}", ifcName);
107         // Nothing besides interconnection here
108         setInterconnection(id, swIfIndex, ifcName, vppL2, writeContext);
109     }
110
111     private void setInterconnection(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName,
112                                     final L2 vppL2, final WriteContext writeContext)
113         throws VppApiInvocationException, WriteFailedException {
114         Interconnection ic = vppL2.getInterconnection();
115         if (ic instanceof XconnectBased) {
116             setXconnectBasedL2(swIfIndex, ifcName, (XconnectBased) ic, writeContext);
117         } else if (ic instanceof BridgeBased) {
118             setBridgeBasedL2(swIfIndex, ifcName, (BridgeBased) ic, writeContext);
119         } else {
120             // FIXME how does choice extensibility work
121             // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject
122             // FIXME we might need a choice customizer
123             // THis choice is already from augment, so its probably not possible to augment augmented choice
124             LOG.error("Unable to handle Interconnection of type {}", ic.getClass());
125             throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass());
126         }
127     }
128
129     private void setBridgeBasedL2(final int swIfIndex, final String ifcName, final BridgeBased bb,
130                                   final WriteContext writeContext)
131         throws VppApiInvocationException {
132
133         LOG.debug("Setting bridge based interconnection(bridge-domain={}) for interface: {}",
134             bb.getBridgeDomain(), ifcName);
135
136         String bdName = bb.getBridgeDomain();
137
138         int bdId = bridgeDomainContext.getIndex(bdName, writeContext.getMappingContext());
139         checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist",
140             ifcName, bdName);
141
142         byte bvi = bb.isBridgedVirtualInterface()
143             ? (byte) 1
144             : (byte) 0;
145         byte shg = bb.getSplitHorizonGroup().byteValue();
146
147         final CompletionStage<SwInterfaceSetL2BridgeReply> swInterfaceSetL2BridgeReplyCompletionStage = getFutureJVpp()
148             .swInterfaceSetL2Bridge(getL2BridgeRequest(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */));
149         final SwInterfaceSetL2BridgeReply reply =
150             V3poUtils.getReply(swInterfaceSetL2BridgeReplyCompletionStage.toCompletableFuture());
151
152         if (reply.retval < 0) {
153             LOG.warn("Failed to update bridge based interconnection flags for: {}, interconnection: {}", ifcName,
154                 bb);
155             throw new VppApiInvocationException("swInterfaceSetL2Bridge", reply.context, reply.retval);
156         } else {
157             LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifcName,
158                 bb);
159         }
160     }
161
162     private SwInterfaceSetL2Bridge getL2BridgeRequest(final int swIfIndex, final int bdId, final byte shg,
163                                                       final byte bvi, final byte enabled) {
164         final SwInterfaceSetL2Bridge swInterfaceSetL2Bridge = new SwInterfaceSetL2Bridge();
165         swInterfaceSetL2Bridge.rxSwIfIndex = swIfIndex;
166         swInterfaceSetL2Bridge.bdId = bdId;
167         swInterfaceSetL2Bridge.shg = shg;
168         swInterfaceSetL2Bridge.bvi = bvi;
169         swInterfaceSetL2Bridge.enable = enabled;
170         return swInterfaceSetL2Bridge;
171     }
172
173     private void setXconnectBasedL2(final int swIfIndex, final String ifcName, final XconnectBased ic,
174                                     final WriteContext writeContext)
175         throws VppApiInvocationException {
176
177         String outSwIfName = ic.getXconnectOutgoingInterface();
178         LOG.debug("Setting xconnect based interconnection(outgoing ifc={}) for interface: {}", outSwIfName,
179             ifcName);
180
181         int outSwIfIndex = interfaceContext.getIndex(outSwIfName, writeContext.getMappingContext());
182         checkArgument(outSwIfIndex > 0,
183             "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist",
184             ifcName, outSwIfIndex);
185
186         final CompletionStage<SwInterfaceSetL2XconnectReply> swInterfaceSetL2XconnectReplyCompletionStage =
187             getFutureJVpp()
188                 .swInterfaceSetL2Xconnect(getL2XConnectRequest(swIfIndex, outSwIfIndex, (byte) 1 /* enable */));
189         final SwInterfaceSetL2XconnectReply reply =
190             V3poUtils.getReply(swInterfaceSetL2XconnectReplyCompletionStage.toCompletableFuture());
191
192         if (reply.retval < 0) {
193             LOG.warn("Failed to update xconnect based interconnection flags for: {}, interconnection: {}",
194                 ifcName, ic);
195             throw new VppApiInvocationException("swInterfaceSetL2Xconnect", reply.context, reply.retval);
196         } else {
197             LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifcName,
198                 ic);
199         }
200     }
201
202     private SwInterfaceSetL2Xconnect getL2XConnectRequest(final int rxIfc, final int txIfc,
203                                                           final byte enabled) {
204
205         final SwInterfaceSetL2Xconnect swInterfaceSetL2Xconnect = new SwInterfaceSetL2Xconnect();
206         swInterfaceSetL2Xconnect.enable = enabled;
207         swInterfaceSetL2Xconnect.rxSwIfIndex = rxIfc;
208         swInterfaceSetL2Xconnect.txSwIfIndex = txIfc;
209         return swInterfaceSetL2Xconnect;
210     }
211 }