ecaaa471788a92cfc93bf9c30ceffb08b14b5fab
[honeycomb.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
17 package io.fd.honeycomb.translate.v3po.interfaces;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static java.util.Objects.requireNonNull;
21
22 import io.fd.honeycomb.translate.v3po.util.NamingContext;
23 import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException;
24 import io.fd.honeycomb.translate.write.WriteContext;
25 import io.fd.honeycomb.translate.write.WriteFailedException;
26 import io.fd.honeycomb.translate.v3po.util.TranslateUtils;
27 import java.util.concurrent.CompletionStage;
28 import javax.annotation.Nonnull;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.XconnectBased;
32 import org.opendaylight.yangtools.yang.binding.DataObject;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.openvpp.jvpp.VppBaseCallException;
35 import org.openvpp.jvpp.dto.SwInterfaceSetL2Bridge;
36 import org.openvpp.jvpp.dto.SwInterfaceSetL2BridgeReply;
37 import org.openvpp.jvpp.dto.SwInterfaceSetL2Xconnect;
38 import org.openvpp.jvpp.dto.SwInterfaceSetL2XconnectReply;
39 import org.openvpp.jvpp.future.FutureJVpp;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * Utility class providing Interconnection CUD support.
45  */
46 final class InterconnectionWriteUtils {
47
48     private static final Logger LOG = LoggerFactory.getLogger(InterconnectionWriteUtils.class);
49
50     private final FutureJVpp futureJvpp;
51     private final NamingContext interfaceContext;
52     private final NamingContext bridgeDomainContext;
53
54     InterconnectionWriteUtils(@Nonnull final FutureJVpp futureJvpp,
55                               @Nonnull final NamingContext interfaceContext,
56                               @Nonnull final NamingContext bridgeDomainContext) {
57         this.futureJvpp = requireNonNull(futureJvpp, "futureJvpp should not be null");
58         this.interfaceContext = requireNonNull(interfaceContext, "interfaceContext should not be null");
59         this.bridgeDomainContext = requireNonNull(bridgeDomainContext, "bridgeDomainContext should not be null");
60     }
61
62     void setInterconnection(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
63                             final String ifcName, final Interconnection ic, final WriteContext writeContext)
64         throws WriteFailedException {
65         try {
66             if (ic == null) { // TODO in case of update we should delete interconnection
67                 LOG.trace("Interconnection is not set. Skipping");
68             } else if (ic instanceof XconnectBased) {
69                 setXconnectBasedL2(id, swIfIndex, ifcName, (XconnectBased) ic, writeContext, (byte) 1 /*enable*/);
70             } else if (ic instanceof BridgeBased) {
71                 setBridgeBasedL2(id, swIfIndex, ifcName, (BridgeBased) ic, writeContext, (byte) 1 /*enable*/);
72             } else {
73                 // FIXME how does choice extensibility work
74                 // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject
75                 // FIXME we might need a choice customizer
76                 // THis choice is already from augment, so its probably not possible to augment augmented choice
77                 LOG.error("Unable to handle Interconnection of type {}", ic.getClass());
78                 throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass());
79             }
80         } catch (VppBaseCallException e) {
81             LOG.warn("Failed to update bridge/xconnect based interconnection flags for: {}, interconnection: {}",
82                 ifcName, ic);
83             throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass(), e);
84         }
85     }
86
87     void deleteInterconnection(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
88                                final String ifcName, final Interconnection ic, final WriteContext writeContext)
89         throws WriteFailedException {
90         try {
91             if (ic == null) { // TODO in case of update we should delete interconnection
92                 LOG.trace("Interconnection is not set. Skipping");
93             } else if (ic instanceof XconnectBased) {
94                 setXconnectBasedL2(id, swIfIndex, ifcName, (XconnectBased) ic, writeContext, (byte) 0 /*disable*/);
95             } else if (ic instanceof BridgeBased) {
96                 setBridgeBasedL2(id, swIfIndex, ifcName, (BridgeBased) ic, writeContext, (byte) 0 /*disable*/);
97             } else {
98                 LOG.error("Unable to delete Interconnection of type {}", ic.getClass());
99                 throw new WriteFailedException(id, "Unable to delete Interconnection of type " + ic.getClass());
100             }
101         } catch (VppBaseCallException e) {
102             LOG.warn("Failed to delete bridge/xconnect based interconnection flags for: {}, interconnection: {}",
103                 ifcName, ic);
104             throw new WriteFailedException(id, "Unable to delete Interconnection of type " + ic.getClass(), e);
105         }
106     }
107
108     private void setBridgeBasedL2(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
109                                   final String ifcName, final BridgeBased bb,
110                                   final WriteContext writeContext, final byte enabled)
111         throws VppBaseCallException, WriteTimeoutException {
112         LOG.debug("Setting bridge based interconnection(bridge-domain={}) for interface: {}", bb.getBridgeDomain(),
113             ifcName);
114
115         String bdName = bb.getBridgeDomain();
116
117         int bdId = bridgeDomainContext.getIndex(bdName, writeContext.getMappingContext());
118         checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist",
119             ifcName, bdName);
120
121         byte bvi = bb.isBridgedVirtualInterface()
122             ? (byte) 1
123             : (byte) 0;
124         byte shg = 0;
125         if (bb.getSplitHorizonGroup() != null) {
126             shg = bb.getSplitHorizonGroup().byteValue();
127         }
128
129         final CompletionStage<SwInterfaceSetL2BridgeReply> swInterfaceSetL2BridgeReplyCompletionStage = futureJvpp
130             .swInterfaceSetL2Bridge(getL2BridgeRequest(swIfIndex, bdId, shg, bvi, enabled));
131         TranslateUtils.getReplyForWrite(swInterfaceSetL2BridgeReplyCompletionStage.toCompletableFuture(), id);
132
133         LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifcName, bb);
134     }
135
136     private SwInterfaceSetL2Bridge getL2BridgeRequest(final int swIfIndex, final int bdId, final byte shg,
137                                                       final byte bvi, final byte enabled) {
138         final SwInterfaceSetL2Bridge swInterfaceSetL2Bridge = new SwInterfaceSetL2Bridge();
139         swInterfaceSetL2Bridge.rxSwIfIndex = swIfIndex;
140         swInterfaceSetL2Bridge.bdId = bdId;
141         swInterfaceSetL2Bridge.shg = shg;
142         swInterfaceSetL2Bridge.bvi = bvi;
143         swInterfaceSetL2Bridge.enable = enabled;
144         return swInterfaceSetL2Bridge;
145     }
146
147     private void setXconnectBasedL2(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex,
148                                     final String ifcName, final XconnectBased ic,
149                                     final WriteContext writeContext, final byte enabled)
150         throws VppBaseCallException, WriteTimeoutException {
151         String outSwIfName = ic.getXconnectOutgoingInterface();
152         LOG.debug("Setting xconnect based interconnection(outgoing ifc={}) for interface: {}", outSwIfName, ifcName);
153
154         int outSwIfIndex = interfaceContext.getIndex(outSwIfName, writeContext.getMappingContext());
155         checkArgument(outSwIfIndex > 0,
156             "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist",
157             ifcName, outSwIfIndex);
158
159         final CompletionStage<SwInterfaceSetL2XconnectReply> swInterfaceSetL2XconnectReplyCompletionStage =
160             futureJvpp
161                 .swInterfaceSetL2Xconnect(getL2XConnectRequest(swIfIndex, outSwIfIndex, enabled));
162         TranslateUtils.getReplyForWrite(swInterfaceSetL2XconnectReplyCompletionStage.toCompletableFuture(), id);
163         LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifcName, ic);
164     }
165
166     private SwInterfaceSetL2Xconnect getL2XConnectRequest(final int rxIfc, final int txIfc,
167                                                           final byte enabled) {
168
169         final SwInterfaceSetL2Xconnect swInterfaceSetL2Xconnect = new SwInterfaceSetL2Xconnect();
170         swInterfaceSetL2Xconnect.enable = enabled;
171         swInterfaceSetL2Xconnect.rxSwIfIndex = rxIfc;
172         swInterfaceSetL2Xconnect.txSwIfIndex = txIfc;
173         return swInterfaceSetL2Xconnect;
174     }
175 }