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