327247b41adb3eb4a80d5057d0a9c90e672dba36
[honeycomb.git] / v3po / v3po2vpp / src / main / java / io / fd / honeycomb / translate / v3po / vpp / BridgeDomainCustomizer.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.translate.v3po.vpp;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21
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.write.WriteContext;
29 import io.fd.honeycomb.translate.write.WriteFailedException;
30 import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDel;
31 import io.fd.vpp.jvpp.core.dto.BridgeDomainAddDelReply;
32 import io.fd.vpp.jvpp.core.future.FutureJVppCore;
33 import javax.annotation.Nonnull;
34 import javax.annotation.concurrent.GuardedBy;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomain;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.bridge.domains.BridgeDomainKey;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class BridgeDomainCustomizer
42         extends FutureJVppCustomizer
43         implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey>, ByteDataTranslator, JvppReplyConsumer {
44
45     private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class);
46
47     private static final byte ADD_OR_UPDATE_BD = (byte) 1;
48     private final NamingContext bdContext;
49     @GuardedBy("this")
50     private int bridgeDomainIndexCounter = 1;
51
52     public BridgeDomainCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
53                                   @Nonnull final NamingContext bdContext) {
54         super(futureJVppCore);
55         this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null");
56     }
57
58     private BridgeDomainAddDelReply addOrUpdateBridgeDomain(@Nonnull final InstanceIdentifier<BridgeDomain> id,
59                                                             final int bdId, @Nonnull final BridgeDomain bd)
60             throws WriteFailedException {
61         final BridgeDomainAddDelReply reply;
62         final BridgeDomainAddDel request = new BridgeDomainAddDel();
63         request.bdId = bdId;
64         request.flood = booleanToByte(bd.isFlood());
65         request.forward = booleanToByte(bd.isForward());
66         request.learn = booleanToByte(bd.isLearn());
67         request.uuFlood = booleanToByte(bd.isUnknownUnicastFlood());
68         request.arpTerm = booleanToByte(bd.isArpTermination());
69         request.isAdd = ADD_OR_UPDATE_BD;
70
71         reply = getReplyForWrite(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture(), id);
72         LOG.debug("Bridge domain {} (id={}) add/update successful", bd.getName(), bdId);
73         return reply;
74     }
75
76     @Override
77     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
78                                        @Nonnull final BridgeDomain dataBefore,
79                                        @Nonnull final WriteContext ctx)
80             throws WriteFailedException {
81         LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, dataBefore, ctx);
82         final String bdName = dataBefore.getName();
83
84         // Invoke 1. check index, 2. increase index 3. create ND 4. store mapping in a synchronized block to prevent
85         // race conditions in case of concurrent invocation
86         synchronized (this) {
87             int index;
88             if (bdContext.containsIndex(bdName, ctx.getMappingContext())) {
89                 index = bdContext.getIndex(bdName, ctx.getMappingContext());
90             } else {
91                 // Critical section due to bridgeDomainIndexCounter read and write access
92                 // TODO HONEYCOMB-199 move this "get next available index" into naming context or an adapter
93                 // or a dedicated object
94
95                 // Use counter to assign bridge domain index, but still check naming context if it's not taken there
96                 while (bdContext.containsName(bridgeDomainIndexCounter, ctx.getMappingContext())) {
97                     bridgeDomainIndexCounter++;
98                 }
99                 index = bridgeDomainIndexCounter;
100             }
101             addOrUpdateBridgeDomain(id, index, dataBefore);
102             bdContext.addName(index, bdName, ctx.getMappingContext());
103         }
104     }
105
106     @Override
107     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
108                                         @Nonnull final BridgeDomain dataBefore,
109                                         @Nonnull final WriteContext ctx)
110             throws WriteFailedException {
111         LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx);
112         final String bdName = id.firstKeyOf(BridgeDomain.class).getName();
113         int bdId = bdContext.getIndex(bdName, ctx.getMappingContext());
114
115         final BridgeDomainAddDel request = new BridgeDomainAddDel();
116         request.bdId = bdId;
117
118         getReplyForWrite(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture(), id);
119         LOG.debug("Bridge domain {} (id={}) deleted successfully", bdName, bdId);
120     }
121
122     @Override
123     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id,
124                                         @Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter,
125                                         @Nonnull final WriteContext ctx)
126             throws WriteFailedException {
127         LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter,
128                 ctx);
129
130         final String bdName = checkNotNull(dataAfter.getName());
131         checkArgument(bdName.equals(dataBefore.getName()),
132                 "BridgeDomain name changed. It should be deleted and then created.");
133
134         addOrUpdateBridgeDomain(id, bdContext.getIndex(bdName, ctx.getMappingContext()), dataAfter);
135     }
136
137 }