2 * Copyright © 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.elan.evpn.utils;
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;
41 public class ElanEvpnFlowUtils {
42 private final IMdsalApiManager mdsalManager;
43 private final ElanItmUtils elanItmUtils;
44 private final ElanEtreeUtils elanEtreeUtils;
45 private final ManagedNewTransactionRunner txRunner;
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);
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);
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())) {
79 evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(evpnDmacFlow.getElanTag(), evpnDmacFlow.dpId,
80 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
81 futures.addAll(evpnDeleteEtreeDmacFlowsToExternalMac(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDpId(),
82 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
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) {
93 evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(
94 etreeLeafTag.getEtreeLeafTag().getValue().toJava(), dpId,
95 nexthopIp, macToRemove));
97 evpnRemoveTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue().toJava(),
98 dpId, nexthopIp, macToRemove));
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;
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)));
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)));
126 public static class EvpnDmacFlowBuilder {
128 private String nexthopIP;
129 private long elanTag;
131 private String dstMacAddress;
132 private String elanName;
134 public EvpnDmacFlowBuilder() {
137 public EvpnDmacFlowBuilder setDpId(Uint64 dpId) {
142 public EvpnDmacFlowBuilder setNexthopIP(String nexthopIP) {
143 this.nexthopIP = nexthopIP;
147 public EvpnDmacFlowBuilder setElanTag(long elanTag) {
148 this.elanTag = elanTag;
152 public EvpnDmacFlowBuilder setVni(Long vni) {
157 public EvpnDmacFlowBuilder setDstMacAddress(String dstMacAddress) {
158 this.dstMacAddress = dstMacAddress;
162 public EvpnDmacFlowBuilder setElanName(String elanName) {
163 this.elanName = elanName;
167 public EvpnDmacFlow build() {
168 return new EvpnDmacFlow(dpId, nexthopIP, elanTag, vni, dstMacAddress, elanName);
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;
180 EvpnDmacFlow(Uint64 dpId, String nexthopIP, long elanTag, Long vni, String dstMacAddress,
183 this.nexthopIP = nexthopIP;
184 this.elanTag = elanTag;
186 this.dstMacAddress = dstMacAddress;
187 this.elanName = elanName;
190 public Uint64 getDpId() {
194 public String getNexthopIP() {
198 public long getElanTag() {
202 public Long getVni() {
206 public String getDstMacAddress() {
207 return dstMacAddress;
210 public String getElanName() {