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.utils;
10 import com.google.common.base.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.Future;
23 import org.apache.commons.lang3.StringUtils;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
30 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
31 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
32 import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil;
33 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
34 import org.opendaylight.genius.itm.globals.ITMConstants;
35 import org.opendaylight.genius.mdsalutil.FlowEntity;
36 import org.opendaylight.genius.mdsalutil.InstructionInfo;
37 import org.opendaylight.genius.mdsalutil.InstructionType;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.genius.mdsalutil.MDSALUtil.MdsalOp;
40 import org.opendaylight.genius.mdsalutil.MatchFieldType;
41 import org.opendaylight.genius.mdsalutil.MatchInfo;
42 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
43 import org.opendaylight.genius.mdsalutil.NwConstants;
44 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
45 import org.opendaylight.genius.utils.ServiceIndex;
46 import org.opendaylight.netvirt.elan.ElanException;
47 import org.opendaylight.netvirt.elan.internal.ElanInstanceManager;
48 import org.opendaylight.netvirt.elan.internal.ElanInterfaceManager;
49 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
50 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
51 import org.opendaylight.netvirt.elan.l2gw.utils.L2GatewayConnectionUtils;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.IfIndexesInterfaceMap;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterface;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterfaceKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfExternal;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetDpidFromInterfaceOutput;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInput;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelList;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInputBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInputBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInput;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.RemoveTerminatingServiceActionsInputBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstanceBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface.EtreeInterfaceType;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTag;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagNameBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaceForwardingEntries;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanState;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMap;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeFlat;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVlan;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVxlan;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTableBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTableKey;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.Elan;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.state.ElanKey;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
150 import org.opendaylight.yangtools.yang.binding.DataObject;
151 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
152 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
153 import org.opendaylight.yangtools.yang.common.RpcResult;
154 import org.slf4j.Logger;
155 import org.slf4j.LoggerFactory;
157 public class ElanUtils {
159 private static final Logger LOG = LoggerFactory.getLogger(ElanUtils.class);
161 private static Map<String, ElanInstance> elanInstanceLocalCache = new ConcurrentHashMap<>();
162 private static Map<String, ElanInterface> elanInterfaceLocalCache = new ConcurrentHashMap<>();
164 private final DataBroker broker;
165 private final IMdsalApiManager mdsalManager;
166 private final ElanInstanceManager elanInstanceManager;
167 private final OdlInterfaceRpcService interfaceManagerRpcService;
168 private final ItmRpcService itmRpcService;
169 private ElanL2GatewayUtils elanL2GatewayUtils;
170 private ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
171 private L2GatewayConnectionUtils l2GatewayConnectionUtils;
173 public static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
175 public void onSuccess(Void result) {
176 LOG.debug("Success in Datastore operation");
180 public void onFailure(Throwable error) {
181 LOG.error("Error in Datastore operation", error);
185 public ElanUtils(DataBroker dataBroker, IMdsalApiManager mdsalManager, ElanInstanceManager elanInstanceManager,
186 OdlInterfaceRpcService interfaceManagerRpcService, ItmRpcService itmRpcService,
187 ElanInterfaceManager elanInterfaceManager,
188 EntityOwnershipService entityOwnershipService) {
189 this.broker = dataBroker;
190 this.mdsalManager = mdsalManager;
191 this.elanInstanceManager = elanInstanceManager;
192 this.interfaceManagerRpcService = interfaceManagerRpcService;
193 this.itmRpcService = itmRpcService;
195 elanL2GatewayMulticastUtils =
196 new ElanL2GatewayMulticastUtils(broker, elanInstanceManager, elanInterfaceManager, this);
197 elanL2GatewayUtils = new ElanL2GatewayUtils(broker, itmRpcService, this,
198 entityOwnershipService, elanL2GatewayMulticastUtils);
199 l2GatewayConnectionUtils = new L2GatewayConnectionUtils(broker,
200 elanInstanceManager, entityOwnershipService, this);
203 public ElanL2GatewayUtils getElanL2GatewayUtils() {
204 return elanL2GatewayUtils;
207 public ElanL2GatewayMulticastUtils getElanL2GatewayMulticastUtils() {
208 return elanL2GatewayMulticastUtils;
211 public L2GatewayConnectionUtils getL2GatewayConnectionUtils() {
212 return l2GatewayConnectionUtils;
215 public static void addElanInstanceIntoCache(String elanInstanceName, ElanInstance elanInstance) {
216 elanInstanceLocalCache.put(elanInstanceName, elanInstance);
219 public static void removeElanInstanceFromCache(String elanInstanceName) {
220 elanInstanceLocalCache.remove(elanInstanceName);
223 public static ElanInstance getElanInstanceFromCache(String elanInstanceName) {
224 return elanInstanceLocalCache.get(elanInstanceName);
227 public static void addElanInterfaceIntoCache(String interfaceName, ElanInterface elanInterface) {
228 elanInterfaceLocalCache.put(interfaceName, elanInterface);
231 public static void removeElanInterfaceFromCache(String interfaceName) {
232 elanInterfaceLocalCache.remove(interfaceName);
235 public static ElanInterface getElanInterfaceFromCache(String interfaceName) {
236 return elanInterfaceLocalCache.get(interfaceName);
240 * Uses the IdManager to retrieve a brand new ElanTag.
246 * @return the integer
248 public static Long retrieveNewElanTag(IdManagerService idManager, String idKey) {
250 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
251 .setIdKey(idKey).build();
254 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
255 RpcResult<AllocateIdOutput> rpcResult = result.get();
256 if (rpcResult.isSuccessful()) {
257 return rpcResult.getResult().getIdValue().longValue();
259 LOG.warn("RPC Call to Allocate Id returned with Errors {}", rpcResult.getErrors());
261 } catch (InterruptedException | ExecutionException e) {
262 LOG.warn("Exception when Allocating Id", e);
267 public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
268 ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
269 Future<RpcResult<Void>> result = idManager.releaseId(releaseIdInput);
275 * @deprecated Consider using {@link #read2(LogicalDatastoreType, InstanceIdentifier)} with proper exception
279 @SuppressWarnings("checkstyle:IllegalCatch")
280 public <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
281 InstanceIdentifier<T> path) {
282 ReadOnlyTransaction tx = broker != null ? broker.newReadOnlyTransaction()
283 : this.broker.newReadOnlyTransaction();
284 Optional<T> result = Optional.absent();
286 CheckedFuture<Optional<T>, ReadFailedException> checkedFuture = tx.read(datastoreType, path);
287 result = checkedFuture.get();
288 } catch (Exception e) {
289 throw new RuntimeException(e);
297 public <T extends DataObject> Optional<T> read2(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path)
298 throws ReadFailedException {
299 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
301 CheckedFuture<Optional<T>, ReadFailedException> checkedFuture = tx.read(datastoreType, path);
302 return checkedFuture.checkedGet();
308 public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
309 InstanceIdentifier<T> path) {
310 WriteTransaction tx = broker.newWriteOnlyTransaction();
311 tx.delete(datastoreType, path);
312 Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
315 public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
316 InstanceIdentifier<T> path, FutureCallback<Void> callback) {
317 WriteTransaction tx = broker.newWriteOnlyTransaction();
318 tx.delete(datastoreType, path);
319 Futures.addCallback(tx.submit(), callback);
322 public static InstanceIdentifier<ElanInstance> getElanInstanceIdentifier() {
323 return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class).build();
326 // elan-instances config container
327 public static ElanInstance getElanInstanceByName(DataBroker broker, String elanInstanceName) {
328 ElanInstance elanObj = getElanInstanceFromCache(elanInstanceName);
329 if (elanObj != null) {
332 InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
333 Optional<ElanInstance> elanInstance = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
335 if (elanInstance.isPresent()) {
336 return elanInstance.get();
341 public static InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
342 return InstanceIdentifier.builder(ElanInstances.class)
343 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
346 // elan-interfaces Config Container
347 public static ElanInterface getElanInterfaceByElanInterfaceName(DataBroker broker, String elanInterfaceName) {
348 ElanInterface elanInterfaceObj = getElanInterfaceFromCache(elanInterfaceName);
349 if (elanInterfaceObj != null) {
350 return elanInterfaceObj;
352 InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
353 Optional<ElanInterface> existingElanInterface = MDSALUtil.read(broker,
354 LogicalDatastoreType.CONFIGURATION, elanInterfaceId);
355 if (existingElanInterface.isPresent()) {
356 return existingElanInterface.get();
361 public static EtreeInterface getEtreeInterfaceByElanInterfaceName(DataBroker broker, String elanInterfaceName) {
362 ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(broker, elanInterfaceName);
363 return elanInterface.getAugmentation(EtreeInterface.class);
366 public static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
367 return InstanceIdentifier.builder(ElanInterfaces.class)
368 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
371 // elan-state Operational container
372 public static Elan getElanByName(DataBroker broker, String elanInstanceName) {
373 InstanceIdentifier<Elan> elanIdentifier = getElanInstanceOperationalDataPath(elanInstanceName);
374 Optional<Elan> elanInstance = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
376 if (elanInstance.isPresent()) {
377 return elanInstance.get();
382 public static InstanceIdentifier<Elan> getElanInstanceOperationalDataPath(String elanInstanceName) {
383 return InstanceIdentifier.builder(ElanState.class).child(Elan.class, new ElanKey(elanInstanceName)).build();
386 // grouping of forwarding-entries
387 public MacEntry getInterfaceMacEntriesOperationalDataPath(String interfaceName, PhysAddress physAddress) {
388 InstanceIdentifier<MacEntry> existingMacEntryId = getInterfaceMacEntriesIdentifierOperationalDataPath(
389 interfaceName, physAddress);
390 Optional<MacEntry> existingInterfaceMacEntry = read(broker,
391 LogicalDatastoreType.OPERATIONAL, existingMacEntryId);
392 if (existingInterfaceMacEntry.isPresent()) {
393 return existingInterfaceMacEntry.get();
398 public MacEntry getInterfaceMacEntriesOperationalDataPathFromId(InstanceIdentifier identifier) {
399 Optional<MacEntry> existingInterfaceMacEntry = read(broker,
400 LogicalDatastoreType.OPERATIONAL, identifier);
401 if (existingInterfaceMacEntry.isPresent()) {
402 return existingInterfaceMacEntry.get();
407 public static InstanceIdentifier<MacEntry> getInterfaceMacEntriesIdentifierOperationalDataPath(String interfaceName,
408 PhysAddress physAddress) {
409 return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class)
410 .child(ElanInterfaceMac.class, new ElanInterfaceMacKey(interfaceName))
411 .child(MacEntry.class, new MacEntryKey(physAddress)).build();
415 // elan-forwarding-tables Operational container
416 public MacEntry getMacTableByElanName(String elanName, PhysAddress physAddress) {
417 InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
418 Optional<MacEntry> existingElanMacEntry = read(broker,
419 LogicalDatastoreType.OPERATIONAL, macId);
420 if (existingElanMacEntry.isPresent()) {
421 return existingElanMacEntry.get();
426 public MacEntry getMacEntryFromElanMacId(InstanceIdentifier identifier) {
427 Optional<MacEntry> existingInterfaceMacEntry = read(broker,
428 LogicalDatastoreType.OPERATIONAL, identifier);
429 if (existingInterfaceMacEntry.isPresent()) {
430 return existingInterfaceMacEntry.get();
435 public static InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName,
436 PhysAddress physAddress) {
437 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName))
438 .child(MacEntry.class, new MacEntryKey(physAddress)).build();
441 public static InstanceIdentifier<MacTable> getElanMacTableOperationalDataPath(String elanName) {
442 return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName))
446 // elan-interface-forwarding-entries Operational container
447 public ElanInterfaceMac getElanInterfaceMacByInterfaceName(String interfaceName) {
448 InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = getElanInterfaceMacEntriesOperationalDataPath(
450 Optional<ElanInterfaceMac> existingElanInterface = read(broker,
451 LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
452 if (existingElanInterface.isPresent()) {
453 return existingElanInterface.get();
459 * Gets the elan interface mac addresses.
461 * @param interfaceName
463 * @return the elan interface mac addresses
465 public List<PhysAddress> getElanInterfaceMacAddresses(String interfaceName) {
466 List<PhysAddress> macAddresses = new ArrayList<>();
467 ElanInterfaceMac elanInterfaceMac = getElanInterfaceMacByInterfaceName(interfaceName);
468 if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
469 List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
470 for (MacEntry macEntry : macEntries) {
471 macAddresses.add(macEntry.getMacAddress());
477 public static InstanceIdentifier<ElanInterfaceMac> getElanInterfaceMacEntriesOperationalDataPath(
478 String interfaceName) {
479 return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class)
480 .child(ElanInterfaceMac.class, new ElanInterfaceMacKey(interfaceName)).build();
484 * Returns the list of Interfaces that belong to an Elan on an specific DPN.
485 * Data retrieved from Elan's operational DS: elan-dpn-interfaces container
487 * @param elanInstanceName
488 * name of the Elan to which the interfaces must belong to
490 * Id of the DPN where the interfaces are located
491 * @return the elan interface Info
493 public DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) {
494 InstanceIdentifier<DpnInterfaces> elanDpnInterfacesId = getElanDpnInterfaceOperationalDataPath(elanInstanceName,
496 Optional<DpnInterfaces> elanDpnInterfaces = read(broker,
497 LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId);
498 if (elanDpnInterfaces.isPresent()) {
499 return elanDpnInterfaces.get();
505 * Returns the InstanceIdentifier that points to the Interfaces of an Elan
506 * in a given DPN in the Operational DS. Data retrieved from Elans's
507 * operational DS: dpn-interfaces list
509 * @param elanInstanceName
510 * name of the Elan to which the interfaces must belong to
512 * Id of the DPN where the interfaces are located
513 * @return the elan dpn interface
515 public static InstanceIdentifier<DpnInterfaces> getElanDpnInterfaceOperationalDataPath(String elanInstanceName,
517 return InstanceIdentifier.builder(ElanDpnInterfaces.class)
518 .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName))
519 .child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build();
522 // elan-tag-name-map Operational Container
523 public ElanTagName getElanInfoByElanTag(long elanTag) {
524 InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
525 Optional<ElanTagName> existingElanInfo = read(broker,
526 LogicalDatastoreType.OPERATIONAL, elanId);
527 if (existingElanInfo.isPresent()) {
528 return existingElanInfo.get();
533 public EtreeLeafTagName getEtreeLeafTagByElanTag(long elanTag) {
534 InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
535 Optional<ElanTagName> existingElanInfo = read(broker,
536 LogicalDatastoreType.OPERATIONAL, elanId);
537 if (existingElanInfo.isPresent()) {
538 ElanTagName elanTagName = existingElanInfo.get();
539 EtreeLeafTagName etreeAugmentation = elanTagName.getAugmentation(EtreeLeafTagName.class);
540 return etreeAugmentation;
545 public static InstanceIdentifier<ElanTagName> getElanInfoEntriesOperationalDataPath(long elanTag) {
546 return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class, new ElanTagNameKey(elanTag))
550 // interface-index-tag operational container
551 public Optional<IfIndexInterface> getInterfaceInfoByInterfaceTag(long interfaceTag) {
552 InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
553 return read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
556 public static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
557 return InstanceIdentifier.builder(IfIndexesInterfaceMap.class)
558 .child(IfIndexInterface.class, new IfIndexInterfaceKey((int) interfaceTag)).build();
561 public static InstanceIdentifier<ElanDpnInterfacesList> getElanDpnOperationDataPath(String elanInstanceName) {
562 return InstanceIdentifier.builder(ElanDpnInterfaces.class)
563 .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build();
566 public ElanDpnInterfacesList getElanDpnInterfacesList(String elanName) {
567 InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanName);
568 Optional<ElanDpnInterfacesList> existingElanDpnInterfaces = read(broker,
569 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
570 if (existingElanDpnInterfaces.isPresent()) {
571 return existingElanDpnInterfaces.get();
576 public ElanDpnInterfaces getElanDpnInterfacesList() {
577 InstanceIdentifier<ElanDpnInterfaces> elanDpnInterfaceId = InstanceIdentifier.builder(ElanDpnInterfaces.class)
579 Optional<ElanDpnInterfaces> existingElanDpnInterfaces = read(broker,
580 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
581 if (existingElanDpnInterfaces.isPresent()) {
582 return existingElanDpnInterfaces.get();
588 * This method is useful get all ELAN participating CSS dpIds to install
589 * program remote dmac entries and updating remote bc groups for tor
592 * @param elanInstanceName
593 * the elan instance name
594 * @return list of dpIds
596 public List<BigInteger> getParticipatingDPNsInElanInstance(String elanInstanceName) {
597 List<BigInteger> dpIds = new ArrayList<>();
598 InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName);
599 Optional<ElanDpnInterfacesList> existingElanDpnInterfaces = read(broker,
600 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
601 if (!existingElanDpnInterfaces.isPresent()) {
604 List<DpnInterfaces> dpnInterfaces = existingElanDpnInterfaces.get().getDpnInterfaces();
605 for (DpnInterfaces dpnInterface : dpnInterfaces) {
606 dpIds.add(dpnInterface.getDpId());
612 * To check given dpId is already present in Elan instance. This can be used
613 * to program flow entry in external tunnel table when a new access port
614 * added for first time into the ELAN instance
618 * @param elanInstanceName
619 * the elan instance name
620 * @return true if dpId is already present, otherwise return false
622 public boolean isDpnAlreadyPresentInElanInstance(BigInteger dpId, String elanInstanceName) {
623 boolean isDpIdPresent = false;
624 InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName);
625 Optional<ElanDpnInterfacesList> existingElanDpnInterfaces = read(broker,
626 LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
627 if (!existingElanDpnInterfaces.isPresent()) {
628 return isDpIdPresent;
630 List<DpnInterfaces> dpnInterfaces = existingElanDpnInterfaces.get().getDpnInterfaces();
631 for (DpnInterfaces dpnInterface : dpnInterfaces) {
632 if (dpnInterface.getDpId().equals(dpId)) {
633 isDpIdPresent = true;
637 return isDpIdPresent;
640 public ElanForwardingTables getElanForwardingList() {
641 InstanceIdentifier<ElanForwardingTables> elanForwardingTableId = InstanceIdentifier
642 .builder(ElanForwardingTables.class).build();
643 Optional<ElanForwardingTables> existingElanForwardingList = read(broker,
644 LogicalDatastoreType.OPERATIONAL, elanForwardingTableId);
645 if (existingElanForwardingList.isPresent()) {
646 return existingElanForwardingList.get();
652 * Gets the elan mac table.
656 * @return the elan mac table
658 public MacTable getElanMacTable(String elanName) {
659 InstanceIdentifier<MacTable> elanMacTableId = getElanMacTableOperationalDataPath(elanName);
660 Optional<MacTable> existingElanMacTable = read(broker,
661 LogicalDatastoreType.OPERATIONAL, elanMacTableId);
662 if (existingElanMacTable.isPresent()) {
663 return existingElanMacTable.get();
668 public static long getElanLocalBCGId(long elanTag) {
669 return ElanConstants.ELAN_GID_MIN + (elanTag % ElanConstants.ELAN_GID_MIN * 2 - 1);
672 public static long getElanRemoteBCGId(long elanTag) {
673 return ElanConstants.ELAN_GID_MIN + elanTag % ElanConstants.ELAN_GID_MIN * 2;
676 public static long getEtreeLeafLocalBCGId(long etreeLeafTag) {
677 return ElanConstants.ELAN_GID_MIN + (etreeLeafTag % ElanConstants.ELAN_GID_MIN * 2 - 1);
680 public static long getEtreeLeafRemoteBCGId(long etreeLeafTag) {
681 return ElanConstants.ELAN_GID_MIN + etreeLeafTag % ElanConstants.ELAN_GID_MIN * 2;
684 public static BigInteger getElanMetadataLabel(long elanTag) {
685 return BigInteger.valueOf(elanTag).shiftLeft(24);
688 public static BigInteger getElanMetadataLabel(long elanTag, boolean isSHFlagSet) {
689 int shBit = isSHFlagSet ? 1 : 0;
690 return BigInteger.valueOf(elanTag).shiftLeft(24).or(BigInteger.valueOf(shBit));
693 public static BigInteger getElanMetadataLabel(long elanTag, int lportTag) {
694 return getElanMetadataLabel(elanTag).or(MetaDataUtil.getLportTagMetaData(lportTag));
697 public static BigInteger getElanMetadataMask() {
698 return MetaDataUtil.METADATA_MASK_SERVICE.or(MetaDataUtil.METADATA_MASK_LPORT_TAG);
702 * Setting INTERNAL_TUNNEL_TABLE, SMAC, DMAC, UDMAC in this DPN and also in
707 * @param interfaceInfo
713 * @param writeFlowGroupTx
715 * @throws ElanException in case of issues creating the flow objects
717 public void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
718 String macAddress, WriteTransaction writeFlowGroupTx) throws ElanException {
719 synchronized (macAddress) {
720 LOG.debug("Acquired lock for mac : " + macAddress + ". Proceeding with install operation.");
721 setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, mdsalManager,
723 setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, mdsalManager,
724 broker, writeFlowGroupTx);
728 public void setupDMacFlowonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId,
729 String macAddress, WriteTransaction writeFlowTx) throws ElanException {
730 synchronized (macAddress) {
731 LOG.debug("Acquired lock for mac : " + macAddress + ". Proceeding with install operation.");
732 setupOrigDmacFlowsonRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress, writeFlowTx);
737 * Inserts a Flow in SMAC table to state that the MAC has already been
740 private void setupKnownSmacFlow(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
741 String macAddress, IMdsalApiManager mdsalApiManager, WriteTransaction writeFlowGroupTx) {
742 FlowEntity flowEntity = buildKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress);
743 mdsalApiManager.addFlowToTx(flowEntity, writeFlowGroupTx);
744 if (LOG.isDebugEnabled()) {
745 LOG.debug("Known Smac flow entry created for elan Name:{}, logical Interface port:{} and mac address:{}",
746 elanInfo.getElanInstanceName(), elanInfo.getDescription(), macAddress);
750 public FlowEntity buildKnownSmacFlow(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
752 int lportTag = interfaceInfo.getInterfaceTag();
753 // Matching metadata and eth_src fields
754 List<MatchInfo> mkMatches = new ArrayList<>();
755 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
756 getElanMetadataLabel(elanInfo.getElanTag(), lportTag), getElanMetadataMask() }));
757 mkMatches.add(new MatchInfo(MatchFieldType.eth_src, new String[] { macAddress }));
758 List<InstructionInfo> mkInstructions = new ArrayList<>();
759 mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.ELAN_DMAC_TABLE }));
761 BigInteger dpId = interfaceInfo.getDpId();
762 long elanTag = getElanTag(broker, elanInfo, interfaceInfo);
763 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_SMAC_TABLE,
764 getKnownDynamicmacFlowRef(NwConstants.ELAN_SMAC_TABLE, dpId, lportTag, macAddress, elanTag), 20,
765 elanInfo.getDescription(), (int) macTimeout, 0,
766 ElanConstants.COOKIE_ELAN_KNOWN_SMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
767 flowEntity.setStrictFlag(true);
768 flowEntity.setSendFlowRemFlag(macTimeout != 0); // If Mac timeout is 0,
771 // automatically, so no
772 // need to get notified
776 private static Long getElanTag(DataBroker broker, ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
777 EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, interfaceInfo.getInterfaceName());
778 if (etreeInterface == null || etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
779 return elanInfo.getElanTag();
781 EtreeInstance etreeInstance = elanInfo.getAugmentation(EtreeInstance.class);
782 if (etreeInstance == null) {
783 LOG.warn("EtreeInterface " + interfaceInfo.getInterfaceName() + " is connected to a non-Etree network: "
784 + elanInfo.getElanInstanceName());
785 return elanInfo.getElanTag();
787 return etreeInstance.getEtreeLeafTagVal().getValue();
793 * Installs a Flow in INTERNAL_TUNNEL_TABLE of the affected DPN that sends
794 * the packet through the specified interface if the tunnel_id matches the
795 * interface's lportTag.
797 * @param interfaceInfo
799 * @param mdsalApiManager
800 * the mdsal API manager
801 * @param writeFlowGroupTx
802 * the writeFLowGroup tx
804 public void setupTermDmacFlows(InterfaceInfo interfaceInfo, IMdsalApiManager mdsalApiManager,
805 WriteTransaction writeFlowGroupTx) {
806 BigInteger dpId = interfaceInfo.getDpId();
807 int lportTag = interfaceInfo.getInterfaceTag();
808 Flow flow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
809 getIntTunnelTableFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, lportTag), 5,
810 String.format("%s:%d", "ITM Flow Entry ", lportTag), 0, 0,
811 ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(lportTag)),
812 getTunnelIdMatchForFilterEqualsLPortTag(lportTag),
813 getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
814 mdsalApiManager.addFlowToTx(dpId, flow, writeFlowGroupTx);
815 if (LOG.isDebugEnabled()) {
816 LOG.debug("Terminating service table flow entry created on dpn:{} for logical Interface port:{}", dpId,
817 interfaceInfo.getPortName());
822 * Constructs the FlowName for flows installed in the Internal Tunnel Table,
823 * consisting in tableId + elanTag.
829 * @return the Internal tunnel
831 public static String getIntTunnelTableFlowRef(short tableId, int elanTag) {
832 return new StringBuffer().append(tableId).append(elanTag).toString();
836 * Constructs the Matches that checks that the tunnel_id field contains a
840 * lportTag that must be checked against the tunnel_id field
841 * @return the list of match Info
843 public static List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int lportTag) {
844 List<MatchInfo> mkMatches = new ArrayList<>();
846 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(lportTag) }));
851 * Constructs the Instructions that take the packet over a given interface.
854 * Name of the interface where the packet must be sent over. It
855 * can be a local interface or a tunnel interface (internal or
857 * @return the Instruction
859 public List<Instruction> getInstructionsInPortForOutGroup(String ifName) {
860 List<Instruction> mkInstructions = new ArrayList<>();
861 List<Action> actions = getEgressActionsForInterface(ifName, /* tunnelKey */ null);
863 mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
864 return mkInstructions;
868 * Returns the list of Actions to be taken when sending the packet through
869 * an Elan interface. Note that this interface can refer to an ElanInterface
870 * where the Elan VM is attached to a DPN or an ITM tunnel interface where
871 * Elan traffic can be sent through. In this latter case, the tunnelKey is
872 * mandatory and it can hold serviceId for internal tunnels or the VNI for
879 * @return the egress actions for interface
881 public List<Action> getEgressActionsForInterface(String ifName, Long tunnelKey) {
882 List<Action> listAction = new ArrayList<>();
884 GetEgressActionsForInterfaceInput getEgressActionInput = new GetEgressActionsForInterfaceInputBuilder()
885 .setIntfName(ifName).setTunnelKey(tunnelKey).build();
886 Future<RpcResult<GetEgressActionsForInterfaceOutput>> result = interfaceManagerRpcService
887 .getEgressActionsForInterface(getEgressActionInput);
888 RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
889 if (!rpcResult.isSuccessful()) {
890 LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName,
891 rpcResult.getErrors());
893 List<Action> actions = rpcResult.getResult().getAction();
894 listAction = actions;
896 } catch (InterruptedException | ExecutionException e) {
897 LOG.warn("Exception when egress actions for interface {}", ifName, e);
902 private void setupOrigDmacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress,
903 IMdsalApiManager mdsalApiManager, DataBroker broker, WriteTransaction writeFlowGroupTx)
904 throws ElanException {
905 BigInteger dpId = interfaceInfo.getDpId();
906 String ifName = interfaceInfo.getInterfaceName();
907 long ifTag = interfaceInfo.getInterfaceTag();
908 String elanInstanceName = elanInfo.getElanInstanceName();
909 List<DpnInterfaces> elanDpns = getInvolvedDpnsInElan(elanInstanceName);
910 if (elanDpns != null) {
911 // TODO might be bug and should call here just elanInfo.getElanTag()
912 Long elanTag = getElanTag(broker, elanInfo, interfaceInfo);
913 for (DpnInterfaces elanDpn : elanDpns) {
914 if (elanDpn.getDpId().equals(dpId)) {
915 // On the local DPN set up a direct output flow
916 setupLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInstanceName, mdsalApiManager, ifTag,
918 LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} mand mac address:{} "
919 + "on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dpId);
921 // Check for the Remote DPN present in Inventory Manager
922 if (isDpnPresent(elanDpn.getDpId())) {
923 // For remote DPNs a flow is needed to indicate that
924 // packets of this ELAN going to this MAC
925 // need to be forwarded through the appropiated ITM
927 setupRemoteDmacFlow(elanDpn.getDpId(), // srcDpn (the
930 dpId, // dstDpn (the local DPN)
931 interfaceInfo.getInterfaceTag(), // lportTag of
934 elanTag, // identifier of the Elan
935 macAddress, // MAC to be programmed in remote
937 elanInstanceName, writeFlowGroupTx, ifName);
938 LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on"
939 + " dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress,
945 // TODO: Make sure that the same is performed against the
950 private void setupOrigDmacFlowsonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
951 BigInteger dstDpId, String macAddress, WriteTransaction writeFlowTx) throws ElanException {
952 BigInteger dpId = interfaceInfo.getDpId();
953 String elanInstanceName = elanInfo.getElanInstanceName();
954 List<DpnInterfaces> remoteFEs = getInvolvedDpnsInElan(elanInstanceName);
955 for (DpnInterfaces remoteFE : remoteFEs) {
956 Long elanTag = elanInfo.getElanTag();
957 if (remoteFE.getDpId().equals(dstDpId)) {
958 // Check for the Remote DPN present in Inventory Manager
959 setupRemoteDmacFlow(dstDpId, dpId, interfaceInfo.getInterfaceTag(), elanTag, macAddress,
960 elanInstanceName, writeFlowTx, interfaceInfo.getInterfaceName());
961 if (LOG.isDebugEnabled()) {
962 LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address {} on"
963 + " dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, remoteFE.getDpId());
970 @SuppressWarnings("unchecked")
971 public List<DpnInterfaces> getInvolvedDpnsInElan(String elanName) {
972 List<DpnInterfaces> dpns = elanInstanceManager.getElanDPNByName(elanName);
974 return Collections.emptyList();
979 private void setupLocalDmacFlow(long elanTag, BigInteger dpId, String ifName, String macAddress,
980 String displayName, IMdsalApiManager mdsalApiManager, long ifTag, WriteTransaction writeFlowGroupTx) {
981 Flow flowEntity = buildLocalDmacFlowEntry(elanTag, dpId, ifName, macAddress, displayName, ifTag);
982 mdsalApiManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
983 installEtreeLocalDmacFlow(elanTag, dpId, ifName, macAddress, displayName, mdsalApiManager, ifTag,
987 private void installEtreeLocalDmacFlow(long elanTag, BigInteger dpId, String ifName, String macAddress,
988 String displayName, IMdsalApiManager mdsalApiManager, long ifTag, WriteTransaction writeFlowGroupTx) {
989 EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, ifName);
990 if (etreeInterface != null) {
991 if (etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
992 EtreeLeafTagName etreeTagName = getEtreeLeafTagByElanTag(elanTag);
993 if (etreeTagName == null) {
994 LOG.warn("Interface " + ifName + " seems like it belongs to Etree but etreeTagName from elanTag "
995 + elanTag + " is null.");
997 Flow flowEntity = buildLocalDmacFlowEntry(etreeTagName.getEtreeLeafTag().getValue(), dpId, ifName,
998 macAddress, displayName, ifTag);
999 mdsalApiManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
1005 public static String getKnownDynamicmacFlowRef(short tableId, BigInteger dpId, long lporTag, String macAddress,
1007 return new StringBuffer().append(tableId).append(elanTag).append(dpId).append(lporTag).append(macAddress)
1011 public static String getKnownDynamicmacFlowRef(short tableId, BigInteger dpId, BigInteger remoteDpId,
1012 String macAddress, long elanTag) {
1013 return new StringBuffer().append(tableId).append(elanTag).append(dpId).append(remoteDpId).append(macAddress)
1017 private static String getKnownDynamicmacFlowRef(short elanDmacTable, BigInteger dpId, String extDeviceNodeId,
1018 String dstMacAddress, long elanTag, boolean shFlag) {
1019 return new StringBuffer().append(elanDmacTable).append(elanTag).append(dpId).append(extDeviceNodeId)
1020 .append(dstMacAddress).append(shFlag).toString();
1024 * Builds the flow to be programmed in the DMAC table of the local DPN (that
1025 * is, where the MAC is attached to). This flow consists in:
1027 * <p>Match: + elanTag in metadata + packet goes to a MAC locally attached
1028 * Actions: + optionally, pop-vlan + set-vlan-id + output to ifName's
1039 * @param displayName
1045 public Flow buildLocalDmacFlowEntry(long elanTag, BigInteger dpId, String ifName, String macAddress,
1046 String displayName, long ifTag) {
1047 List<MatchInfo> mkMatches = new ArrayList<>();
1048 mkMatches.add(new MatchInfo(MatchFieldType.metadata,
1049 new BigInteger[] { getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE }));
1050 mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddress }));
1052 List<Instruction> mkInstructions = new ArrayList<>();
1053 List<Action> actions = getEgressActionsForInterface(ifName, /* tunnelKey */ null);
1054 mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
1055 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
1056 getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, ifTag, macAddress, elanTag), 20,
1057 displayName, 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches,
1063 public void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
1064 String macAddress, String displayName, WriteTransaction writeFlowGroupTx, String interfaceName)
1065 throws ElanException {
1066 Flow flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName);
1067 mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
1068 setupEtreeRemoteDmacFlow(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName, interfaceName,
1072 private void setupEtreeRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
1073 String macAddress, String displayName, String interfaceName, WriteTransaction writeFlowGroupTx)
1074 throws ElanException {
1076 EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, interfaceName);
1077 if (etreeInterface != null) {
1078 if (etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1079 EtreeLeafTagName etreeTagName = getEtreeLeafTagByElanTag(elanTag);
1080 if (etreeTagName == null) {
1081 LOG.warn("Interface " + interfaceName
1082 + " seems like it belongs to Etree but etreeTagName from elanTag " + elanTag + " is null.");
1084 flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag,
1085 etreeTagName.getEtreeLeafTag().getValue(), macAddress, displayName);
1086 mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
1093 * Builds a Flow to be programmed in a remote DPN's DMAC table. This flow
1094 * consists in: Match: + elanTag in packet's metadata + packet going to a
1095 * MAC known to be located in another DPN Actions: + set_tunnel_id(lportTag)
1096 * + output ITM internal tunnel interface with the other DPN
1108 * @param displayName
1110 * @return the flow remote Dmac
1111 * @throws ElanException in case of issues creating the flow objects
1113 @SuppressWarnings("checkstyle:IllegalCatch")
1114 public Flow buildRemoteDmacFlowEntry(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
1115 String macAddress, String displayName) throws ElanException {
1116 List<MatchInfo> mkMatches = new ArrayList<>();
1117 mkMatches.add(new MatchInfo(MatchFieldType.metadata,
1118 new BigInteger[] { getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE }));
1119 mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddress }));
1121 List<Instruction> mkInstructions = new ArrayList<>();
1123 // List of Action for the provided Source and Destination DPIDs
1125 List<Action> actions = getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTag);
1126 mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
1127 } catch (Exception e) {
1128 LOG.error("Could not get egress actions to add to flow for srcDpId=" + srcDpId + ", destDpId=" + destDpId
1129 + ", lportTag=" + lportTag, e);
1132 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
1133 getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, srcDpId, destDpId, macAddress, elanTag),
1135 displayName, 0, /* idleTimeout */
1136 0, /* hardTimeout */
1137 ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
1143 public void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, MacEntry macEntry,
1144 WriteTransaction deleteFlowGroupTx) {
1145 if (elanInfo == null || interfaceInfo == null) {
1148 String macAddress = macEntry.getMacAddress().getValue();
1149 synchronized (macAddress) {
1150 LOG.debug("Acquired lock for mac : " + macAddress + ". Proceeding with remove operation.");
1151 deleteMacFlows(elanInfo, interfaceInfo, macAddress, /* alsoDeleteSMAC */ true, deleteFlowGroupTx);
1155 public void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress,
1156 boolean deleteSmac, WriteTransaction deleteFlowGroupTx) {
1157 String elanInstanceName = elanInfo.getElanInstanceName();
1158 List<DpnInterfaces> remoteFEs = getInvolvedDpnsInElan(elanInstanceName);
1159 BigInteger srcdpId = interfaceInfo.getDpId();
1160 boolean isFlowsRemovedInSrcDpn = false;
1161 for (DpnInterfaces dpnInterface : remoteFEs) {
1162 Long elanTag = elanInfo.getElanTag();
1163 BigInteger dstDpId = dpnInterface.getDpId();
1164 if (executeDeleteMacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, elanInstanceName, srcdpId,
1165 elanTag, dstDpId, deleteFlowGroupTx)) {
1166 isFlowsRemovedInSrcDpn = true;
1168 executeEtreeDeleteMacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, elanInstanceName, srcdpId,
1169 elanTag, dstDpId, deleteFlowGroupTx);
1171 if (!isFlowsRemovedInSrcDpn) {
1172 deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, deleteFlowGroupTx);
1176 private void executeEtreeDeleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress,
1177 boolean deleteSmac, String elanInstanceName, BigInteger srcdpId, Long elanTag, BigInteger dstDpId,
1178 WriteTransaction deleteFlowGroupTx) {
1179 EtreeLeafTagName etreeLeafTag = getEtreeLeafTagByElanTag(elanTag);
1180 if (etreeLeafTag != null) {
1181 executeDeleteMacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, elanInstanceName, srcdpId,
1182 etreeLeafTag.getEtreeLeafTag().getValue(), dstDpId, deleteFlowGroupTx);
1186 private boolean executeDeleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress,
1187 boolean deleteSmac, String elanInstanceName, BigInteger srcdpId, Long elanTag, BigInteger dstDpId,
1188 WriteTransaction deleteFlowGroupTx) {
1189 boolean isFlowsRemovedInSrcDpn = false;
1190 if (dstDpId.equals(srcdpId)) {
1191 isFlowsRemovedInSrcDpn = true;
1192 deleteSmacAndDmacFlows(elanInfo, interfaceInfo, macAddress, deleteSmac, deleteFlowGroupTx);
1193 } else if (isDpnPresent(dstDpId)) {
1195 .removeFlowToTx(dstDpId,
1196 MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE, getKnownDynamicmacFlowRef(
1197 NwConstants.ELAN_DMAC_TABLE, dstDpId, srcdpId, macAddress, elanTag)),
1199 if (LOG.isDebugEnabled()) {
1200 LOG.debug("Dmac flow entry deleted for elan:{}, logical interface port:{} and mac address:{} on dpn:{}",
1201 elanInstanceName, interfaceInfo.getPortName(), macAddress, dstDpId);
1204 return isFlowsRemovedInSrcDpn;
1207 private void deleteSmacAndDmacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress,
1208 boolean deleteSmac, WriteTransaction deleteFlowGroupTx) {
1209 String elanInstanceName = elanInfo.getElanInstanceName();
1210 long ifTag = interfaceInfo.getInterfaceTag();
1211 BigInteger srcdpId = interfaceInfo.getDpId();
1212 Long elanTag = elanInfo.getElanTag();
1215 .removeFlowToTx(srcdpId,
1216 MDSALUtil.buildFlow(NwConstants.ELAN_SMAC_TABLE, getKnownDynamicmacFlowRef(
1217 NwConstants.ELAN_SMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)),
1220 mdsalManager.removeFlowToTx(srcdpId,
1221 MDSALUtil.buildFlow(NwConstants.ELAN_DMAC_TABLE,
1222 getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)),
1224 if (LOG.isDebugEnabled()) {
1225 LOG.debug("All the required flows deleted for elan:{}, logical Interface port:{} and MAC address:{} "
1226 + "on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, srcdpId);
1231 * Updates the Elan information in the Operational DS. It also updates the
1232 * ElanInstance in the Config DS by setting the adquired elanTag.
1238 * @param elanInstanceAdded
1239 * the elan instance added
1240 * @param elanInterfaces
1241 * the elan interfaces
1245 public static void updateOperationalDataStore(DataBroker broker, IdManagerService idManager,
1246 ElanInstance elanInstanceAdded, List<String> elanInterfaces, WriteTransaction tx) {
1247 String elanInstanceName = elanInstanceAdded.getElanInstanceName();
1248 Long elanTag = elanInstanceAdded.getElanTag();
1249 if (elanTag == null || elanTag == 0L) {
1250 elanTag = retrieveNewElanTag(idManager, elanInstanceName);
1252 Elan elanInfo = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(elanInterfaces)
1253 .setKey(new ElanKey(elanInstanceName)).build();
1255 // Add the ElanState in the elan-state operational data-store
1256 tx.put(LogicalDatastoreType.OPERATIONAL, getElanInstanceOperationalDataPath(elanInstanceName),
1259 // Add the ElanMacTable in the elan-mac-table operational data-store
1260 MacTable elanMacTable = new MacTableBuilder().setKey(new MacTableKey(elanInstanceName)).build();
1261 tx.put(LogicalDatastoreType.OPERATIONAL, getElanMacTableOperationalDataPath(elanInstanceName),
1262 elanMacTable, true);
1264 ElanTagNameBuilder elanTagNameBuilder = new ElanTagNameBuilder().setElanTag(elanTag)
1265 .setKey(new ElanTagNameKey(elanTag)).setName(elanInstanceName);
1266 long etreeLeafTag = -1;
1267 if (isEtreeInstance(elanInstanceAdded)) {
1268 etreeLeafTag = retrieveNewElanTag(idManager, elanInstanceName + ElanConstants.LEAVES_POSTFIX);
1269 EtreeLeafTagName etreeLeafTagName = new EtreeLeafTagNameBuilder()
1270 .setEtreeLeafTag(new EtreeLeafTag(etreeLeafTag)).build();
1271 elanTagNameBuilder.addAugmentation(EtreeLeafTagName.class, etreeLeafTagName);
1272 addTheLeafTagAsElanTag(broker, elanInstanceName, etreeLeafTag, tx);
1274 ElanTagName elanTagName = elanTagNameBuilder.build();
1276 // Add the ElanTag to ElanName in the elan-tag-name Operational
1278 tx.put(LogicalDatastoreType.OPERATIONAL,
1279 getElanInfoEntriesOperationalDataPath(elanTag), elanTagName);
1281 // Updates the ElanInstance Config DS by setting the just acquired
1283 ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName)
1284 .setDescription(elanInstanceAdded.getDescription())
1285 .setMacTimeout(elanInstanceAdded.getMacTimeout() == null ? ElanConstants.DEFAULT_MAC_TIME_OUT
1286 : elanInstanceAdded.getMacTimeout())
1287 .setKey(elanInstanceAdded.getKey()).setElanTag(elanTag);
1288 if (isEtreeInstance(elanInstanceAdded)) {
1289 EtreeInstance etreeInstance = new EtreeInstanceBuilder().setEtreeLeafTagVal(new EtreeLeafTag(etreeLeafTag))
1291 elanInstanceBuilder.addAugmentation(EtreeInstance.class, etreeInstance);
1293 ElanInstance elanInstanceWithTag = elanInstanceBuilder.build();
1294 tx.merge(LogicalDatastoreType.CONFIGURATION, getElanInstanceConfigurationDataPath(elanInstanceName),
1295 elanInstanceWithTag, true);
1298 private static void addTheLeafTagAsElanTag(DataBroker broker, String elanInstanceName, long etreeLeafTag,
1299 WriteTransaction tx) {
1300 ElanTagName etreeTagAsElanTag = new ElanTagNameBuilder().setElanTag(etreeLeafTag)
1301 .setKey(new ElanTagNameKey(etreeLeafTag)).setName(elanInstanceName).build();
1302 tx.put(LogicalDatastoreType.OPERATIONAL,
1303 getElanInfoEntriesOperationalDataPath(etreeLeafTag), etreeTagAsElanTag);
1306 private static boolean isEtreeInstance(ElanInstance elanInstanceAdded) {
1307 return elanInstanceAdded.getAugmentation(EtreeInstance.class) != null;
1310 public boolean isDpnPresent(BigInteger dpnId) {
1311 String dpn = String.format("%s:%s", "openflow", dpnId);
1312 NodeId nodeId = new NodeId(dpn);
1314 InstanceIdentifier<Node> node = InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(nodeId))
1316 Optional<Node> nodePresent = read(broker, LogicalDatastoreType.OPERATIONAL, node);
1317 return nodePresent.isPresent();
1320 public static ServicesInfo getServiceInfo(String elanInstanceName, long elanTag, String interfaceName) {
1321 int priority = ElanConstants.ELAN_SERVICE_PRIORITY;
1322 int instructionKey = 0;
1323 List<Instruction> instructions = new ArrayList<>();
1324 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(getElanMetadataLabel(elanTag),
1325 MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
1326 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.ELAN_SMAC_TABLE, ++instructionKey));
1328 short serviceIndex = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX);
1329 ServicesInfo serviceInfo = InterfaceServiceUtil.buildServiceInfo(
1330 String.format("%s.%s", elanInstanceName, interfaceName), serviceIndex, priority,
1331 NwConstants.COOKIE_ELAN_INGRESS_TABLE, instructions);
1335 public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
1336 InstanceIdentifier<T> path, T data) {
1337 WriteTransaction tx = broker.newWriteOnlyTransaction();
1338 tx.put(datastoreType, path, data, true);
1339 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
1342 } catch (InterruptedException | ExecutionException e) {
1343 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
1344 throw new RuntimeException(e.getMessage());
1348 public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
1349 BigInteger cookie, List<Instruction> instructions) {
1350 StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority)
1351 .setInstruction(instructions);
1352 return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)).setServiceName(serviceName)
1353 .setServicePriority(servicePriority).setServiceType(ServiceTypeFlowBased.class)
1354 .addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
1357 public static InstanceIdentifier<BoundServices> buildServiceId(String vpnInterfaceName, short serviceIndex) {
1358 return InstanceIdentifier.builder(ServiceBindings.class)
1359 .child(ServicesInfo.class, new ServicesInfoKey(vpnInterfaceName, ServiceModeIngress.class))
1360 .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
1364 * Builds the list of actions to be taken when sending the packet over a
1365 * VxLan Tunnel Interface, such as setting the tunnel_id field, the vlanId
1366 * if proceeds and output the packet over the right port.
1368 * @param tunnelIfaceName
1369 * the tunnel iface name
1374 public List<Action> buildTunnelItmEgressActions(String tunnelIfaceName, Long tunnelKey) {
1375 if (tunnelIfaceName != null && !tunnelIfaceName.isEmpty()) {
1376 return buildItmEgressActions(tunnelIfaceName, tunnelKey);
1379 return Collections.emptyList();
1383 * Builds the list of actions to be taken when sending the packet over
1384 * external port such as tunnel, physical port etc.
1386 * @param interfaceName
1387 * the interface name
1389 * can be VNI for VxLAN tunnel interfaces, Gre Key for GRE
1393 public List<Action> buildItmEgressActions(String interfaceName, Long tunnelKey) {
1394 List<Action> result = Collections.emptyList();
1395 GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
1396 .setIntfName(interfaceName).setTunnelKey(tunnelKey).build();
1398 Future<RpcResult<GetEgressActionsForInterfaceOutput>> egressActionsOutputFuture = interfaceManagerRpcService
1399 .getEgressActionsForInterface(getEgressActInput);
1401 if (egressActionsOutputFuture.get().isSuccessful()) {
1402 GetEgressActionsForInterfaceOutput egressActionsOutput = egressActionsOutputFuture.get().getResult();
1403 result = egressActionsOutput.getAction();
1405 } catch (InterruptedException | ExecutionException e) {
1406 LOG.error("Error in RPC call getEgressActionsForInterface {}", e);
1409 if (result == null || result.size() == 0) {
1410 LOG.warn("Could not build Egress actions for interface {} and tunnelId {}", interfaceName, tunnelKey);
1416 * Builds the list of actions to be taken when sending the packet over an
1417 * external VxLan tunnel interface, such as stamping the VNI on the VxLAN
1418 * header, setting the vlanId if it proceeds and output the packet over the
1422 * Dpn where the tunnelInterface is located
1424 * NodeId of the ExternalDevice where the packet must be sent to.
1426 * Vni to be stamped on the VxLAN Header.
1427 * @return the external itm egress action
1429 public List<Action> getExternalTunnelItmEgressAction(BigInteger srcDpnId, NodeId torNode, long vni) {
1430 List<Action> result = Collections.emptyList();
1432 GetExternalTunnelInterfaceNameInput input = new GetExternalTunnelInterfaceNameInputBuilder()
1433 .setDestinationNode(torNode.getValue()).setSourceNode(srcDpnId.toString())
1434 .setTunnelType(TunnelTypeVxlan.class).build();
1435 Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
1436 .getExternalTunnelInterfaceName(input);
1438 if (output.get().isSuccessful()) {
1439 GetExternalTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
1440 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
1441 if (LOG.isDebugEnabled()) {
1442 LOG.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
1445 result = buildTunnelItmEgressActions(tunnelIfaceName, vni);
1448 } catch (InterruptedException | ExecutionException e) {
1449 LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
1456 * Builds the list of actions to be taken when sending the packet over an
1457 * internal VxLan tunnel interface, such as setting the serviceTag on the
1458 * VNI field of the VxLAN header, setting the vlanId if it proceeds and
1459 * output the packet over the right port.
1461 * @param sourceDpnId
1462 * Dpn where the tunnelInterface is located
1463 * @param destinationDpnId
1464 * Dpn where the packet must be sent to. It is used here in order
1465 * to select the right tunnel interface.
1467 * serviceId to be sent on the VxLAN header.
1468 * @return the internal itm egress action
1470 public List<Action> getInternalTunnelItmEgressAction(BigInteger sourceDpnId, BigInteger destinationDpnId,
1472 List<Action> result = Collections.emptyList();
1474 LOG.debug("In getInternalItmEgressAction Action source {}, destination {}, elanTag {}", sourceDpnId,
1475 destinationDpnId, serviceTag);
1476 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
1477 GetTunnelInterfaceNameInput input = new GetTunnelInterfaceNameInputBuilder()
1478 .setDestinationDpid(destinationDpnId).setSourceDpid(sourceDpnId).setTunnelType(tunType).build();
1479 Future<RpcResult<GetTunnelInterfaceNameOutput>> output = itmRpcService
1480 .getTunnelInterfaceName(input);
1482 if (output.get().isSuccessful()) {
1483 GetTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
1484 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
1485 LOG.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
1487 result = buildTunnelItmEgressActions(tunnelIfaceName, serviceTag);
1489 } catch (InterruptedException | ExecutionException e) {
1490 LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
1497 * Build the list of actions to be taken when sending the packet to external
1500 * @param interfaceName
1502 * @return the external port itm egress actions
1504 public List<Action> getExternalPortItmEgressAction(String interfaceName) {
1505 return buildItmEgressActions(interfaceName, null);
1508 public static List<MatchInfo> getTunnelMatchesForServiceId(int elanTag) {
1509 List<MatchInfo> mkMatches = new ArrayList<>();
1510 // Matching metadata
1511 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { BigInteger.valueOf(elanTag) }));
1516 public void removeTerminatingServiceAction(BigInteger destDpId, int serviceId) {
1517 RemoveTerminatingServiceActionsInput input = new RemoveTerminatingServiceActionsInputBuilder()
1518 .setDpnId(destDpId).setServiceId(serviceId).build();
1519 Future<RpcResult<Void>> futureObject = itmRpcService
1520 .removeTerminatingServiceActions(input);
1522 RpcResult<Void> result = futureObject.get();
1523 if (result.isSuccessful()) {
1524 LOG.debug("Successfully completed removeTerminatingServiceActions");
1526 LOG.debug("Failure in removeTerminatingServiceAction RPC call");
1528 } catch (InterruptedException | ExecutionException e) {
1529 LOG.error("Error in RPC call removeTerminatingServiceActions {}", e);
1533 public void createTerminatingServiceActions(BigInteger destDpId, int serviceId, List<Action> actions) {
1534 List<Instruction> mkInstructions = new ArrayList<>();
1535 mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
1536 CreateTerminatingServiceActionsInput input = new CreateTerminatingServiceActionsInputBuilder()
1537 .setDpnId(destDpId).setServiceId(serviceId).setInstruction(mkInstructions).build();
1539 itmRpcService.createTerminatingServiceActions(input);
1542 public static TunnelList buildInternalTunnel(DataBroker broker) {
1543 InstanceIdentifier<TunnelList> tunnelListInstanceIdentifier = InstanceIdentifier.builder(TunnelList.class)
1545 Optional<TunnelList> tunnelList = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
1546 tunnelListInstanceIdentifier);
1547 if (tunnelList.isPresent()) {
1548 return tunnelList.get();
1554 * Gets the external tunnel.
1556 * @param sourceDevice
1558 * @param destinationDevice
1559 * the destination device
1560 * @param datastoreType
1561 * the datastore type
1562 * @return the external tunnel
1564 public ExternalTunnel getExternalTunnel(String sourceDevice, String destinationDevice,
1565 LogicalDatastoreType datastoreType) {
1566 ExternalTunnel externalTunnel = null;
1567 Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
1568 InstanceIdentifier<ExternalTunnel> iid = InstanceIdentifier.builder(ExternalTunnelList.class)
1569 .child(ExternalTunnel.class, new ExternalTunnelKey(destinationDevice, sourceDevice, tunType)).build();
1570 Optional<ExternalTunnel> tunnelList = read(broker, datastoreType, iid);
1571 if (tunnelList.isPresent()) {
1572 externalTunnel = tunnelList.get();
1574 return externalTunnel;
1578 * Gets the external tunnel.
1580 * @param interfaceName
1581 * the interface name
1582 * @param datastoreType
1583 * the datastore type
1584 * @return the external tunnel
1586 public ExternalTunnel getExternalTunnel(String interfaceName, LogicalDatastoreType datastoreType) {
1587 ExternalTunnel externalTunnel = null;
1588 List<ExternalTunnel> externalTunnels = getAllExternalTunnels(datastoreType);
1589 for (ExternalTunnel tunnel : externalTunnels) {
1590 if (StringUtils.equalsIgnoreCase(interfaceName, tunnel.getTunnelInterfaceName())) {
1591 externalTunnel = tunnel;
1595 return externalTunnel;
1599 * Gets the all external tunnels.
1601 * @param datastoreType
1602 * the data store type
1603 * @return the all external tunnels
1605 public List<ExternalTunnel> getAllExternalTunnels(LogicalDatastoreType datastoreType) {
1606 List<ExternalTunnel> result = null;
1607 InstanceIdentifier<ExternalTunnelList> iid = InstanceIdentifier.builder(ExternalTunnelList.class).build();
1608 Optional<ExternalTunnelList> tunnelList = read(broker, datastoreType, iid);
1609 if (tunnelList.isPresent()) {
1610 result = tunnelList.get().getExternalTunnel();
1612 if (result == null) {
1613 result = Collections.emptyList();
1619 * Installs a Flow in a DPN's DMAC table. The Flow is for a MAC that is
1620 * connected remotely in another CSS and accessible through an internal
1621 * tunnel. It also installs the flow for dropping the packet if it came over
1622 * an ITM tunnel (that is, if the Split-Horizon flag is set)
1625 * Id of the DPN where the MAC Addr is accessible locally
1627 * Id of the DPN where the flow must be installed
1629 * lportTag of the interface where the mac is connected to.
1631 * Identifier of the ELAN
1633 * MAC to be installed in remoteDpId's DMAC table
1634 * @param displayName
1636 * @throws ElanException in case of issues creating the flow objects
1638 public void installDmacFlowsToInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, long lportTag,
1639 long elanTag, String macAddress, String displayName) throws ElanException {
1640 Flow flow = buildDmacFlowForInternalRemoteMac(localDpId, remoteDpId, lportTag, elanTag, macAddress,
1642 mdsalManager.installFlow(remoteDpId, flow);
1646 * Installs a Flow in the specified DPN's DMAC table. The flow is for a MAC
1647 * that is connected remotely in an External Device (TOR) and that is
1648 * accessible through an external tunnel. It also installs the flow for
1649 * dropping the packet if it came over an ITM tunnel (that is, if the
1650 * Split-Horizon flag is set)
1653 * Id of the DPN where the flow must be installed
1654 * @param extDeviceNodeId
1655 * the ext device node id
1662 * @param displayName
1664 * @param interfaceName
1665 * the interface name
1667 * @return the dmac flows
1668 * @throws ElanException in case of issues creating the flow objects
1670 public List<ListenableFuture<Void>> installDmacFlowsToExternalRemoteMac(BigInteger dpnId,
1671 String extDeviceNodeId, Long elanTag, Long vni, String macAddress, String displayName,
1672 String interfaceName) throws ElanException {
1673 List<ListenableFuture<Void>> futures = new ArrayList<>();
1674 synchronized (macAddress) {
1675 Flow flow = buildDmacFlowForExternalRemoteMac(dpnId, extDeviceNodeId, elanTag, vni, macAddress,
1677 futures.add(mdsalManager.installFlow(dpnId, flow));
1679 Flow dropFlow = buildDmacFlowDropIfPacketComingFromTunnel(dpnId, extDeviceNodeId, elanTag, macAddress);
1680 futures.add(mdsalManager.installFlow(dpnId, dropFlow));
1681 installEtreeDmacFlowsToExternalRemoteMac(dpnId, extDeviceNodeId, elanTag, vni, macAddress, displayName,
1682 interfaceName, futures);
1687 private void installEtreeDmacFlowsToExternalRemoteMac(BigInteger dpnId, String extDeviceNodeId, Long elanTag,
1688 Long vni, String macAddress, String displayName, String interfaceName,
1689 List<ListenableFuture<Void>> futures) throws ElanException {
1690 EtreeLeafTagName etreeLeafTag = getEtreeLeafTagByElanTag(elanTag);
1691 if (etreeLeafTag != null) {
1692 buildEtreeDmacFlowDropIfPacketComingFromTunnel(dpnId, extDeviceNodeId, elanTag, macAddress, futures,
1694 buildEtreeDmacFlowForExternalRemoteMac(dpnId, extDeviceNodeId, vni, macAddress, displayName, interfaceName,
1695 futures, etreeLeafTag);
1699 private void buildEtreeDmacFlowForExternalRemoteMac(BigInteger dpnId, String extDeviceNodeId, Long vni,
1700 String macAddress, String displayName, String interfaceName, List<ListenableFuture<Void>> futures,
1701 EtreeLeafTagName etreeLeafTag) throws ElanException {
1702 boolean isRoot = false;
1703 if (interfaceName == null) {
1706 EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, interfaceName);
1707 if (etreeInterface != null) {
1708 if (etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
1714 Flow flow = buildDmacFlowForExternalRemoteMac(dpnId, extDeviceNodeId,
1715 etreeLeafTag.getEtreeLeafTag().getValue(), vni, macAddress, displayName);
1716 futures.add(mdsalManager.installFlow(dpnId, flow));
1720 private void buildEtreeDmacFlowDropIfPacketComingFromTunnel(BigInteger dpnId, String extDeviceNodeId,
1721 Long elanTag, String macAddress, List<ListenableFuture<Void>> futures, EtreeLeafTagName etreeLeafTag) {
1722 if (etreeLeafTag != null) {
1723 Flow dropFlow = buildDmacFlowDropIfPacketComingFromTunnel(dpnId, extDeviceNodeId,
1724 etreeLeafTag.getEtreeLeafTag().getValue(), macAddress);
1725 futures.add(mdsalManager.installFlow(dpnId, dropFlow));
1729 public static List<MatchInfo> buildMatchesForElanTagShFlagAndDstMac(long elanTag, boolean shFlag, String macAddr) {
1730 List<MatchInfo> mkMatches = new ArrayList<>();
1731 mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
1732 getElanMetadataLabel(elanTag, shFlag), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG }));
1733 mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddr }));
1739 * Builds a Flow to be programmed in a DPN's DMAC table. This method must be
1740 * used when the MAC is located in an External Device (TOR). The flow
1741 * matches on the specified MAC and 1) sends the packet over the CSS-TOR
1742 * tunnel if SHFlag is not set, or 2) drops it if SHFlag is set (what means
1743 * the packet came from an external tunnel)
1746 * DPN whose DMAC table is going to be modified
1747 * @param extDeviceNodeId
1748 * Hwvtep node where the mac is attached to
1750 * ElanId to which the MAC is being added to
1753 * @param dstMacAddress
1754 * The mac address to be programmed
1755 * @param displayName
1758 * @throws ElanException in case of issues creating the flow objects
1760 @SuppressWarnings("checkstyle:IllegalCatch")
1761 public Flow buildDmacFlowForExternalRemoteMac(BigInteger dpId, String extDeviceNodeId, long elanTag,
1762 Long vni, String dstMacAddress, String displayName) throws ElanException {
1763 List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /* shFlag */ false, dstMacAddress);
1764 List<Instruction> mkInstructions = new ArrayList<>();
1766 List<Action> actions = getExternalTunnelItmEgressAction(dpId, new NodeId(extDeviceNodeId), vni);
1767 mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
1768 } catch (Exception e) {
1769 LOG.error("Could not get Egress Actions for DpId=" + dpId + ", externalNode=" + extDeviceNodeId, e);
1772 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
1773 getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, dstMacAddress, elanTag,
1776 displayName, 0, /* idleTimeout */
1777 0, /* hardTimeout */
1778 ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
1784 * Builds the flow that drops the packet if it came through an external
1785 * tunnel, that is, if the Split-Horizon flag is set.
1788 * DPN whose DMAC table is going to be modified
1789 * @param extDeviceNodeId
1790 * Hwvtep node where the mac is attached to
1792 * ElanId to which the MAC is being added to
1793 * @param dstMacAddress
1794 * The mac address to be programmed
1796 private static Flow buildDmacFlowDropIfPacketComingFromTunnel(BigInteger dpnId, String extDeviceNodeId,
1797 Long elanTag, String dstMacAddress) {
1798 List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /* shFlag */ true, dstMacAddress);
1799 List<Instruction> mkInstructions = MDSALUtil.buildInstructionsDrop();
1800 String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpnId, extDeviceNodeId, dstMacAddress,
1802 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE, flowId, 20, /* prio */
1803 "Drop", 0, /* idleTimeout */
1804 0, /* hardTimeout */
1805 ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
1810 private static String getDmacDropFlowId(Long elanTag, String dstMacAddress) {
1811 return new StringBuilder(NwConstants.ELAN_DMAC_TABLE).append(elanTag).append(dstMacAddress).append("Drop")
1816 * Builds a Flow to be programmed in a remote DPN's DMAC table. This method
1817 * must be used when the MAC is located in another CSS.
1819 * <p>This flow consists in: Match: + elanTag in packet's metadata + packet
1820 * going to a MAC known to be located in another DPN Actions: +
1821 * set_tunnel_id(lportTag) + output on ITM internal tunnel interface with
1834 * @param displayName
1837 * @throws ElanException in case of issues creating the flow objects
1839 @SuppressWarnings("checkstyle:IllegalCatch")
1840 public Flow buildDmacFlowForInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, long lportTag,
1841 long elanTag, String macAddress, String displayName) throws ElanException {
1842 List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /* shFlag */ false, macAddress);
1844 List<Instruction> mkInstructions = new ArrayList<>();
1847 // List of Action for the provided Source and Destination DPIDs
1848 List<Action> actions = getInternalTunnelItmEgressAction(localDpId, remoteDpId, lportTag);
1849 mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
1850 } catch (Exception e) {
1851 LOG.error("Could not get Egress Actions for localDpId=" + localDpId + ", remoteDpId="
1852 + remoteDpId + ", lportTag=" + lportTag, e);
1855 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
1856 getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, localDpId, remoteDpId, macAddress, elanTag),
1858 displayName, 0, /* idleTimeout */
1859 0, /* hardTimeout */
1860 ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
1867 * Installs or removes flows in DMAC table for MACs that are/were located in
1868 * an external Elan Device.
1871 * Id of the DPN where the DMAC table is going to be modified
1873 * Id of the External Device where the MAC is located
1877 * VNI of the LogicalSwitch to which the MAC belongs to, and that
1878 * is associated with the ELAN
1881 * @param elanInstanceName
1882 * the elan instance name
1883 * @param addOrRemove
1884 * Indicates if flows must be installed or removed.
1885 * @param interfaceName
1886 * the interface name
1887 * @throws ElanException in case of issues creating the flow objects
1888 * @see org.opendaylight.genius.mdsalutil.MDSALUtil.MdsalOp
1890 public void setupDmacFlowsToExternalRemoteMac(BigInteger dpId, String extNodeId, Long elanTag, Long vni,
1891 String macAddress, String elanInstanceName, MdsalOp addOrRemove, String interfaceName)
1892 throws ElanException {
1893 if (addOrRemove == MdsalOp.CREATION_OP) {
1894 installDmacFlowsToExternalRemoteMac(dpId, extNodeId, elanTag, vni, macAddress, elanInstanceName,
1896 } else if (addOrRemove == MdsalOp.REMOVAL_OP) {
1897 deleteDmacFlowsToExternalMac(elanTag, dpId, extNodeId, macAddress);
1902 * Delete dmac flows to external mac.
1908 * @param extDeviceNodeId
1909 * the ext device node id
1910 * @param macToRemove
1914 public List<ListenableFuture<Void>> deleteDmacFlowsToExternalMac(long elanTag, BigInteger dpId,
1915 String extDeviceNodeId, String macToRemove) {
1916 List<ListenableFuture<Void>> futures = new ArrayList<>();
1917 synchronized (macToRemove) {
1918 // Removing the flows that sends the packet on an external tunnel
1919 removeFlowThatSendsThePacketOnAnExternalTunnel(elanTag, dpId, extDeviceNodeId, macToRemove, futures);
1921 // And now removing the drop flow
1922 removeTheDropFlow(elanTag, dpId, extDeviceNodeId, macToRemove, futures);
1924 deleteEtreeDmacFlowsToExternalMac(elanTag, dpId, extDeviceNodeId, macToRemove, futures);
1929 private void deleteEtreeDmacFlowsToExternalMac(long elanTag, BigInteger dpId, String extDeviceNodeId,
1930 String macToRemove, List<ListenableFuture<Void>> futures) {
1931 EtreeLeafTagName etreeLeafTag = getEtreeLeafTagByElanTag(elanTag);
1932 if (etreeLeafTag != null) {
1933 removeFlowThatSendsThePacketOnAnExternalTunnel(etreeLeafTag.getEtreeLeafTag().getValue(), dpId,
1934 extDeviceNodeId, macToRemove, futures);
1935 removeTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue(), dpId, extDeviceNodeId, macToRemove, futures);
1939 private void removeTheDropFlow(long elanTag, BigInteger dpId, String extDeviceNodeId, String macToRemove,
1940 List<ListenableFuture<Void>> futures) {
1941 String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, macToRemove,
1943 Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
1944 futures.add(mdsalManager.removeFlow(dpId, flowToRemove));
1947 private void removeFlowThatSendsThePacketOnAnExternalTunnel(long elanTag, BigInteger dpId,
1948 String extDeviceNodeId, String macToRemove, List<ListenableFuture<Void>> futures) {
1949 String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, macToRemove,
1951 Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
1952 futures.add(mdsalManager.removeFlow(dpId, flowToRemove));
1956 * Gets the dpid from interface.
1958 * @param interfaceName
1959 * the interface name
1960 * @return the dpid from interface
1962 public BigInteger getDpidFromInterface(String interfaceName) {
1963 BigInteger dpId = null;
1964 Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService
1965 .getDpidFromInterface(new GetDpidFromInterfaceInputBuilder().setIntfName(interfaceName).build());
1967 RpcResult<GetDpidFromInterfaceOutput> rpcResult = output.get();
1968 if (rpcResult.isSuccessful()) {
1969 dpId = rpcResult.getResult().getDpid();
1971 } catch (NullPointerException | InterruptedException | ExecutionException e) {
1972 LOG.error("Failed to get the DPN ID: {} for interface {}: {} ", dpId, interfaceName, e);
1978 * Checks if is interface operational.
1980 * @param interfaceName
1981 * the interface name
1984 * @return true, if is interface operational
1986 public static boolean isInterfaceOperational(String interfaceName, DataBroker dataBroker) {
1987 if (StringUtils.isBlank(interfaceName)) {
1990 Interface ifState = getInterfaceStateFromOperDS(interfaceName, dataBroker);
1991 if (ifState == null) {
1994 return ifState.getOperStatus() == OperStatus.Up && ifState.getAdminStatus() == AdminStatus.Up;
1998 * Gets the interface state from operational ds.
2000 * @param interfaceName
2001 * the interface name
2004 * @return the interface state from oper ds
2006 public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2007 .ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
2008 String interfaceName, DataBroker dataBroker) {
2009 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2010 .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = createInterfaceStateInstanceIdentifier(
2012 Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2013 .ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = MDSALUtil
2014 .read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
2015 if (ifStateOptional.isPresent()) {
2016 return ifStateOptional.get();
2022 * Gets the interface from config ds.
2024 * @param interfaceName
2025 * the interface name
2028 * @return the interface from config ds
2030 public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2031 .ietf.interfaces.rev140508.interfaces.Interface getInterfaceFromConfigDS(
2032 String interfaceName, DataBroker dataBroker) {
2033 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2034 .ietf.interfaces.rev140508.interfaces.Interface> ifaceId = createInterfaceInstanceIdentifier(interfaceName);
2035 Optional<org.opendaylight.yang.gen.v1.urn
2036 .ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> iface = MDSALUtil
2037 .read(dataBroker, LogicalDatastoreType.CONFIGURATION, ifaceId);
2038 if (iface.isPresent()) {
2045 * Creates the interface state instance identifier.
2047 * @param interfaceName
2048 * the interface name
2049 * @return the instance identifier
2051 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2052 .ietf.interfaces.rev140508.interfaces.state.Interface> createInterfaceStateInstanceIdentifier(
2053 String interfaceName) {
2054 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2055 .ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder = InstanceIdentifier
2056 .builder(InterfacesState.class)
2057 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2058 .ietf.interfaces.rev140508.interfaces.state.Interface.class,
2059 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2060 .ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
2062 return idBuilder.build();
2066 * Creates the interface instance identifier.
2068 * @param interfaceName
2069 * the interface name
2070 * @return the instance identifier
2072 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2073 .ietf.interfaces.rev140508.interfaces.Interface> createInterfaceInstanceIdentifier(
2074 String interfaceName) {
2075 InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2076 .ietf.interfaces.rev140508.interfaces.Interface> idBuilder = InstanceIdentifier
2077 .builder(Interfaces.class)
2078 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2079 .ietf.interfaces.rev140508.interfaces.Interface.class,
2080 new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2081 .ietf.interfaces.rev140508.interfaces.InterfaceKey(
2083 return idBuilder.build();
2086 public static CheckedFuture<Void, TransactionCommitFailedException> waitForTransactionToComplete(
2087 WriteTransaction tx) {
2088 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
2091 } catch (InterruptedException | ExecutionException e) {
2092 LOG.error("Error writing to datastore {}", e);
2097 public static boolean isVxlan(ElanInstance elanInstance) {
2098 return elanInstance != null && elanInstance.getSegmentType() != null
2099 && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeVxlan.class)
2100 && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId().longValue() != 0;
2103 public static boolean isVlan(ElanInstance elanInstance) {
2104 return elanInstance != null && elanInstance.getSegmentType() != null
2105 && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeVlan.class)
2106 && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId().longValue() != 0;
2109 public static boolean isFlat(ElanInstance elanInstance) {
2110 return elanInstance != null && elanInstance.getSegmentType() != null
2111 && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeFlat.class);
2114 public boolean isExternal(String interfaceName) {
2115 return isExternal(getInterfaceFromConfigDS(interfaceName, broker));
2118 public static boolean isExternal(
2119 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang
2120 .ietf.interfaces.rev140508.interfaces.Interface iface) {
2121 if (iface == null) {
2125 IfExternal ifExternal = iface.getAugmentation(IfExternal.class);
2126 return ifExternal != null && Boolean.TRUE.equals(ifExternal.isExternal());
2129 public static boolean isEtreeRootInterfaceByInterfaceName(DataBroker broker, String interfaceName) {
2130 EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, interfaceName);
2131 if (etreeInterface != null && etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root) {
2138 * Add Mac Address to ElanInterfaceForwardingEntries and ElanForwardingTables
2139 * Install SMAC and DMAC flows.
2141 public void addMacEntryToDsAndSetupFlows(IInterfaceManager interfaceManager, String interfaceName,
2142 String macAddress, String elanName, WriteTransaction tx, WriteTransaction flowWritetx, int macTimeOut)
2143 throws ElanException {
2144 LOG.trace("Adding mac address {} and interface name {} to ElanInterfaceForwardingEntries and "
2145 + "ElanForwardingTables DS", macAddress, interfaceName);
2146 BigInteger timeStamp = new BigInteger(String.valueOf(System.currentTimeMillis()));
2147 PhysAddress physAddress = new PhysAddress(macAddress);
2148 MacEntry macEntry = new MacEntryBuilder().setInterface(interfaceName).setMacAddress(physAddress)
2149 .setKey(new MacEntryKey(physAddress)).setControllerLearnedForwardingEntryTimestamp(timeStamp)
2150 .setIsStaticAddress(false).build();
2151 InstanceIdentifier<MacEntry> macEntryId = ElanUtils
2152 .getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
2153 tx.put(LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry);
2154 InstanceIdentifier<MacEntry> elanMacEntryId = ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress);
2155 tx.put(LogicalDatastoreType.OPERATIONAL, elanMacEntryId, macEntry);
2156 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(broker, elanName);
2157 setupMacFlows(elanInstance, interfaceManager.getInterfaceInfo(interfaceName), macTimeOut, macAddress,
2162 * Remove Mac Address from ElanInterfaceForwardingEntries and ElanForwardingTables
2163 * Remove SMAC and DMAC flows.
2165 public void deleteMacEntryFromDsAndRemoveFlows(IInterfaceManager interfaceManager, String interfaceName,
2166 String macAddress, String elanName, WriteTransaction tx, WriteTransaction deleteFlowTx) {
2167 LOG.trace("Deleting mac address {} and interface name {} from ElanInterfaceForwardingEntries "
2168 + "and ElanForwardingTables DS", macAddress, interfaceName);
2169 PhysAddress physAddress = new PhysAddress(macAddress);
2170 MacEntry macEntry = getInterfaceMacEntriesOperationalDataPath(interfaceName, physAddress);
2171 InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
2172 if (macEntry != null && interfaceInfo != null) {
2173 deleteMacFlows(ElanUtils.getElanInstanceByName(broker, elanName), interfaceInfo, macEntry, deleteFlowTx);
2175 tx.delete(LogicalDatastoreType.OPERATIONAL,
2176 ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress));
2177 tx.delete(LogicalDatastoreType.OPERATIONAL,
2178 ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress));