fbd56638a606ef60b0294b64dd110823f04f9f61
[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.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;
41
42 @Singleton
43 public class ElanEvpnFlowUtils {
44     private final IMdsalApiManager mdsalManager;
45     private final ElanItmUtils elanItmUtils;
46     private final ElanEtreeUtils elanEtreeUtils;
47     private final ManagedNewTransactionRunner txRunner;
48
49     @Inject
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);
56     }
57
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);
72
73         return flow;
74     }
75
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())) {
80             futures.addAll(
81                     evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(evpnDmacFlow.getElanTag(), evpnDmacFlow.dpId,
82                             evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
83             futures.addAll(evpnDeleteEtreeDmacFlowsToExternalMac(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDpId(),
84                     evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
85         }
86         return futures;
87     }
88
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) {
94             futures.addAll(
95                     evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(
96                             etreeLeafTag.getEtreeLeafTag().getValue().toJava(), dpId,
97                             nexthopIp, macToRemove));
98             futures.addAll(
99                     evpnRemoveTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue().toJava(),
100                             dpId, nexthopIp, macToRemove));
101         }
102         return futures;
103     }
104
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;
108     }
109
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)));
117     }
118
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)));
126     }
127
128     public static class EvpnDmacFlowBuilder {
129         private Uint64 dpId;
130         private String nexthopIP;
131         private long elanTag;
132         private Long vni;
133         private String dstMacAddress;
134         private String elanName;
135
136         public EvpnDmacFlowBuilder() {
137         }
138
139         public EvpnDmacFlowBuilder setDpId(Uint64 dpId) {
140             this.dpId = dpId;
141             return this;
142         }
143
144         public EvpnDmacFlowBuilder setNexthopIP(String nexthopIP) {
145             this.nexthopIP = nexthopIP;
146             return this;
147         }
148
149         public EvpnDmacFlowBuilder setElanTag(long elanTag) {
150             this.elanTag = elanTag;
151             return this;
152         }
153
154         public EvpnDmacFlowBuilder setVni(Long vni) {
155             this.vni = vni;
156             return this;
157         }
158
159         public EvpnDmacFlowBuilder setDstMacAddress(String dstMacAddress) {
160             this.dstMacAddress = dstMacAddress;
161             return this;
162         }
163
164         public EvpnDmacFlowBuilder setElanName(String elanName) {
165             this.elanName = elanName;
166             return this;
167         }
168
169         public EvpnDmacFlow build() {
170             return new EvpnDmacFlow(dpId, nexthopIP, elanTag, vni, dstMacAddress, elanName);
171         }
172     }
173
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;
181
182         EvpnDmacFlow(Uint64 dpId, String nexthopIP, long elanTag, Long vni, String dstMacAddress,
183                             String elanName) {
184             this.dpId = dpId;
185             this.nexthopIP = nexthopIP;
186             this.elanTag = elanTag;
187             this.vni = vni;
188             this.dstMacAddress = dstMacAddress;
189             this.elanName = elanName;
190         }
191
192         public Uint64 getDpId() {
193             return dpId;
194         }
195
196         public String getNexthopIP() {
197             return nexthopIP;
198         }
199
200         public long getElanTag() {
201             return elanTag;
202         }
203
204         public Long getVni() {
205             return vni;
206         }
207
208         public String getDstMacAddress() {
209             return dstMacAddress;
210         }
211
212         public String getElanName() {
213             return elanName;
214         }
215     }
216 }