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.translate.v3po.vpp;
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
22 import com.google.common.base.Preconditions;
23 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
24 import io.fd.honeycomb.translate.vpp.util.ByteDataTranslator;
25 import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer;
26 import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer;
27 import io.fd.honeycomb.translate.vpp.util.NamingContext;
28 import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException;
29 import io.fd.honeycomb.translate.write.WriteContext;
30 import io.fd.honeycomb.translate.write.WriteFailedException;
31 import javax.annotation.Nonnull;
32 import javax.annotation.concurrent.GuardedBy;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.openvpp.jvpp.VppBaseCallException;
37 import org.openvpp.jvpp.core.dto.BridgeDomainAddDel;
38 import org.openvpp.jvpp.core.dto.BridgeDomainAddDelReply;
39 import org.openvpp.jvpp.core.future.FutureJVppCore;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 public class BridgeDomainCustomizer
44 extends FutureJVppCustomizer
45 implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey>, ByteDataTranslator, JvppReplyConsumer {
47 private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class);
49 private static final byte ADD_OR_UPDATE_BD = (byte) 1;
50 private final NamingContext bdContext;
52 private int bridgeDomainIndexCounter = 1;
54 public BridgeDomainCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
55 @Nonnull final NamingContext bdContext) {
56 super(futureJVppCore);
57 this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null");
60 private BridgeDomainAddDelReply addOrUpdateBridgeDomain(@Nonnull final InstanceIdentifier<BridgeDomain> id,
61 final int bdId, @Nonnull final BridgeDomain bd)
62 throws VppBaseCallException, WriteTimeoutException {
63 final BridgeDomainAddDelReply reply;
64 final BridgeDomainAddDel request = new BridgeDomainAddDel();
66 request.flood = booleanToByte(bd.isFlood());
67 request.forward = booleanToByte(bd.isForward());
68 request.learn = booleanToByte(bd.isLearn());
69 request.uuFlood = booleanToByte(bd.isUnknownUnicastFlood());
70 request.arpTerm = booleanToByte(bd.isArpTermination());
71 request.isAdd = ADD_OR_UPDATE_BD;
73 reply = getReplyForWrite(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture(), id);
74 LOG.debug("Bridge domain {} (id={}) add/update successful", bd.getName(), bdId);
79 public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
80 @Nonnull final BridgeDomain dataBefore,
81 @Nonnull final WriteContext ctx)
82 throws WriteFailedException {
83 LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, dataBefore, ctx);
84 final String bdName = dataBefore.getName();
86 // Invoke 1. check index, 2. increase index 3. create ND 4. store mapping in a synchronized block to prevent
87 // race conditions in case of concurrent invocation
91 if (bdContext.containsIndex(bdName, ctx.getMappingContext())) {
92 index = bdContext.getIndex(bdName, ctx.getMappingContext());
94 // Critical section due to bridgeDomainIndexCounter read and write access
95 // TODO HONEYCOMB-199 move this "get next available index" into naming context or an adapter
96 // or a dedicated object
98 // Use counter to assign bridge domain index, but still check naming context if it's not taken there
99 while (bdContext.containsName(bridgeDomainIndexCounter, ctx.getMappingContext())) {
100 bridgeDomainIndexCounter++;
102 index = bridgeDomainIndexCounter;
104 addOrUpdateBridgeDomain(id, index, dataBefore);
105 bdContext.addName(index, bdName, ctx.getMappingContext());
106 } catch (VppBaseCallException e) {
107 LOG.warn("Failed to create bridge domain", e);
108 throw new WriteFailedException.CreateFailedException(id, dataBefore, e);
114 public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
115 @Nonnull final BridgeDomain dataBefore,
116 @Nonnull final WriteContext ctx)
117 throws WriteFailedException {
118 LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx);
119 final String bdName = id.firstKeyOf(BridgeDomain.class).getName();
120 int bdId = bdContext.getIndex(bdName, ctx.getMappingContext());
123 final BridgeDomainAddDel request = new BridgeDomainAddDel();
126 getReplyForWrite(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture(), id);
127 LOG.debug("Bridge domain {} (id={}) deleted successfully", bdName, bdId);
128 } catch (VppBaseCallException e) {
129 LOG.warn("Bridge domain {} (id={}) delete failed", bdName, bdId);
130 throw new WriteFailedException.DeleteFailedException(id, e);
135 public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
136 @Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter,
137 @Nonnull final WriteContext ctx)
138 throws WriteFailedException {
139 LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter,
142 final String bdName = checkNotNull(dataAfter.getName());
143 checkArgument(bdName.equals(dataBefore.getName()),
144 "BridgeDomain name changed. It should be deleted and then created.");
147 addOrUpdateBridgeDomain(id, bdContext.getIndex(bdName, ctx.getMappingContext()), dataAfter);
148 } catch (VppBaseCallException e) {
149 LOG.warn("Failed to create bridge domain", e);
150 throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e);