bb9e3365a6e609a6b5ee6db3a01c2286b31eb060
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / test / java / org / opendaylight / netvirt / elanmanager / tests / ElanServiceTest.java
1 /*
2  * Copyright (C) 2016, 2017 Red Hat Inc., 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 package org.opendaylight.netvirt.elanmanager.tests;
9
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
11
12 import com.google.common.base.Optional;
13
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;
52
53
54
55
56 /**
57  * End-to-end test of IElanService.
58  *
59  * @author Michael Vorburger
60  * @author Riyazahmed Talikoti
61  */
62 @Ignore("This relies on flawed interface handling, see GENIUS-109")
63 public class ElanServiceTest extends  ElanServiceTestBase {
64
65     private static final Logger LOG = LoggerFactory.getLogger(ElanServiceTest.class);
66
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);
72
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;
88
89     @Before public void before() throws TransactionCommitFailedException {
90         setupItm();
91     }
92
93     @Test public void elanServiceTestModule() {
94         // Intentionally empty; the goal is just to first test the ElanServiceTestModule
95     }
96
97     @Test public void checkSMAC() throws Exception {
98         // Create Elan instance
99         createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
100         awaitForElanTag(ExpectedObjects.ELAN1);
101
102         // Add Elan interface
103         InterfaceInfo interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft();
104         addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN1IP1);
105
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);
110
111         // Read and Compare SMAC flow
112         String flowId =  new StringBuffer()
113                 .append(NwConstants.ELAN_SMAC_TABLE)
114                 .append(actualElanInstances.getElanTag())
115                 .append(DPN1_ID)
116                 .append(interfaceInfo.getInterfaceTag())
117                 .append(interfaceInfo.getMacAddress())
118                 .toString();
119         InstanceIdentifier<Flow> flowInstanceIidSrc = getFlowIid(NwConstants.ELAN_SMAC_TABLE,
120                 new FlowId(flowId), DPN1_ID);
121         awaitForData(LogicalDatastoreType.CONFIGURATION, flowInstanceIidSrc);
122
123         Flow flowSrc = singleTxdataBroker.syncRead(CONFIGURATION, flowInstanceIidSrc);
124         flowSrc = getFlowWithoutCookie(flowSrc);
125
126         Flow expected = ExpectedObjects.checkSmac(flowId, interfaceInfo, actualElanInstances);
127         AssertDataObjects.assertEqualBeans(expected, flowSrc);
128     }
129
130     @Test public void checkDmacSameDPN() throws Exception {
131         // Create Elan instance
132         createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
133         awaitForElanTag(ExpectedObjects.ELAN1);
134
135         // Add Elan interface in DPN1
136         InterfaceInfo interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft();
137         addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN1IP1);
138
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);
143
144         // Read DMAC Flow in DPN1
145         String flowId =  new StringBuffer()
146                 .append(NwConstants.ELAN_DMAC_TABLE)
147                 .append(actualElanInstances.getElanTag())
148                 .append(DPN1_ID)
149                 .append(interfaceInfo.getInterfaceTag())
150                 .append(interfaceInfo.getMacAddress())
151                 .toString();
152         InstanceIdentifier<Flow> flowInstanceIidDst = getFlowIid(NwConstants.ELAN_DMAC_TABLE,
153                 new FlowId(flowId), DPN1_ID);
154         awaitForData(LogicalDatastoreType.CONFIGURATION, flowInstanceIidDst);
155
156         Flow flowDst = singleTxdataBroker.syncRead(CONFIGURATION, flowInstanceIidDst);
157         flowDst = getFlowWithoutCookie(flowDst);
158
159         Flow expected = ExpectedObjects.checkDmacOfSameDpn(flowId, interfaceInfo, actualElanInstances);
160         AssertDataObjects.assertEqualBeans(expected, flowDst);
161     }
162
163     @Test public void checkDmacOfOtherDPN() throws Exception {
164         // Create Elan instance
165         createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
166         awaitForElanTag(ExpectedObjects.ELAN1);
167
168         InterfaceInfo interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft();
169         addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN1IP1);
170
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);
175
176         interfaceInfo = ELAN_INTERFACES.get(ELAN1 + ":" + DPN2MAC1).getLeft();
177         addElanInterface(ExpectedObjects.ELAN1, interfaceInfo, DPN2IP1);
178
179         // Read and Compare DMAC flow in DPN1 for MAC1 of DPN2
180         String flowId = ElanUtils.getKnownDynamicmacFlowRef((short)51,
181                         DPN1_ID,
182                         DPN2_ID,
183                         interfaceInfo.getMacAddress().toString(),
184                         actualElanInstances.getElanTag());
185
186         InstanceIdentifier<Flow> flowInstanceIidDst = getFlowIid(NwConstants.ELAN_DMAC_TABLE,
187                 new FlowId(flowId), DPN1_ID);
188         awaitForData(LogicalDatastoreType.CONFIGURATION, flowInstanceIidDst);
189
190         Flow flowDst = singleTxdataBroker.syncRead(CONFIGURATION, flowInstanceIidDst);
191         flowDst = getFlowWithoutCookie(flowDst);
192
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));
197     }
198
199     @Test public void checkEvpnAdvRT2() throws Exception {
200         createElanInstanceAndInterfaceAndAttachEvpn();
201
202         AssertDataObjects.assertEqualBeans(
203                 ExpectedObjects.checkEvpnAdvertiseRoute(ELAN1_SEGMENT_ID, DPN1MAC1, DPN1_TEPIP, DPN1IP1, RD),
204                 readBgpNetworkFromDS(DPN1IP1));
205     }
206
207     @Test public void checkEvpnAdvRT2NewInterface() throws Exception {
208         createElanInstanceAndInterfaceAndAttachEvpn();
209
210         // Add Elan interface
211         addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
212
213         AssertDataObjects.assertEqualBeans(
214                 ExpectedObjects.checkEvpnAdvertiseRoute(ELAN1_SEGMENT_ID, DPN1MAC2, DPN1_TEPIP, DPN1IP2, RD),
215                 readBgpNetworkFromDS(DPN1IP2));
216     }
217
218     @Test public void checkEvpnWithdrawRT2DelIntf() throws Exception {
219         createElanInstanceAndInterfaceAndAttachEvpn();
220
221         InstanceIdentifier<Networks> iid = evpnTestHelper.buildBgpNetworkIid(DPN1IP1);
222         awaitForData(LogicalDatastoreType.CONFIGURATION, iid);
223
224         evpnTestHelper.deleteRdtoNetworks();
225
226         deleteElanInterface(ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft());
227         awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, iid);
228     }
229
230     @Test public void checkEvpnWithdrawRouteDetachEvpn() throws Exception {
231         createElanInstanceAndInterfaceAndAttachEvpn();
232         addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
233
234         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
235         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
236
237         evpnTestHelper.detachEvpnToNetwork(ExpectedObjects.ELAN1);
238
239         awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
240         awaitForDataDelete(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
241     }
242
243     @Test public void checkEvpnInstalDmacFlow() throws Exception {
244         createElanInstanceAndInterfaceAndAttachEvpn();
245         addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
246
247         // Verify advertise RT2 route success for both MAC's
248         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
249         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
250
251         // RT2 received from Peer
252         evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC1, EVPNRECVIP1);
253         evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC2, EVPNRECVIP2);
254
255         // verify successful installation of DMAC flow for recvd rt2
256         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC1));
257         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC2));
258     }
259
260     @Test public void checkEvpnUnInstalDmacFlow() throws Exception {
261         createElanInstanceAndInterfaceAndAttachEvpn();
262         addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC2).getLeft(), DPN1IP2);
263
264         // Verify advertise RT2 route success for both MAC's
265         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP1));
266         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildBgpNetworkIid(DPN1IP2));
267
268         // RT2 received from Peer
269         evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC1, EVPNRECVIP1);
270         evpnTestHelper.handleEvpnRt2Recvd(EVPNRECVMAC2, EVPNRECVIP2);
271
272         // verify successful installation of DMAC flow for recvd rt2
273         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC1));
274         awaitForData(LogicalDatastoreType.CONFIGURATION, evpnTestHelper.buildMacVrfEntryIid(EVPNRECVMAC2));
275
276         // withdraw RT2 received from Peer
277         evpnTestHelper.deleteMacVrfEntryToDS(RD, EVPNRECVMAC1);
278         evpnTestHelper.deleteMacVrfEntryToDS(RD, EVPNRECVMAC2);
279
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));
283     }
284
285     public void createElanInstanceAndInterfaceAndAttachEvpn() throws ReadFailedException,
286             TransactionCommitFailedException {
287         // Create Elan instance
288         createElanInstance(ExpectedObjects.ELAN1, ExpectedObjects.ELAN1_SEGMENT_ID);
289         awaitForElanTag(ExpectedObjects.ELAN1);
290
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);
295
296         // Add Elan interface
297         addElanInterface(ExpectedObjects.ELAN1, ELAN_INTERFACES.get(ELAN1 + ":" + DPN1MAC1).getLeft(), DPN1IP1);
298
299         // Attach EVPN to networks
300         evpnTestHelper.attachEvpnToNetwork(elanInstance);
301     }
302
303     public Networks readBgpNetworkFromDS(String prefix) throws ReadFailedException {
304         InstanceIdentifier<Networks> iid = InstanceIdentifier.builder(Bgp.class)
305                 .child(Networks.class, new NetworksKey(prefix, RD))
306                 .build();
307         awaitForData(LogicalDatastoreType.CONFIGURATION, iid);
308
309         return singleTxdataBroker.syncRead(CONFIGURATION, iid);
310     }
311
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;
318         });
319     }
320 }