Bulk merge of l2gw changes
[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 static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
12
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20 import javax.inject.Inject;
21 import javax.inject.Singleton;
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.mdsal.binding.api.DataBroker;
28 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
29 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
30 import org.opendaylight.netvirt.elan.utils.ElanConstants;
31 import org.opendaylight.netvirt.elan.utils.ElanEtreeUtils;
32 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
33 import org.opendaylight.netvirt.elan.utils.ElanUtils;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
41 import org.opendaylight.yangtools.yang.common.Uint64;
42
43 @Singleton
44 public class ElanEvpnFlowUtils {
45     private final IMdsalApiManager mdsalManager;
46     private final ElanItmUtils elanItmUtils;
47     private final ElanEtreeUtils elanEtreeUtils;
48     private final ManagedNewTransactionRunner txRunner;
49
50     @Inject
51     public ElanEvpnFlowUtils(final IMdsalApiManager mdsalManager, final ElanItmUtils elanItmUtils,
52             final ElanEtreeUtils elanEtreeUtils, final DataBroker dataBroker) {
53         this.mdsalManager = mdsalManager;
54         this.elanItmUtils = elanItmUtils;
55         this.elanEtreeUtils = elanEtreeUtils;
56         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
57     }
58
59     public Flow evpnBuildDmacFlowForExternalRemoteMac(EvpnDmacFlow evpnDmacFlow) {
60         List<MatchInfo> mkMatches = ElanUtils.buildMatchesForElanTagShFlagAndDstMac(evpnDmacFlow.getElanTag(), false,
61                 evpnDmacFlow.getDstMacAddress());
62         Map<InstructionKey, Instruction> mkInstructionsMap = new HashMap<>();
63         List<Action> actions = elanItmUtils.getExternalTunnelItmEgressAction(evpnDmacFlow.getDpId(),
64                 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getVni());
65         mkInstructionsMap.put(new InstructionKey(0), MDSALUtil.buildApplyActionsInstruction(actions));
66         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
67                 ElanUtils.getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, evpnDmacFlow.getDpId(),
68                         evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress(), evpnDmacFlow.getElanTag(), false),
69                 20, evpnDmacFlow.getElanName(), 0, 0,
70                 Uint64.valueOf(ElanConstants.COOKIE_ELAN_KNOWN_DMAC.toJava()
71                     .add(BigInteger.valueOf(evpnDmacFlow.getElanTag()))),
72                 mkMatches, mkInstructionsMap);
73
74         return flow;
75     }
76
77     public List<ListenableFuture<?>> evpnDeleteDmacFlowsToExternalMac(EvpnDmacFlow evpnDmacFlow) {
78         List<ListenableFuture<?>> futures = new ArrayList<>();
79         try (Acquired lock = ElanUtils.lockElanMacDPN(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDstMacAddress(),
80                 evpnDmacFlow.getDpId())) {
81             futures.addAll(
82                     evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(evpnDmacFlow.getElanTag(), evpnDmacFlow.dpId,
83                             evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
84             futures.addAll(evpnDeleteEtreeDmacFlowsToExternalMac(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDpId(),
85                     evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
86         }
87         return futures;
88     }
89
90     private List<ListenableFuture<?>> evpnDeleteEtreeDmacFlowsToExternalMac(long elanTag, Uint64 dpId,
91             String nexthopIp, String macToRemove) {
92         List<ListenableFuture<?>> futures = new ArrayList<>();
93         EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag);
94         if (etreeLeafTag != null) {
95             futures.addAll(
96                     evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(
97                             etreeLeafTag.getEtreeLeafTag().getValue().toJava(), dpId,
98                             nexthopIp, macToRemove));
99             futures.addAll(
100                     evpnRemoveTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue().toJava(),
101                             dpId, nexthopIp, macToRemove));
102         }
103         return futures;
104     }
105
106     static String evpnGetKnownDynamicmacFlowRef(short elanDmacTable, Uint64 dpId, String nexthopIp,
107                                                 String dstMacAddress, long elanTag, boolean shFlag) {
108         return String.valueOf(elanDmacTable) + elanTag + dpId + nexthopIp + dstMacAddress + shFlag;
109     }
110
111     private List<ListenableFuture<?>> evpnRemoveTheDropFlow(long elanTag, Uint64 dpId, String nexthopIp,
112             String macToRemove) {
113         String flowId = ElanEvpnFlowUtils.evpnGetKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, nexthopIp,
114                 macToRemove, elanTag, true);
115         Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
116         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
117             tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
118     }
119
120     private List<ListenableFuture<?>> evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(long elanTag,
121             Uint64 dpId, String nexthopIp, String macToRemove) {
122         String flowId = ElanEvpnFlowUtils.evpnGetKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, nexthopIp,
123                 macToRemove, elanTag, false);
124         Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(NwConstants.ELAN_DMAC_TABLE).build();
125         return Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
126             tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
127     }
128
129     public static class EvpnDmacFlowBuilder {
130         private Uint64 dpId;
131         private String nexthopIP;
132         private long elanTag;
133         private Long vni;
134         private String dstMacAddress;
135         private String elanName;
136
137         public EvpnDmacFlowBuilder() {
138         }
139
140         public EvpnDmacFlowBuilder setDpId(Uint64 dpId) {
141             this.dpId = dpId;
142             return this;
143         }
144
145         public EvpnDmacFlowBuilder setNexthopIP(String nexthopIP) {
146             this.nexthopIP = nexthopIP;
147             return this;
148         }
149
150         public EvpnDmacFlowBuilder setElanTag(long elanTag) {
151             this.elanTag = elanTag;
152             return this;
153         }
154
155         public EvpnDmacFlowBuilder setVni(Long vni) {
156             this.vni = vni;
157             return this;
158         }
159
160         public EvpnDmacFlowBuilder setDstMacAddress(String dstMacAddress) {
161             this.dstMacAddress = dstMacAddress;
162             return this;
163         }
164
165         public EvpnDmacFlowBuilder setElanName(String elanName) {
166             this.elanName = elanName;
167             return this;
168         }
169
170         public EvpnDmacFlow build() {
171             return new EvpnDmacFlow(dpId, nexthopIP, elanTag, vni, dstMacAddress, elanName);
172         }
173     }
174
175     static class EvpnDmacFlow {
176         private final Uint64 dpId;
177         private final String nexthopIP;
178         private final long elanTag;
179         private final Long vni;
180         private final String dstMacAddress;
181         private final String elanName;
182
183         EvpnDmacFlow(Uint64 dpId, String nexthopIP, long elanTag, Long vni, String dstMacAddress,
184                             String elanName) {
185             this.dpId = dpId;
186             this.nexthopIP = nexthopIP;
187             this.elanTag = elanTag;
188             this.vni = vni;
189             this.dstMacAddress = dstMacAddress;
190             this.elanName = elanName;
191         }
192
193         public Uint64 getDpId() {
194             return dpId;
195         }
196
197         public String getNexthopIP() {
198             return nexthopIP;
199         }
200
201         public long getElanTag() {
202             return elanTag;
203         }
204
205         public Long getVni() {
206             return vni;
207         }
208
209         public String getDstMacAddress() {
210             return dstMacAddress;
211         }
212
213         public String getElanName() {
214             return elanName;
215         }
216     }
217 }