2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.elan.internal;
10 import com.google.common.util.concurrent.ListenableFuture;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.concurrent.Callable;
16 import javax.annotation.PostConstruct;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
23 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
24 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
25 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
26 import org.opendaylight.netvirt.elan.ElanException;
27 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
28 import org.opendaylight.netvirt.elan.utils.ElanConstants;
29 import org.opendaylight.netvirt.elan.utils.ElanUtils;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 public class ElanLearntVpnVipToPortListener extends
44 AsyncDataTreeChangeListenerBase<LearntVpnVipToPort, ElanLearntVpnVipToPortListener> {
45 private static final Logger LOG = LoggerFactory.getLogger(ElanLearntVpnVipToPortListener.class);
46 private final DataBroker broker;
47 private final IInterfaceManager interfaceManager;
48 private final ElanUtils elanUtils;
49 private final JobCoordinator jobCoordinator;
50 private final ElanInstanceCache elanInstanceCache;
53 public ElanLearntVpnVipToPortListener(DataBroker broker, IInterfaceManager interfaceManager, ElanUtils elanUtils,
54 JobCoordinator jobCoordinator, ElanInstanceCache elanInstanceCache) {
55 super(LearntVpnVipToPort.class, ElanLearntVpnVipToPortListener.class);
57 this.interfaceManager = interfaceManager;
58 this.elanUtils = elanUtils;
59 this.jobCoordinator = jobCoordinator;
60 this.elanInstanceCache = elanInstanceCache;
66 registerListener(LogicalDatastoreType.OPERATIONAL, broker);
70 protected InstanceIdentifier<LearntVpnVipToPort> getWildCardPath() {
71 return InstanceIdentifier.create(LearntVpnVipToPortData.class).child(LearntVpnVipToPort.class);
75 protected void remove(InstanceIdentifier<LearntVpnVipToPort> key, LearntVpnVipToPort dataObjectModification) {
76 String macAddress = dataObjectModification.getMacAddress();
77 String interfaceName = dataObjectModification.getPortName();
78 LOG.trace("Removing mac address {} from interface {} ", macAddress, interfaceName);
79 jobCoordinator.enqueueJob(buildJobKey(macAddress, interfaceName),
80 new StaticMacRemoveWorker(macAddress, interfaceName));
84 protected void update(InstanceIdentifier<LearntVpnVipToPort> key, LearntVpnVipToPort dataObjectModificationBefore,
85 LearntVpnVipToPort dataObjectModificationAfter) {
89 protected void add(InstanceIdentifier<LearntVpnVipToPort> key, LearntVpnVipToPort dataObjectModification) {
90 String macAddress = dataObjectModification.getMacAddress();
91 String interfaceName = dataObjectModification.getPortName();
92 LOG.trace("Adding mac address {} to interface {} ", macAddress, interfaceName);
93 jobCoordinator.enqueueJob(buildJobKey(macAddress, interfaceName),
94 new StaticMacAddWorker(macAddress, interfaceName));
98 protected ElanLearntVpnVipToPortListener getDataTreeChangeListener() {
102 private class StaticMacAddWorker implements Callable<List<ListenableFuture<Void>>> {
104 String interfaceName;
106 StaticMacAddWorker(String macAddress, String interfaceName) {
107 this.macAddress = macAddress;
108 this.interfaceName = interfaceName;
112 public List<ListenableFuture<Void>> call() throws Exception {
113 ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
114 if (elanInterface == null) {
115 LOG.debug("ElanInterface Not present for interfaceName {} for add event", interfaceName);
116 return Collections.emptyList();
118 WriteTransaction interfaceTx = broker.newWriteOnlyTransaction();
119 WriteTransaction flowTx = broker.newWriteOnlyTransaction();
120 addMacEntryToDsAndSetupFlows(elanInterface.getElanInstanceName(), interfaceTx,
121 flowTx, ElanConstants.STATIC_MAC_TIMEOUT);
122 List<ListenableFuture<Void>> futures = new ArrayList<>();
123 futures.add(interfaceTx.submit());
124 futures.add(flowTx.submit());
128 private void addMacEntryToDsAndSetupFlows(String elanName, WriteTransaction interfaceTx,
129 WriteTransaction flowTx, int macTimeOut) throws ElanException {
130 LOG.trace("Adding mac address {} and interface name {} to ElanInterfaceForwardingEntries and "
131 + "ElanForwardingTables DS", macAddress, interfaceName);
132 BigInteger timeStamp = new BigInteger(String.valueOf(System.currentTimeMillis()));
133 PhysAddress physAddress = new PhysAddress(macAddress);
134 MacEntry macEntry = new MacEntryBuilder().setInterface(interfaceName).setMacAddress(physAddress)
135 .setKey(new MacEntryKey(physAddress)).setControllerLearnedForwardingEntryTimestamp(timeStamp)
136 .setIsStaticAddress(false).build();
137 InstanceIdentifier<MacEntry> macEntryId = ElanUtils
138 .getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
139 interfaceTx.put(LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry);
140 InstanceIdentifier<MacEntry> elanMacEntryId =
141 ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress);
142 interfaceTx.put(LogicalDatastoreType.OPERATIONAL, elanMacEntryId, macEntry);
143 ElanInstance elanInstance = elanInstanceCache.get(elanName).orNull();
144 elanUtils.setupMacFlows(elanInstance, interfaceManager.getInterfaceInfo(interfaceName), macTimeOut,
145 macAddress, true, flowTx);
149 private class StaticMacRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
151 String interfaceName;
153 StaticMacRemoveWorker(String macAddress, String interfaceName) {
154 this.macAddress = macAddress;
155 this.interfaceName = interfaceName;
159 public List<ListenableFuture<Void>> call() throws Exception {
160 ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
161 if (elanInterface == null) {
162 LOG.debug("ElanInterface Not present for interfaceName {} for delete event", interfaceName);
163 return Collections.emptyList();
165 WriteTransaction interfaceTx = broker.newWriteOnlyTransaction();
166 WriteTransaction flowTx = broker.newWriteOnlyTransaction();
167 deleteMacEntryFromDsAndRemoveFlows(elanInterface.getElanInstanceName(), interfaceTx,
169 List<ListenableFuture<Void>> futures = new ArrayList<>();
170 futures.add(interfaceTx.submit());
171 futures.add(flowTx.submit());
175 private void deleteMacEntryFromDsAndRemoveFlows(String elanName, WriteTransaction interfaceTx,
176 WriteTransaction flowTx) {
177 LOG.trace("Deleting mac address {} and interface name {} from ElanInterfaceForwardingEntries "
178 + "and ElanForwardingTables DS", macAddress, interfaceName);
179 PhysAddress physAddress = new PhysAddress(macAddress);
180 MacEntry macEntry = elanUtils.getInterfaceMacEntriesOperationalDataPath(interfaceName, physAddress);
181 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
182 if (macEntry != null && interfaceInfo != null) {
183 elanUtils.deleteMacFlows(elanInstanceCache.get(elanName).orNull(), interfaceInfo, macEntry, flowTx);
185 interfaceTx.delete(LogicalDatastoreType.OPERATIONAL,
186 ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress));
187 interfaceTx.delete(LogicalDatastoreType.OPERATIONAL,
188 ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress));
192 private String buildJobKey(String mac, String interfaceName) {
193 return "ENTERPRISEMACJOB" + mac + interfaceName;