6e13651c98e8023d7d5d49ce135af144643fec0e
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / transact / McastMacsRemoteUpdateCommand.java
1 /*
2  * Copyright © 2015, 2017 China Telecom Beijing Research Institute and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.ovsdb.hwvtepsouthbound.transact;
10
11 import static org.opendaylight.ovsdb.lib.operations.Operations.op;
12
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import java.util.Objects;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
22 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepDeviceInfo;
23 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundConstants;
24 import org.opendaylight.ovsdb.hwvtepsouthbound.HwvtepSouthboundUtil;
25 import org.opendaylight.ovsdb.lib.notation.UUID;
26 import org.opendaylight.ovsdb.lib.operations.TransactionBuilder;
27 import org.opendaylight.ovsdb.lib.schema.typed.TyperUtils;
28 import org.opendaylight.ovsdb.schema.hardwarevtep.McastMacsRemote;
29 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 public class McastMacsRemoteUpdateCommand extends AbstractTransactCommand<RemoteMcastMacs, HwvtepGlobalAugmentation> {
40     private static final Logger LOG = LoggerFactory.getLogger(McastMacsRemoteUpdateCommand.class);
41     private static final McastMacUnMetDependencyGetter MCAST_MAC_DATA_VALIDATOR = new McastMacUnMetDependencyGetter();
42
43     public McastMacsRemoteUpdateCommand(HwvtepOperationalState state,
44             Collection<DataTreeModification<Node>> changes) {
45         super(state, changes);
46     }
47
48     @Override
49     public void execute(TransactionBuilder transaction) {
50         Map<InstanceIdentifier<Node>, List<RemoteMcastMacs>> updateds =
51                 extractUpdated(getChanges(),RemoteMcastMacs.class);
52         if (!updateds.isEmpty()) {
53             for (Entry<InstanceIdentifier<Node>, List<RemoteMcastMacs>> updated:
54                 updateds.entrySet()) {
55                 updateMcastMacRemote(transaction,  updated.getKey(), updated.getValue());
56             }
57         }
58     }
59
60     private void updateMcastMacRemote(TransactionBuilder transaction,
61             InstanceIdentifier<Node> instanceIdentifier, List<RemoteMcastMacs> macList) {
62         for (RemoteMcastMacs mac: macList) {
63             //add / update only if locator set got changed
64             if (!HwvtepSouthboundUtil.isEmpty(mac.getLocatorSet())) {
65                 onConfigUpdate(transaction, instanceIdentifier, mac, null);
66             }
67         }
68     }
69
70     @Override
71     public void onConfigUpdate(TransactionBuilder transaction,
72                                   InstanceIdentifier<Node> nodeIid,
73                                   RemoteMcastMacs remoteMcastMac,
74                                   InstanceIdentifier macKey,
75                                   Object... extraData) {
76         InstanceIdentifier<RemoteMcastMacs> macIid = nodeIid.augmentation(HwvtepGlobalAugmentation.class)
77                 .child(RemoteMcastMacs.class, remoteMcastMac.key());
78         processDependencies(MCAST_MAC_DATA_VALIDATOR, transaction, nodeIid, macIid, remoteMcastMac);
79     }
80
81     @Override
82     public void doDeviceTransaction(TransactionBuilder transaction,
83                                        InstanceIdentifier<Node> instanceIdentifier,
84                                        RemoteMcastMacs mac,
85                                        InstanceIdentifier macKey,
86                                        Object... extraData) {
87         LOG.debug("Creating remoteMcastMacs, mac address: {}", mac.getMacEntryKey().getValue());
88         final HwvtepDeviceInfo.DeviceData operationalMacOptional =
89                 getDeviceInfo().getDeviceOperData(RemoteMcastMacs.class, macKey);
90         McastMacsRemote mcastMacsRemote = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
91                 McastMacsRemote.class);
92         setIpAddress(mcastMacsRemote, mac);
93         setLocatorSet(transaction, mcastMacsRemote, mac);
94         setLogicalSwitch(transaction, mcastMacsRemote, mac);
95         if (operationalMacOptional == null) {
96             setMac(mcastMacsRemote, mac);
97             LOG.trace("execute: create RemoteMcastMac entry: {}", mcastMacsRemote);
98             transaction.add(op.insert(mcastMacsRemote));
99             transaction.add(op.comment("McastMacRemote: Creating " + mac.getMacEntryKey().getValue()));
100             updateCurrentTxData(RemoteMcastMacs.class, macKey, TXUUID, mac);
101             updateControllerTxHistory(TransactionType.ADD, mcastMacsRemote);
102         } else if (operationalMacOptional.getUuid() != null) {
103             UUID macEntryUUID = operationalMacOptional.getUuid();
104             McastMacsRemote extraMac = TyperUtils.getTypedRowWrapper(transaction.getDatabaseSchema(),
105                     McastMacsRemote.class, null);
106             extraMac.getUuidColumn().setData(macEntryUUID);
107             LOG.trace("execute: update RemoteMcastMac entry: {}", mcastMacsRemote);
108             transaction.add(op.update(mcastMacsRemote)
109                     .where(extraMac.getUuidColumn().getSchema().opEqual(macEntryUUID))
110                     .build());
111             transaction.add(op.comment("McastMacRemote: Updating " + macEntryUUID));
112             updateControllerTxHistory(TransactionType.UPDATE, mcastMacsRemote);
113             //add to updates so that tep ref counts can be updated upon success
114             addToUpdates(macKey, mac);
115         } else {
116             LOG.warn("Unable to update remoteMcastMacs {} because uuid not found in the operational store",
117                     mac.getMacEntryKey().getValue());
118         }
119     }
120
121     private void setLogicalSwitch(final TransactionBuilder transaction, final McastMacsRemote mcastMacsRemote,
122             final RemoteMcastMacs inputMac) {
123         if (inputMac.getLogicalSwitchRef() != null) {
124             @SuppressWarnings("unchecked")
125             InstanceIdentifier<LogicalSwitches> lswitchIid =
126                     (InstanceIdentifier<LogicalSwitches>) inputMac.getLogicalSwitchRef().getValue();
127             mcastMacsRemote.setLogicalSwitch(TransactUtils.getLogicalSwitchUUID(transaction,
128                     getOperationalState(), lswitchIid));
129         }
130     }
131
132     private void setLocatorSet(TransactionBuilder transaction, McastMacsRemote mcastMacsRemote,
133             RemoteMcastMacs inputMac) {
134         if (inputMac.getLocatorSet() != null && !inputMac.getLocatorSet().isEmpty()) {
135             UUID locatorSetUuid = TransactUtils.createPhysicalLocatorSet(getOperationalState(),
136                     transaction, inputMac.getLocatorSet());
137             mcastMacsRemote.setLocatorSet(locatorSetUuid);
138         }
139     }
140
141     private void setIpAddress(McastMacsRemote mcastMacsRemote, RemoteMcastMacs inputMac) {
142         if (inputMac.getIpaddr() != null) {
143             mcastMacsRemote.setIpAddress(inputMac.getIpaddr().getIpv4Address().getValue());
144         }
145     }
146
147     private void setMac(McastMacsRemote mcastMacsRemote, RemoteMcastMacs inputMac) {
148         if (inputMac.getMacEntryKey() != null) {
149             if (inputMac.getMacEntryKey().equals(HwvtepSouthboundConstants.UNKNOWN_DST_MAC)) {
150                 mcastMacsRemote.setMac(HwvtepSouthboundConstants.UNKNOWN_DST_STRING);
151             } else {
152                 mcastMacsRemote.setMac(inputMac.getMacEntryKey().getValue());
153             }
154         }
155     }
156
157     @Override
158     protected List<RemoteMcastMacs> getData(HwvtepGlobalAugmentation augmentation) {
159         return augmentation.getRemoteMcastMacs();
160     }
161
162     @Override
163     protected boolean areEqual(RemoteMcastMacs macs1, RemoteMcastMacs macs2) {
164         return macs1.key().equals(macs2.key()) && Objects.equals(macs1.getLocatorSet(), macs2.getLocatorSet());
165     }
166
167     static class McastMacUnMetDependencyGetter extends UnMetDependencyGetter<RemoteMcastMacs> {
168
169         @Override
170         public List<InstanceIdentifier<?>> getLogicalSwitchDependencies(RemoteMcastMacs data) {
171             if (data == null) {
172                 return Collections.emptyList();
173             }
174             return Collections.singletonList(data.getLogicalSwitchRef().getValue());
175         }
176
177         @Override
178         public List<InstanceIdentifier<?>> getTerminationPointDependencies(RemoteMcastMacs data) {
179             if (data == null || HwvtepSouthboundUtil.isEmpty(data.getLocatorSet())) {
180                 return Collections.emptyList();
181             }
182             List<InstanceIdentifier<?>> locators = new ArrayList<>();
183             for (LocatorSet locator: data.getLocatorSet()) {
184                 locators.add(locator.getLocatorRef().getValue());
185             }
186             return locators;
187         }
188     }
189
190     @SuppressFBWarnings("UC_USELESS_OBJECT")
191     private void updateLocatorRefCounts(MdsalUpdate mdsalUpdate) {
192         //decrement the refcounts from old mcast mac
193         //increment the refcounts for new mcast mac
194         RemoteMcastMacs newMac = (RemoteMcastMacs) mdsalUpdate.getNewData();
195         RemoteMcastMacs oldMac = (RemoteMcastMacs) mdsalUpdate.getOldData();
196         InstanceIdentifier<RemoteMcastMacs> macIid = mdsalUpdate.getKey();
197
198         if (oldMac != null && !oldMac.equals(newMac)) {
199             if (oldMac.getLocatorSet() != null) {
200                 List<LocatorSet> removedLocators = new ArrayList<>(oldMac.getLocatorSet());
201                 if (newMac.getLocatorSet() != null) {
202                     removedLocators.removeAll(newMac.getLocatorSet());
203                 }
204                 removedLocators.forEach(iid -> getDeviceInfo().decRefCount(macIid, iid.getLocatorRef().getValue()));
205             }
206         }
207     }
208
209     @Override
210     protected void onCommandSucceeded() {
211         for (MdsalUpdate mdsalUpdate : updates.get(getDeviceTransaction())) {
212             updateLocatorRefCounts(mdsalUpdate);
213             RemoteMcastMacs mac = (RemoteMcastMacs) mdsalUpdate.getNewData();
214             InstanceIdentifier<RemoteMcastMacs> macIid = mdsalUpdate.getKey();
215             getDeviceInfo().updateRemoteMcast(
216                     (InstanceIdentifier<LogicalSwitches>) mac.getLogicalSwitchRef().getValue(), macIid, mac);
217         }
218     }
219 }