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