2 * Copyright (C) 2016, 2017 Red Hat Inc., 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
8 package org.opendaylight.netvirt.elanmanager.tests;
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
12 import com.google.common.base.Optional;
14 import javax.inject.Inject;
15 import org.junit.Before;
16 import org.junit.Ignore;
17 import org.junit.Rule;
18 import org.junit.Test;
19 import org.junit.rules.MethodRule;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
22 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
23 import org.opendaylight.genius.datastoreutils.testutils.JobCoordinatorTestModule;
24 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
25 import org.opendaylight.genius.mdsalutil.MDSALUtil;
26 import org.opendaylight.genius.mdsalutil.NwConstants;
27 import org.opendaylight.genius.testutils.interfacemanager.TunnelInterfaceDetails;
28 import org.opendaylight.infrautils.inject.guice.testutils.GuiceRule;
29 import org.opendaylight.infrautils.testutils.LogRule;
30 import org.opendaylight.mdsal.binding.testutils.AssertDataObjects;
31 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
32 import org.opendaylight.netvirt.elan.evpn.listeners.ElanMacEntryListener;
33 import org.opendaylight.netvirt.elan.evpn.listeners.EvpnElanInstanceListener;
34 import org.opendaylight.netvirt.elan.evpn.listeners.MacVrfEntryListener;
35 import org.opendaylight.netvirt.elan.evpn.utils.EvpnUtils;
36 import org.opendaylight.netvirt.elan.utils.ElanUtils;
37 import org.opendaylight.netvirt.elanmanager.api.IElanService;
38 import org.opendaylight.netvirt.elanmanager.tests.utils.EvpnTestHelper;
39 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
40 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
41 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Networks;
42 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.NetworksKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
57 * End-to-end test of IElanService.
59 * @author Michael Vorburger
60 * @author Riyazahmed Talikoti
62 @Ignore("This relies on flawed interface handling, see GENIUS-109")
63 public class ElanServiceTest extends ElanServiceTestBase {
65 private static final Logger LOG = LoggerFactory.getLogger(ElanServiceTest.class);
67 // TODO as-is, this test is flaky; as uncommenting will show
68 // Uncomment this to keep running this test indefinitely
69 // This is very useful to detect concurrency issues (such as https://bugs.opendaylight.org/show_bug.cgi?id=7538)
70 // public static @ClassRule RunUntilFailureClassRule classRepeater = new RunUntilFailureClassRule();
71 // public @Rule RunUntilFailureRule repeater = new RunUntilFailureRule(classRepeater);
73 public @Rule LogRule logRule = new LogRule();
74 public @Rule MethodRule guice = new GuiceRule(ElanServiceTestModule.class, JobCoordinatorTestModule.class);
75 // TODO re-enable after we can await completion of listeners and DJC:
76 // Otherwise this too frequently causes spurious test failures, e.g. due to error
77 // logs Caused by: java.lang.RuntimeException: java.util.concurrent.ExecutionException: Operation was interrupted
78 // public @Rule LogCaptureRule logCaptureRule = new LogCaptureRule();
79 private @Inject IElanService elanService;
80 private @Inject IdManagerService idManager;
81 private @Inject EvpnElanInstanceListener evpnElanInstanceListener;
82 private @Inject ElanMacEntryListener elanMacEntryListener;
83 private @Inject MacVrfEntryListener macVrfEntryListener;
84 private @Inject EvpnUtils evpnUtils;
85 private @Inject IBgpManager bgpManager;
86 private @Inject IVpnManager vpnManager;
87 private @Inject EvpnTestHelper evpnTestHelper;
89 @Before public void before() throws TransactionCommitFailedException {
93 @Test public void elanServiceTestModule() {
94 // Intentionally empty; the goal is just to first test the ElanServiceTestModule
97 @Test public void checkSMAC() throws Exception {
98 // Create Elan instance
99 createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
100 awaitForElanTag(ExpectedObjects.ELAN1);
102 // Add Elan interface
103 InterfaceInfo interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft();
104 addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN1IP1);
106 // Read Elan instance
107 InstanceIdentifier<ElanInstance> elanInstanceIid = InstanceIdentifier.builder(ElanInstances.class)
108 .child(ElanInstance.class, new ElanInstanceKey(ExpectedObjects.ELAN1)).build();
109 ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, elanInstanceIid);
111 // Read and Compare SMAC flow
112 String flowId = new StringBuffer()
113 .append(NwConstants.ELAN_SMAC_TABLE)
114 .append(actualElanInstances.getElanTag())
116 .append(interfaceInfo.getInterfaceTag())
117 .append(interfaceInfo.getMacAddress())
119 InstanceIdentifier<Flow> flowInstanceIidSrc = getFlowIid(NwConstants.ELAN_SMAC_TABLE,
120 new FlowId(flowId), DPN1_ID);
121 awaitForData(LogicalDatastoreType.CONFIGURATION, flowInstanceIidSrc);
123 Flow flowSrc = singleTxdataBroker.syncRead(CONFIGURATION, flowInstanceIidSrc);
124 flowSrc = getFlowWithoutCookie(flowSrc);
126 Flow expected = ExpectedObjects.checkSmac(flowId, interfaceInfo, actualElanInstances);
127 AssertDataObjects.assertEqualBeans(expected, flowSrc);
130 @Test public void checkDmacSameDPN() throws Exception {
131 // Create Elan instance
132 createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
133 awaitForElanTag(ExpectedObjects.ELAN1);
135 // Add Elan interface in DPN1
136 InterfaceInfo interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft();
137 addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN1IP1);
139 // Read Elan instance
140 InstanceIdentifier<ElanInstance> elanInstanceIid = InstanceIdentifier.builder(ElanInstances.class)
141 .child(ElanInstance.class, new ElanInstanceKey(ExpectedObjects.ELAN1)).build();
142 ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, elanInstanceIid);
144 // Read DMAC Flow in DPN1
145 String flowId = new StringBuffer()
146 .append(NwConstants.ELAN_DMAC_TABLE)
147 .append(actualElanInstances.getElanTag())
149 .append(interfaceInfo.getInterfaceTag())
150 .append(interfaceInfo.getMacAddress())
152 InstanceIdentifier<Flow> flowInstanceIidDst = getFlowIid(NwConstants.ELAN_DMAC_TABLE,
153 new FlowId(flowId), DPN1_ID);
154 awaitForData(LogicalDatastoreType.CONFIGURATION, flowInstanceIidDst);
156 Flow flowDst = singleTxdataBroker.syncRead(CONFIGURATION, flowInstanceIidDst);
157 flowDst = getFlowWithoutCookie(flowDst);
159 Flow expected = ExpectedObjects.checkDmacOfSameDpn(flowId, interfaceInfo, actualElanInstances);
160 AssertDataObjects.assertEqualBeans(expected, flowDst);
163 @Test public void checkDmacOfOtherDPN() throws Exception {
164 // Create Elan instance
165 createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
166 awaitForElanTag(ExpectedObjects.ELAN1);
168 InterfaceInfo interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft();
169 addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN1IP1);
171 // Read Elan instance
172 InstanceIdentifier<ElanInstance> elanInstanceIid = InstanceIdentifier.builder(ElanInstances.class)
173 .child(ElanInstance.class, new ElanInstanceKey(ExpectedObjects.ELAN1)).build();
174 ElanInstance actualElanInstances = singleTxdataBroker.syncRead(CONFIGURATION, elanInstanceIid);
176 interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN2MAC1).getLeft();
177 addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN2IP1);
179 // Read and Compare DMAC flow in DPN1 for MAC1 of DPN2
180 String flowId = ElanUtils.getKnownDynamicmacFlowRef((short)51,
183 interfaceInfo.getMacAddress().toString(),
184 actualElanInstances.getElanTag());
186 InstanceIdentifier<Flow> flowInstanceIidDst = getFlowIid(NwConstants.ELAN_DMAC_TABLE,
187 new FlowId(flowId), DPN1_ID);
188 awaitForData(LogicalDatastoreType.CONFIGURATION, flowInstanceIidDst);
190 Flow flowDst = singleTxdataBroker.syncRead(CONFIGURATION, flowInstanceIidDst);
191 flowDst = getFlowWithoutCookie(flowDst);
193 TunnelInterfaceDetails tepDetails = EXTN_INTFS.get(DPN1_ID_STR + ":" + DPN2_ID_STR);
194 Flow expected = ExpectedObjects.checkDmacOfOtherDPN(flowId, interfaceInfo, tepDetails,
195 actualElanInstances);
196 AssertDataObjects.assertEqualBeans(getSortedActions(expected), getSortedActions(flowDst));
199 @Test public void checkEvpnAdvRT2() throws Exception {
200 createElanInstanceAndInterfaceAndAttachEvpn();
202 AssertDataObjects.assertEqualBeans(
203 ExpectedObjects.checkEvpnAdvertiseRoute(ELAN1_SEGMENT_ID, DPN1MAC1, DPN1_TEPIP, DPN1IP1, RD),
204 readBgpNetworkFromDS(DPN1IP1));
207 @Test public void checkEvpnAdvRT2NewInterface() throws Exception {
208 createElanInstanceAndInterfaceAndAttachEvpn();
210 // Add Elan interface
211 addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
213 AssertDataObjects.assertEqualBeans(
214 ExpectedObjects.checkEvpnAdvertiseRoute(ELAN1_SEGMENT_ID, DPN1MAC2, DPN1_TEPIP, DPN1IP2, RD),
215 readBgpNetworkFromDS(DPN1IP2));
218 @Test public void checkEvpnWithdrawRT2DelIntf() throws Exception {
219 createElanInstanceAndInterfaceAndAttachEvpn();
221 InstanceIdentifier<Networks> iid = evpnTestHelper.buildBgpNetworkIid(DPN1IP1);
222 awaitForData(LogicalDatastoreType.CONFIGURATION, iid);
224 evpnTestHelper.deleteRdtoNetworks();
226 deleteElanInterface(ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft());
227 awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, iid);
230 @Test public void checkEvpnWithdrawRouteDetachEvpn() throws Exception {
231 createElanInstanceAndInterfaceAndAttachEvpn();
232 addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
234 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
235 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
237 evpnTestHelper.detachEvpnToNetwork(ExpectedObjects.ELAN1);
239 awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
240 awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
243 @Test public void checkEvpnInstalDmacFlow() throws Exception {
244 createElanInstanceAndInterfaceAndAttachEvpn();
245 addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
247 // Verify advertise RT2 route success for both MAC's
248 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
249 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
251 // RT2 received from Peer
252 evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC1, EVPNRECVIP1);
253 evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC2, EVPNRECVIP2);
255 // verify successful installation of DMAC flow for recvd rt2
256 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC1));
257 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC2));
260 @Test public void checkEvpnUnInstalDmacFlow() throws Exception {
261 createElanInstanceAndInterfaceAndAttachEvpn();
262 addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
264 // Verify advertise RT2 route success for both MAC's
265 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
266 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
268 // RT2 received from Peer
269 evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC1, EVPNRECVIP1);
270 evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC2, EVPNRECVIP2);
272 // verify successful installation of DMAC flow for recvd rt2
273 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC1));
274 awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC2));
276 // withdraw RT2 received from Peer
277 evpnTestHelper.deleteMacVrfEntryToDS(RD, EVPNRECVMAC1);
278 evpnTestHelper.deleteMacVrfEntryToDS(RD, EVPNRECVMAC2);
280 // verify successful un-installation of DMAC flow for recvd rt2
281 awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC1));
282 awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC2));
285 public void createElanInstanceAndInterfaceAndAttachEvpn() throws ReadFailedException,
286 TransactionCommitFailedException {
287 // Create Elan instance
288 createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
289 awaitForElanTag(ExpectedObjects.ELAN1);
291 // Read Elan Instance
292 InstanceIdentifier<ElanInstance> elanInstanceIid = InstanceIdentifier.builder(ElanInstances.class)
293 .child(ElanInstance.class, new ElanInstanceKey(ExpectedObjects.ELAN1)).build();
294 ElanInstance elanInstance = singleTxdataBroker.syncRead(CONFIGURATION, elanInstanceIid);
296 // Add Elan interface
297 addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft(), DPN1IP1);
299 // Attach EVPN to networks
300 evpnTestHelper.attachEvpnToNetwork(elanInstance);
303 public Networks readBgpNetworkFromDS(String prefix) throws ReadFailedException {
304 InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
305 .child(Networks.class, new NetworksKey(prefix, RD))
307 awaitForData(LogicalDatastoreType.CONFIGURATION, iid);
309 return singleTxdataBroker.syncRead(CONFIGURATION, iid);
312 private void awaitForElanTag(String elanName) {
313 InstanceIdentifier<ElanInstance> elanInstanceIid = InstanceIdentifier.builder(ElanInstances.class)
314 .child(ElanInstance.class, new ElanInstanceKey(elanName)).build();
315 getAwaiter().until(() -> {
316 Optional<ElanInstance> elanInstance = MDSALUtil.read(dataBroker, CONFIGURATION, elanInstanceIid);
317 return elanInstance.isPresent() && elanInstance.get().getElanTag() != null;