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