29895ce30c7d267c50ff0ab7b8d31c24bf5e2eef
[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.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20 import org.opendaylight.genius.infra.Datastore;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
22 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.MatchInfo;
25 import org.opendaylight.genius.mdsalutil.NwConstants;
26 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
27 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
28 import org.opendaylight.mdsal.binding.api.DataBroker;
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;
41
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<Void>> evpnDeleteDmacFlowsToExternalMac(EvpnDmacFlow evpnDmacFlow) {
78         List<ListenableFuture<Void>> 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<Void>> evpnDeleteEtreeDmacFlowsToExternalMac(long elanTag, Uint64 dpId,
91             String nexthopIp, String macToRemove) {
92         List<ListenableFuture<Void>> 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<Void>> 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(Datastore.CONFIGURATION,
117             tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
118     }
119
120     private List<ListenableFuture<Void>> 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(Datastore.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 }