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