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 static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
20 import javax.inject.Inject;
21 import javax.inject.Singleton;
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.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
27 import org.opendaylight.mdsal.binding.api.DataBroker;
28 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
29 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
30 import org.opendaylight.netvirt.elan.utils.ElanConstants;
31 import org.opendaylight.netvirt.elan.utils.ElanEtreeUtils;
32 import org.opendaylight.netvirt.elan.utils.ElanItmUtils;
33 import org.opendaylight.netvirt.elan.utils.ElanUtils;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeLeafTagName;
41 import org.opendaylight.yangtools.yang.common.Uint64;
44 public class ElanEvpnFlowUtils {
45 private final IMdsalApiManager mdsalManager;
46 private final ElanItmUtils elanItmUtils;
47 private final ElanEtreeUtils elanEtreeUtils;
48 private final ManagedNewTransactionRunner txRunner;
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);
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);
77 public List<ListenableFuture<?>> evpnDeleteDmacFlowsToExternalMac(EvpnDmacFlow evpnDmacFlow) {
78 List<ListenableFuture<?>> futures = new ArrayList<>();
79 try (Acquired lock = ElanUtils.lockElanMacDPN(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDstMacAddress(),
80 evpnDmacFlow.getDpId())) {
82 evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(evpnDmacFlow.getElanTag(), evpnDmacFlow.dpId,
83 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
84 futures.addAll(evpnDeleteEtreeDmacFlowsToExternalMac(evpnDmacFlow.getElanTag(), evpnDmacFlow.getDpId(),
85 evpnDmacFlow.getNexthopIP(), evpnDmacFlow.getDstMacAddress()));
90 private List<ListenableFuture<?>> evpnDeleteEtreeDmacFlowsToExternalMac(long elanTag, Uint64 dpId,
91 String nexthopIp, String macToRemove) {
92 List<ListenableFuture<?>> futures = new ArrayList<>();
93 EtreeLeafTagName etreeLeafTag = elanEtreeUtils.getEtreeLeafTagByElanTag(elanTag);
94 if (etreeLeafTag != null) {
96 evpnRemoveFlowThatSendsThePacketOnAnExternalTunnel(
97 etreeLeafTag.getEtreeLeafTag().getValue().toJava(), dpId,
98 nexthopIp, macToRemove));
100 evpnRemoveTheDropFlow(etreeLeafTag.getEtreeLeafTag().getValue().toJava(),
101 dpId, nexthopIp, macToRemove));
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;
111 private List<ListenableFuture<?>> 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(CONFIGURATION,
117 tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
120 private List<ListenableFuture<?>> 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(CONFIGURATION,
126 tx -> mdsalManager.removeFlow(tx, dpId, flowToRemove)));
129 public static class EvpnDmacFlowBuilder {
131 private String nexthopIP;
132 private long elanTag;
134 private String dstMacAddress;
135 private String elanName;
137 public EvpnDmacFlowBuilder() {
140 public EvpnDmacFlowBuilder setDpId(Uint64 dpId) {
145 public EvpnDmacFlowBuilder setNexthopIP(String nexthopIP) {
146 this.nexthopIP = nexthopIP;
150 public EvpnDmacFlowBuilder setElanTag(long elanTag) {
151 this.elanTag = elanTag;
155 public EvpnDmacFlowBuilder setVni(Long vni) {
160 public EvpnDmacFlowBuilder setDstMacAddress(String dstMacAddress) {
161 this.dstMacAddress = dstMacAddress;
165 public EvpnDmacFlowBuilder setElanName(String elanName) {
166 this.elanName = elanName;
170 public EvpnDmacFlow build() {
171 return new EvpnDmacFlow(dpId, nexthopIP, elanTag, vni, dstMacAddress, elanName);
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;
183 EvpnDmacFlow(Uint64 dpId, String nexthopIP, long elanTag, Long vni, String dstMacAddress,
186 this.nexthopIP = nexthopIP;
187 this.elanTag = elanTag;
189 this.dstMacAddress = dstMacAddress;
190 this.elanName = elanName;
193 public Uint64 getDpId() {
197 public String getNexthopIP() {
201 public long getElanTag() {
205 public Long getVni() {
209 public String getDstMacAddress() {
210 return dstMacAddress;
213 public String getElanName() {