NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanLearntVpnVipToPortListener.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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 /*
10 package org.opendaylight.netvirt.elan.internal;
11
12 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
13 import static org.opendaylight.genius.infra.Datastore.OPERATIONAL;
14
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.math.BigInteger;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Optional;
21 import java.util.concurrent.Callable;
22 import java.util.concurrent.ExecutionException;
23 import javax.inject.Inject;
24 import javax.inject.Singleton;
25 import org.opendaylight.genius.infra.Datastore.Configuration;
26 import org.opendaylight.genius.infra.Datastore.Operational;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
30 import org.opendaylight.genius.infra.TypedWriteTransaction;
31 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
32 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
33 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
34 import org.opendaylight.infrautils.utils.concurrent.Executors;
35 import org.opendaylight.mdsal.binding.api.DataBroker;
36 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
37 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
38 import org.opendaylight.netvirt.elan.cache.ElanInterfaceCache;
39 import org.opendaylight.netvirt.elan.utils.ElanConstants;
40 import org.opendaylight.netvirt.elan.utils.ElanUtils;
41 import org.opendaylight.serviceutils.tools.listener.AbstractAsyncDataTreeChangeListener;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 @Singleton
55 public class ElanLearntVpnVipToPortListener extends
56         AbstractAsyncDataTreeChangeListener<LearntVpnVipToPort> {
57     private static final Logger LOG = LoggerFactory.getLogger(ElanLearntVpnVipToPortListener.class);
58     private final DataBroker broker;
59     private final ManagedNewTransactionRunner txRunner;
60     private final IInterfaceManager interfaceManager;
61     private final ElanUtils elanUtils;
62     private final JobCoordinator jobCoordinator;
63     private final ElanInstanceCache elanInstanceCache;
64     private final ElanInterfaceCache elanInterfaceCache;
65
66     @Inject
67     public ElanLearntVpnVipToPortListener(DataBroker broker, IInterfaceManager interfaceManager, ElanUtils elanUtils,
68             JobCoordinator jobCoordinator, ElanInstanceCache elanInstanceCache, ElanInterfaceCache elanInterfaceCache) {
69         super(broker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(LearntVpnVipToPortData.class)
70                 .child(LearntVpnVipToPort.class),
71                 Executors.newListeningSingleThreadExecutor("ElanLearntVpnVipToPortListener", LOG));
72         this.broker = broker;
73         this.txRunner = new ManagedNewTransactionRunnerImpl(broker);
74         this.interfaceManager = interfaceManager;
75         this.elanUtils = elanUtils;
76         this.jobCoordinator = jobCoordinator;
77         this.elanInstanceCache = elanInstanceCache;
78         this.elanInterfaceCache = elanInterfaceCache;
79     }
80
81     public void init() {
82         LOG.info("{} registered", getClass().getSimpleName());
83
84        // ELAN will learn the MAC by itself using ElanPacketInHandler class.
85         //registerListener(LogicalDatastoreType.OPERATIONAL, broker);
86
87     }
88
89     @Override
90     public void remove(InstanceIdentifier<LearntVpnVipToPort> key, LearntVpnVipToPort dataObjectModification) {
91         String macAddress = dataObjectModification.getMacAddress();
92         String interfaceName = dataObjectModification.getPortName();
93         LOG.trace("Removing mac address {} from interface {} ", macAddress, interfaceName);
94         jobCoordinator.enqueueJob(buildJobKey(macAddress, interfaceName),
95                 new StaticMacRemoveWorker(macAddress, interfaceName));
96     }
97
98     @Override
99     public void update(InstanceIdentifier<LearntVpnVipToPort> key, LearntVpnVipToPort dataObjectModificationBefore,
100             LearntVpnVipToPort dataObjectModificationAfter) {
101     }
102
103     @Override
104     public void add(InstanceIdentifier<LearntVpnVipToPort> key, LearntVpnVipToPort dataObjectModification) {
105         String macAddress = dataObjectModification.getMacAddress();
106         String interfaceName = dataObjectModification.getPortName();
107         LOG.trace("Adding mac address {} to interface {} ", macAddress, interfaceName);
108         jobCoordinator.enqueueJob(buildJobKey(macAddress, interfaceName),
109                 new StaticMacAddWorker(macAddress, interfaceName));
110     }
111
112     private class StaticMacAddWorker implements Callable<List<? extends ListenableFuture<?>>> {
113         String macAddress;
114         String interfaceName;
115
116         StaticMacAddWorker(String macAddress, String interfaceName) {
117             this.macAddress = macAddress;
118             this.interfaceName = interfaceName;
119         }
120
121         @Override
122         public List<ListenableFuture<Void>> call() {
123             Optional<ElanInterface> elanInterface = elanInterfaceCache.get(interfaceName);
124             if (!elanInterface.isPresent()) {
125                 LOG.debug("ElanInterface Not present for interfaceName {} for add event", interfaceName);
126                 return Collections.emptyList();
127             }
128             List<ListenableFuture<Void>> futures = new ArrayList<>();
129             futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, interfaceTx ->
130                 futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, flowTx ->
131                     addMacEntryToDsAndSetupFlows(elanInterface.get().getElanInstanceName(), interfaceTx,
132                             flowTx, ElanConstants.STATIC_MAC_TIMEOUT)))));
133             return futures;
134         }
135
136         private void addMacEntryToDsAndSetupFlows(String elanName, TypedWriteTransaction<Operational> interfaceTx,
137                 TypedWriteTransaction<Configuration> flowTx, int macTimeOut) {
138             LOG.trace("Adding mac address {} and interface name {} to ElanInterfaceForwardingEntries and "
139                 + "ElanForwardingTables DS", macAddress, interfaceName);
140             BigInteger timeStamp = new BigInteger(String.valueOf(System.currentTimeMillis()));
141             PhysAddress physAddress = new PhysAddress(macAddress);
142             MacEntry macEntry = new MacEntryBuilder().setInterface(interfaceName).setMacAddress(physAddress)
143                     .withKey(new MacEntryKey(physAddress)).setControllerLearnedForwardingEntryTimestamp(timeStamp)
144                     .setIsStaticAddress(false).build();
145             InstanceIdentifier<MacEntry> macEntryId = ElanUtils
146                     .getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
147             interfaceTx.put(macEntryId, macEntry);
148             InstanceIdentifier<MacEntry> elanMacEntryId =
149                     ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress);
150             interfaceTx.put(elanMacEntryId, macEntry);
151             ElanInstance elanInstance = elanInstanceCache.get(elanName).orElse(null);
152             elanUtils.setupMacFlows(elanInstance, interfaceManager.getInterfaceInfo(interfaceName), macTimeOut,
153                     macAddress, true, flowTx);
154         }
155     }
156
157     private class StaticMacRemoveWorker implements Callable<List<? extends ListenableFuture<?>>> {
158         String macAddress;
159         String interfaceName;
160
161         StaticMacRemoveWorker(String macAddress, String interfaceName) {
162             this.macAddress = macAddress;
163             this.interfaceName = interfaceName;
164         }
165
166         @Override
167         public List<ListenableFuture<Void>> call() {
168             Optional<ElanInterface> elanInterface = elanInterfaceCache.get(interfaceName);
169             if (!elanInterface.isPresent()) {
170                 LOG.debug("ElanInterface Not present for interfaceName {} for delete event", interfaceName);
171                 return Collections.emptyList();
172             }
173             List<ListenableFuture<Void>> futures = new ArrayList<>();
174             futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL, interfaceTx ->
175                 futures.add(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, flowTx ->
176                     deleteMacEntryFromDsAndRemoveFlows(elanInterface.get().getElanInstanceName(),
177                             interfaceTx, flowTx)))));
178             return futures;
179         }
180
181         private void deleteMacEntryFromDsAndRemoveFlows(String elanName,
182                 TypedWriteTransaction<Operational> interfaceTx, TypedReadWriteTransaction<Configuration> flowTx)
183                 throws ExecutionException, InterruptedException {
184             LOG.trace("Deleting mac address {} and interface name {} from ElanInterfaceForwardingEntries "
185                     + "and ElanForwardingTables DS", macAddress, interfaceName);
186             PhysAddress physAddress = new PhysAddress(macAddress);
187             MacEntry macEntry = elanUtils.getInterfaceMacEntriesOperationalDataPath(interfaceName, physAddress);
188             InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
189             if (macEntry != null && interfaceInfo != null) {
190                 elanUtils.deleteMacFlows(elanInstanceCache.get(elanName).orElse(null), interfaceInfo, macEntry, flowTx);
191                 interfaceTx.delete(
192                         ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress));
193                 interfaceTx.delete(
194                         ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress));
195             }
196         }
197     }
198
199     private static String buildJobKey(String mac, String interfaceName) {
200         return "ENTERPRISEMACJOB" + mac + interfaceName;
201     }
202
203
204 }
205 */