2 * Copyright © 2017 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
9 package org.opendaylight.netvirt.elan.evpn.utils;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.HashMap;
16 import java.util.List;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.genius.mdsalutil.MDSALUtil;
21 import org.opendaylight.genius.mdsalutil.MatchInfo;
22 import org.opendaylight.genius.mdsalutil.NwConstants;
23 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
24 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
25 import org.opendaylight.mdsal.binding.api.DataBroker;
26 import org.opendaylight.mdsal.binding.util.Datastore;
27 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
28 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.netvirt.elan.utils.ElanConstants;
30 import org.opendaylight.netvirt.elan.utils.ElanEtreeUtils;
31 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
32 import org.opendaylight.netvirt.elan.utils.ElanUtils;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
40 import org.opendaylight.yangtools.yang.common.Uint64;
43 public class ElanEvpnFlowUtils {
44 private final IMdsalApiManager mdsalManager;
45 private final ElanItmUtils elanItmUtils;
46 private final ElanEtreeUtils elanEtreeUtils;
47 private final ManagedNewTransactionRunner txRunner;
50 public ElanEvpnFlowUtils(final IMdsalApiManager mdsalManager, final ElanItmUtils elanItmUtils,
51 final ElanEtreeUtils elanEtreeUtils, final DataBroker dataBroker) {
52 this.mdsalManager = mdsalManager;
53 this.elanItmUtils = elanItmUtils;
54 this.elanEtreeUtils = elanEtreeUtils;
55 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
58 public Flow evpnBuildDmacFlowForExternalRemoteMac(EvpnDmacFlow evpnDmacFlow) {
59 List<MatchInfo> mkMatches = ElanUtils.buildMatchesForElanTagShFlagAndDstMac(evpnDmacFlow.getElanTag(), false,
60 evpnDmacFlow.getDstMacAddress());
61 Map<InstructionKey, Instruction> mkInstructionsMap = new HashMap<>();
62 List<Action> actions = elanItmUtils.getExternalTunnelItmEgressAction(evpnDmacFlow.getDpId(),
63 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getVni());
64 mkInstructionsMap.put(new InstructionKey(0), MDSALUtil.buildApplyActionsInstruction(actions));
65 Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
66 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, evpnDmacFlow.getDpId(),
67 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress(), evpnDmacFlow.getElanTag(), false),
68 20, evpnDmacFlow.getElanName(), 0, 0,
69 Uint64.valueOf(ElanConstants.COOKIE_ELAN_KNOWN_DMAC.toJava()
70 .add(BigInteger.valueOf(evpnDmacFlow.getElanTag()))),
71 mkMatches, mkInstructionsMap);
76 public List<ListenableFuture<?>> evpnDeleteDmacFlowsToExternalMac(EvpnDmacFlow evpnDmacFlow) {
77 List<ListenableFuture<?>> futures = new ArrayList<>();
78 try (Acquired lock = ElanUtils.lockElanMacDPN(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDstMacAddress(),
79 evpnDmacFlow.getDpId())) {
81 evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(evpnDmacFlow.getElanTag(), evpnDmacFlow.dpId,
82 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
83 futures.addAll(evpnDeleteEtreeDmacFlowsToExternalMac(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDpId(),
84 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
89 private List<ListenableFuture<?>> evpnDeleteEtreeDmacFlowsToExternalMac(long elanTag, Uint64 dpId,
90 String nexthopIp, String macToRemove) {
91 List<ListenableFuture<?>> futures = new ArrayList<>();
92 EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag);
93 if (etreeLeafTag != null) {
95 evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(
96 etreeLeafTag.getEtreeLeafTag().getValue().toJava(), dpId,
97 nexthopIp, macToRemove));
99 evpnRemoveTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue().toJava(),
100 dpId, nexthopIp, macToRemove));
105 static String evpnGetKnownDynamicmacFlowRef(short elanDmacTable, Uint64 dpId, String nexthopIp,
106 String dstMacAddress, long elanTag, boolean shFlag) {
107 return String.valueOf(elanDmacTable) + elanTag + dpId + nexthopIp + dstMacAddress + shFlag;
110 private List<ListenableFuture<?>> evpnRemoveTheDropFlow(long elanTag, Uint64 dpId, String nexthopIp,
111 String macToRemove) {
112 String flowId = ElanEvpnFlowUtils.evpnGetKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, nexthopIp,
113 macToRemove, elanTag, true);
114 Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
115 return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION,
116 tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
119 private List<ListenableFuture<?>> evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(long elanTag,
120 Uint64 dpId, String nexthopIp, String macToRemove) {
121 String flowId = ElanEvpnFlowUtils.evpnGetKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, nexthopIp,
122 macToRemove, elanTag, false);
123 Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
124 return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION,
125 tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
128 public static class EvpnDmacFlowBuilder {
130 private String nexthopIP;
131 private long elanTag;
133 private String dstMacAddress;
134 private String elanName;
136 public EvpnDmacFlowBuilder() {
139 public EvpnDmacFlowBuilder setDpId(Uint64 dpId) {
144 public EvpnDmacFlowBuilder setNexthopIP(String nexthopIP) {
145 this.nexthopIP = nexthopIP;
149 public EvpnDmacFlowBuilder setElanTag(long elanTag) {
150 this.elanTag = elanTag;
154 public EvpnDmacFlowBuilder setVni(Long vni) {
159 public EvpnDmacFlowBuilder setDstMacAddress(String dstMacAddress) {
160 this.dstMacAddress = dstMacAddress;
164 public EvpnDmacFlowBuilder setElanName(String elanName) {
165 this.elanName = elanName;
169 public EvpnDmacFlow build() {
170 return new EvpnDmacFlow(dpId, nexthopIP, elanTag, vni, dstMacAddress, elanName);
174 static class EvpnDmacFlow {
175 private final Uint64 dpId;
176 private final String nexthopIP;
177 private final long elanTag;
178 private final Long vni;
179 private final String dstMacAddress;
180 private final String elanName;
182 EvpnDmacFlow(Uint64 dpId, String nexthopIP, long elanTag, Long vni, String dstMacAddress,
185 this.nexthopIP = nexthopIP;
186 this.elanTag = elanTag;
188 this.dstMacAddress = dstMacAddress;
189 this.elanName = elanName;
192 public Uint64 getDpId() {
196 public String getNexthopIP() {
200 public long getElanTag() {
204 public Long getVni() {
208 public String getDstMacAddress() {
209 return dstMacAddress;
212 public String getElanName() {