Migrate ElanUtils to use NamedLocks
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / evpn / utils / ElanEvpnFlowUtils.java
1 /*
2  * Copyright © 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.elan.evpn.utils;
10
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.List;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.genius.infra.Datastore;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
22 import org.opendaylight.genius.mdsalutil.MDSALUtil;
23 import org.opendaylight.genius.mdsalutil.MatchInfo;
24 import org.opendaylight.genius.mdsalutil.NwConstants;
25 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
26 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
27 import org.opendaylight.netvirt.elan.utils.ElanConstants;
28 import org.opendaylight.netvirt.elan.utils.ElanEtreeUtils;
29 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
30 import org.opendaylight.netvirt.elan.utils.ElanUtils;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
37
38
39 @Singleton
40 public class ElanEvpnFlowUtils {
41     private final IMdsalApiManager mdsalManager;
42     private final ElanItmUtils elanItmUtils;
43     private final ElanEtreeUtils elanEtreeUtils;
44     private final ManagedNewTransactionRunner txRunner;
45
46     @Inject
47     public ElanEvpnFlowUtils(final IMdsalApiManager mdsalManager, final ElanItmUtils elanItmUtils,
48             final ElanEtreeUtils elanEtreeUtils, final DataBroker dataBroker) {
49         this.mdsalManager = mdsalManager;
50         this.elanItmUtils = elanItmUtils;
51         this.elanEtreeUtils = elanEtreeUtils;
52         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
53     }
54
55     public Flow evpnBuildDmacFlowForExternalRemoteMac(EvpnDmacFlow evpnDmacFlow) {
56         List<MatchInfo> mkMatches = ElanUtils.buildMatchesForElanTagShFlagAndDstMac(evpnDmacFlow.getElanTag(), false,
57                 evpnDmacFlow.getDstMacAddress());
58         List<Instruction> mkInstructions = new ArrayList<>();
59         List<Action> actions = elanItmUtils.getExternalTunnelItmEgressAction(evpnDmacFlow.getDpId(),
60                 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getVni());
61         mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
62         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
63                 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, evpnDmacFlow.getDpId(),
64                         evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress(), evpnDmacFlow.getElanTag(), false),
65                 20, evpnDmacFlow.getElanName(), 0, 0,
66                 ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(evpnDmacFlow.getElanTag())), mkMatches,
67                 mkInstructions);
68
69         return flow;
70     }
71
72     public List<ListenableFuture<Void>> evpnDeleteDmacFlowsToExternalMac(EvpnDmacFlow evpnDmacFlow) {
73         List<ListenableFuture<Void>> futures = new ArrayList<>();
74         try (Acquired lock = ElanUtils.lockElanMacDPN(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDstMacAddress(),
75                 evpnDmacFlow.getDpId())) {
76             futures.addAll(
77                     evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(evpnDmacFlow.getElanTag(), evpnDmacFlow.dpId,
78                             evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
79             futures.addAll(evpnDeleteEtreeDmacFlowsToExternalMac(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDpId(),
80                     evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
81         }
82         return futures;
83     }
84
85     private List<ListenableFuture<Void>> evpnDeleteEtreeDmacFlowsToExternalMac(long elanTag, BigInteger dpId,
86             String nexthopIp, String macToRemove) {
87         List<ListenableFuture<Void>> futures = new ArrayList<>();
88         EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag);
89         if (etreeLeafTag != null) {
90             futures.addAll(
91                     evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(etreeLeafTag.getEtreeLeafTag().getValue(), dpId,
92                             nexthopIp, macToRemove));
93             futures.addAll(
94                     evpnRemoveTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue(), dpId, nexthopIp, macToRemove));
95         }
96         return futures;
97     }
98
99     static String evpnGetKnownDynamicmacFlowRef(short elanDmacTable, BigInteger dpId, String nexthopIp,
100                                                 String dstMacAddress, long elanTag, boolean shFlag) {
101         return String.valueOf(elanDmacTable) + elanTag + dpId + nexthopIp + dstMacAddress + shFlag;
102     }
103
104     private List<ListenableFuture<Void>> evpnRemoveTheDropFlow(long elanTag, BigInteger dpId, String nexthopIp,
105             String macToRemove) {
106         String flowId = ElanEvpnFlowUtils.evpnGetKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, nexthopIp,
107                 macToRemove, elanTag, true);
108         Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
109         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION,
110             tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
111     }
112
113     private List<ListenableFuture<Void>> evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(long elanTag,
114             BigInteger dpId, String nexthopIp, String macToRemove) {
115         String flowId = ElanEvpnFlowUtils.evpnGetKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, nexthopIp,
116                 macToRemove, elanTag, false);
117         Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
118         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(Datastore.CONFIGURATION,
119             tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
120     }
121
122     public static class EvpnDmacFlowBuilder {
123         private BigInteger dpId;
124         private String nexthopIP;
125         private long elanTag;
126         private Long vni;
127         private String dstMacAddress;
128         private String elanName;
129
130         public EvpnDmacFlowBuilder() {
131         }
132
133         public EvpnDmacFlowBuilder setDpId(BigInteger dpId) {
134             this.dpId = dpId;
135             return this;
136         }
137
138         public EvpnDmacFlowBuilder setNexthopIP(String nexthopIP) {
139             this.nexthopIP = nexthopIP;
140             return this;
141         }
142
143         public EvpnDmacFlowBuilder setElanTag(long elanTag) {
144             this.elanTag = elanTag;
145             return this;
146         }
147
148         public EvpnDmacFlowBuilder setVni(Long vni) {
149             this.vni = vni;
150             return this;
151         }
152
153         public EvpnDmacFlowBuilder setDstMacAddress(String dstMacAddress) {
154             this.dstMacAddress = dstMacAddress;
155             return this;
156         }
157
158         public EvpnDmacFlowBuilder setElanName(String elanName) {
159             this.elanName = elanName;
160             return this;
161         }
162
163         public EvpnDmacFlow build() {
164             return new EvpnDmacFlow(dpId, nexthopIP, elanTag, vni, dstMacAddress, elanName);
165         }
166     }
167
168     static class EvpnDmacFlow {
169         private final BigInteger dpId;
170         private final String nexthopIP;
171         private final long elanTag;
172         private final Long vni;
173         private final String dstMacAddress;
174         private final String elanName;
175
176         EvpnDmacFlow(BigInteger dpId, String nexthopIP, long elanTag, Long vni, String dstMacAddress,
177                             String elanName) {
178             this.dpId = dpId;
179             this.nexthopIP = nexthopIP;
180             this.elanTag = elanTag;
181             this.vni = vni;
182             this.dstMacAddress = dstMacAddress;
183             this.elanName = elanName;
184         }
185
186         public BigInteger getDpId() {
187             return dpId;
188         }
189
190         public String getNexthopIP() {
191             return nexthopIP;
192         }
193
194         public long getElanTag() {
195             return elanTag;
196         }
197
198         public Long getVni() {
199             return vni;
200         }
201
202         public String getDstMacAddress() {
203             return dstMacAddress;
204         }
205
206         public String getElanName() {
207             return elanName;
208         }
209     }
210 }