Optimize DHCP relay processing for VPP
[groupbasedpolicy.git] / renderers / vpp / src / test / java / org / opendaylight / groupbasedpolicy / renderer / vpp / policy / VppRendererPolicyManagerTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, 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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
10
11 import java.util.AbstractMap;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.List;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.locks.ReentrantLock;
18 import java.util.stream.Collectors;
19
20 import org.junit.Assert;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.Mockito;
25 import org.mockito.runners.MockitoJUnitRunner;
26 import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
29 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
30 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
31 import org.opendaylight.groupbasedpolicy.renderer.vpp.DtoFactory;
32 import org.opendaylight.groupbasedpolicy.renderer.vpp.dhcp.DhcpRelayHandler;
33 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.RendererPolicyConfEvent;
34 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent;
35 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
36 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationProvider;
37 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
38 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
39 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
40 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
41 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
42 import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
43 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
44 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
45 import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
46 import org.opendaylight.groupbasedpolicy.util.IidFactory;
47 import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L2FloodDomain;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L2BridgeDomain;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclInterfaceAugmentation;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.BridgeDomains;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VppInterfaceAugmentation;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.VxlanVni;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.interfaces._interface.L2;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.Interconnection;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170607.l2.config.attributes.interconnection.BridgeBased;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugment;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev170327.TunnelTypeVxlan;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev170327.network.topology.topology.tunnel.parameters.VxlanTunnelParameters;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
91 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
92
93 import com.google.common.base.Optional;
94 import com.google.common.base.Strings;
95 import com.google.common.collect.Lists;
96
97 @RunWith(MockitoJUnitRunner.class)
98 public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
99
100     private static final InstanceIdentifier<RendererPolicy> RENDERER_POLICY_IID =
101             IidFactory.rendererIid(VppRenderer.NAME).child(RendererPolicy.class);
102     private final static String SOCKET = "socket";
103     private static final String CLIENT_MAC = "10:00:00:00:00:01";
104     private static final String CLIENT_MAC_2 = "10:00:00:00:00:02";
105     private static final String WEB_MAC = "10:00:00:00:00:01";
106     private static final String WEB_MAC_2 = "10:00:00:00:00:02";
107     private static final String WEB_IP_2 = "20.0.0.2/32";
108     private static final String CLIENT_IP_2 = "10.0.0.2/32";
109     private static final String WEB_IP = "20.0.0.1/32";
110     private static final String CLIENT_IP = "10.0.0.1/32";
111     private static final String CLIENT_1_IFACE_NAME = "client1";
112     private static final String CLIENT_2_IFACE_NAME = "client2";
113     private static final String WEB_2_IFACE_NAME = "web2";
114     private static final String WEB_1_IFACE_NAME = "web1";
115
116     public static final TenantId TENANT = new TenantId("tenant");
117     public static final List<EndpointGroupId>
118         ENDPOINT_GROUP =
119         Collections.singletonList(new EndpointGroupId("default"));
120
121     private MountedDataBrokerProvider mountedDataProviderMock;
122     private DataBroker mountPointDataBroker;
123     private DataBroker dataBroker;
124
125     private BridgeDomainManagerImpl bdManager;
126     private InterfaceManager ifaceManager;
127     private AclManager aclManager;
128     private ForwardingManager fwManager;
129     private NatManager natManager;
130     private RoutingManager routingManager;
131     private LispStateManager lispStateManager;
132     private LoopbackManager loopbackManager;
133     private FlatOverlayManager flatOverlayManager;
134     private DhcpRelayHandler dhcpRelayHandler;
135     private VppRendererPolicyManager vppRendererPolicyManager;
136
137     @Override
138     public Collection<Class<?>> getClassesFromModules() {
139         return Arrays.asList(Node.class, VppEndpoint.class, Interfaces.class, BridgeDomains.class,
140                 LocationProviders.class, L2FloodDomain.class, VxlanVni.class, TopologyVbridgeAugment.class,
141                 TunnelTypeVxlan.class, PhysicalLocationRef.class, AccessLists.class,
142                 VppInterfaceAugmentation.class, VppAclInterfaceAugmentation.class, VxlanTunnelParameters.class);
143     }
144
145     @Before
146     public void init() throws Exception {
147         mountedDataProviderMock = Mockito.mock(MountedDataBrokerProvider.class);
148         mountPointDataBroker = getDataBroker();
149         setup(); // initialize new data broker for ODL data store
150         dataBroker = getDataBroker();
151         Mockito.when(mountedDataProviderMock.resolveDataBrokerForMountPoint(Mockito.any(InstanceIdentifier.class)))
152             .thenReturn(Optional.of(mountPointDataBroker));
153         lispStateManager = new LispStateManager(mountedDataProviderMock);
154         loopbackManager = new LoopbackManager(mountedDataProviderMock);
155         flatOverlayManager = new FlatOverlayManager(dataBroker, mountedDataProviderMock);
156         ifaceManager = new InterfaceManager(mountedDataProviderMock, dataBroker, flatOverlayManager);
157         aclManager = new AclManager(mountedDataProviderMock, ifaceManager);
158         natManager = new NatManager(dataBroker, mountedDataProviderMock);
159         routingManager = new RoutingManager(dataBroker, mountedDataProviderMock);
160         bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
161         dhcpRelayHandler = new DhcpRelayHandler(dataBroker);
162         fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager,
163                 lispStateManager, loopbackManager, flatOverlayManager, dhcpRelayHandler, dataBroker);
164         vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
165         fwManager.setTimer((byte) 1);
166         VbdNetconfTransaction.NODE_DATA_BROKER_MAP.put(DtoFactory.VPP_NODE_1_IID,
167                 new AbstractMap.SimpleEntry<DataBroker, ReentrantLock>(mountPointDataBroker, new ReentrantLock()));
168         VbdNetconfTransaction.NODE_DATA_BROKER_MAP.put(DtoFactory.VPP_NODE_2_IID,
169                 new AbstractMap.SimpleEntry<DataBroker, ReentrantLock>(mountPointDataBroker, new ReentrantLock()));
170     }
171
172     @Test
173     public void testRendererPolicyChanged_created_oneEpPerEpg() throws Exception {
174         AbsoluteLocation clientLocation =
175                 DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, null, CLIENT_1_IFACE_NAME);
176         AddressEndpointWithLocation clientEp =
177                 DtoFactory.createEndpoint(CLIENT_IP, CLIENT_MAC, DtoFactory.L2FD_CTX.getValue(), clientLocation);
178         AbsoluteLocation webLocation = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, null, WEB_1_IFACE_NAME);
179         AddressEndpointWithLocation webEp =
180                 DtoFactory.createEndpoint(WEB_IP, WEB_MAC, DtoFactory.L2FD_CTX.getValue(), webLocation);
181
182         storeVppEndpoint(clientEp.getKey(), CLIENT_MAC, CLIENT_1_IFACE_NAME, createVppEndpointIid(clientEp.getKey()));
183         storeVppEndpoint(webEp.getKey(), WEB_MAC, WEB_1_IFACE_NAME, createVppEndpointIid(webEp.getKey()));
184
185         Configuration configuration = DtoFactory.createConfiguration(Arrays.asList(clientEp), Arrays.asList(webEp));
186         RendererPolicy rendererPolicy =
187                 new RendererPolicyBuilder().setVersion(1L).setConfiguration(configuration).build();
188         RendererPolicyConfEvent event = new RendererPolicyConfEvent(RENDERER_POLICY_IID, null, rendererPolicy);
189
190         vppRendererPolicyManager.rendererPolicyChanged(event);
191
192         // assert state on data store behind mount point
193         Interface clientIface = readAndAssertInterface(CLIENT_1_IFACE_NAME);
194         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), clientIface);
195         Interface webIface = readAndAssertInterface(WEB_1_IFACE_NAME);
196         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), webIface);
197         // assert state on ODL data store
198         ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
199         Optional<LocationProvider> optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
200                 IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
201             .get();
202         Assert.assertTrue(optLocationProvider.isPresent());
203         List<ProviderAddressEndpointLocation> epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
204         Assert.assertNotNull(epLocs);
205         Assert.assertEquals(2, epLocs.size());
206         assertProviderAddressEndpointLocation(clientEp.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
207                 DtoFactory.L2FD_CTX.getValue(), CLIENT_1_IFACE_NAME), epLocs);
208         assertProviderAddressEndpointLocation(webEp.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
209                 DtoFactory.L2FD_CTX.getValue(), WEB_1_IFACE_NAME), epLocs);
210     }
211
212     @Test
213     public void testRendererPolicyChanged_update() throws Exception {
214         AbsoluteLocation client1LocationNodeNull =
215                 DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, null, CLIENT_1_IFACE_NAME);
216         AddressEndpointWithLocation client1Ep = DtoFactory.createEndpoint(CLIENT_IP, CLIENT_MAC,
217                 DtoFactory.L2FD_CTX.getValue(), client1LocationNodeNull);
218         AbsoluteLocation web1LocationNodeNull =
219                 DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID, null, WEB_1_IFACE_NAME);
220         AddressEndpointWithLocation web1Ep =
221                 DtoFactory.createEndpoint(WEB_IP, WEB_MAC, DtoFactory.L2FD_CTX.getValue(), web1LocationNodeNull);
222         AbsoluteLocation client2LocationNodeNull =
223                 DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, null, CLIENT_2_IFACE_NAME);
224         AddressEndpointWithLocation client2Ep = DtoFactory.createEndpoint(CLIENT_IP_2, CLIENT_MAC_2,
225                 DtoFactory.L2FD_CTX.getValue(), client2LocationNodeNull);
226         AbsoluteLocation web2LocationNodeNull =
227                 DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID, null, WEB_2_IFACE_NAME);
228         AddressEndpointWithLocation web2Ep =
229                 DtoFactory.createEndpoint(WEB_IP_2, WEB_MAC_2, DtoFactory.L2FD_CTX.getValue(), web2LocationNodeNull);
230
231         storeVppEndpoint(client1Ep.getKey(), CLIENT_MAC, CLIENT_1_IFACE_NAME, createVppEndpointIid(client1Ep.getKey()));
232         storeVppEndpoint(web1Ep.getKey(), WEB_MAC, WEB_1_IFACE_NAME, createVppEndpointIid(web1Ep.getKey()));
233         storeVppEndpoint(client2Ep.getKey(), CLIENT_MAC_2, CLIENT_2_IFACE_NAME,
234                 createVppEndpointIid(client2Ep.getKey()));
235         storeVppEndpoint(web2Ep.getKey(), WEB_MAC_2, WEB_2_IFACE_NAME, createVppEndpointIid(web2Ep.getKey()));
236
237         Configuration configuration =
238                 DtoFactory.createConfiguration(Arrays.asList(client1Ep, client2Ep), Arrays.asList(web1Ep, web2Ep));
239         RendererPolicy rendererPolicy =
240                 new RendererPolicyBuilder().setVersion(1L).setConfiguration(configuration).build();
241         RendererPolicyConfEvent event = new RendererPolicyConfEvent(RENDERER_POLICY_IID, null, rendererPolicy);
242
243         vppRendererPolicyManager.rendererPolicyChanged(event);
244
245         // assert state on data store behind mount point ######################################
246         Interface client1Iface = readAndAssertInterface(CLIENT_1_IFACE_NAME);
247         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), client1Iface);
248         Interface web1Iface = readAndAssertInterface(WEB_1_IFACE_NAME);
249         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), web1Iface);
250         Interface client2Iface = readAndAssertInterface(CLIENT_2_IFACE_NAME);
251         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), client2Iface);
252         Interface web2Iface = readAndAssertInterface(WEB_2_IFACE_NAME);
253         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), web2Iface);
254         // assert state on ODL data store
255         ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
256         Optional<LocationProvider> optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
257                 IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
258             .get();
259         Assert.assertTrue(optLocationProvider.isPresent());
260         List<ProviderAddressEndpointLocation> epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
261         Assert.assertNotNull(epLocs);
262         Assert.assertEquals(4, epLocs.size());
263         assertProviderAddressEndpointLocation(client1Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
264                 DtoFactory.L2FD_CTX.getValue(), CLIENT_1_IFACE_NAME), epLocs);
265         assertProviderAddressEndpointLocation(web1Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
266                 DtoFactory.L2FD_CTX.getValue(), WEB_1_IFACE_NAME), epLocs);
267         assertProviderAddressEndpointLocation(client2Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
268                 DtoFactory.L2FD_CTX.getValue(), CLIENT_2_IFACE_NAME), epLocs);
269         assertProviderAddressEndpointLocation(web2Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
270                 DtoFactory.L2FD_CTX.getValue(), WEB_2_IFACE_NAME), epLocs);
271         // #####################################################################################
272
273         AbsoluteLocation client1Location = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
274                 DtoFactory.L2FD_CTX.getValue(), CLIENT_1_IFACE_NAME);
275         AbsoluteLocation web1Location = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
276                 DtoFactory.L2FD_CTX.getValue(), WEB_1_IFACE_NAME);
277         AbsoluteLocation web2Location = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
278                 DtoFactory.L2FD_CTX.getValue(), WEB_2_IFACE_NAME);
279         configuration = DtoFactory.createConfiguration(
280                 Arrays.asList(new AddressEndpointWithLocationBuilder(client1Ep).setAbsoluteLocation(client1Location)
281                     .build(),
282                         new AddressEndpointWithLocationBuilder(client2Ep).setAbsoluteLocation(client2LocationNodeNull)
283                             .build()),
284                 Arrays.asList(new AddressEndpointWithLocationBuilder(web1Ep).setAbsoluteLocation(web1Location).build(),
285                         new AddressEndpointWithLocationBuilder(web2Ep).setAbsoluteLocation(web2Location).build()));
286         RendererPolicy rendererPolicy2 =
287                 new RendererPolicyBuilder().setVersion(2L).setConfiguration(configuration).build();
288         RendererPolicyConfEvent event2 =
289                 new RendererPolicyConfEvent(RENDERER_POLICY_IID, rendererPolicy, rendererPolicy2);
290
291         vppRendererPolicyManager.rendererPolicyChanged(event2);
292
293         // assert state on data store behind mount point ######################################
294         client1Iface = readAndAssertInterface(CLIENT_1_IFACE_NAME);
295         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), client1Iface);
296         web1Iface = readAndAssertInterface(WEB_1_IFACE_NAME);
297         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), web1Iface);
298         client2Iface = readAndAssertInterface(CLIENT_2_IFACE_NAME);
299         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), client2Iface);
300         web2Iface = readAndAssertInterface(WEB_2_IFACE_NAME);
301         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), web2Iface);
302         // assert state on ODL data store
303         rTx = dataBroker.newReadOnlyTransaction();
304         optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
305                 IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
306             .get();
307         Assert.assertTrue(optLocationProvider.isPresent());
308         epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
309         Assert.assertNotNull(epLocs);
310         Assert.assertEquals(4, epLocs.size());
311         assertProviderAddressEndpointLocation(client1Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
312                 DtoFactory.L2FD_CTX.getValue(), CLIENT_1_IFACE_NAME), epLocs);
313         assertProviderAddressEndpointLocation(web1Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
314                 DtoFactory.L2FD_CTX.getValue(), WEB_1_IFACE_NAME), epLocs);
315         assertProviderAddressEndpointLocation(client2Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
316                 DtoFactory.L2FD_CTX.getValue(), CLIENT_2_IFACE_NAME), epLocs);
317         assertProviderAddressEndpointLocation(web2Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
318                 DtoFactory.L2FD_CTX.getValue(), WEB_2_IFACE_NAME), epLocs);
319         // #####################################################################################
320
321         AbsoluteLocation client2Location = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
322                 DtoFactory.L2FD_CTX.getValue(), CLIENT_2_IFACE_NAME);
323         configuration = DtoFactory.createConfiguration(
324                 Arrays.asList(new AddressEndpointWithLocationBuilder(client1Ep).setAbsoluteLocation(client1Location)
325                     .build(),
326                         new AddressEndpointWithLocationBuilder(client2Ep).setAbsoluteLocation(client2Location).build()),
327                 Arrays.asList(new AddressEndpointWithLocationBuilder(web1Ep).setAbsoluteLocation(web1Location).build(),
328                         new AddressEndpointWithLocationBuilder(web2Ep).setAbsoluteLocation(web2Location).build()));
329         RendererPolicy rendererPolicy3 =
330                 new RendererPolicyBuilder().setVersion(3L).setConfiguration(configuration).build();
331         RendererPolicyConfEvent event3 =
332                 new RendererPolicyConfEvent(RENDERER_POLICY_IID, rendererPolicy2, rendererPolicy3);
333
334         vppRendererPolicyManager.rendererPolicyChanged(event3);
335
336         // assert state on data store behind mount point ######################################
337         client1Iface = readAndAssertInterface(CLIENT_1_IFACE_NAME);
338         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), client1Iface);
339         web1Iface = readAndAssertInterface(WEB_1_IFACE_NAME);
340         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), web1Iface);
341         client2Iface = readAndAssertInterface(CLIENT_2_IFACE_NAME);
342         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), client2Iface);
343         web2Iface = readAndAssertInterface(WEB_2_IFACE_NAME);
344         assertBridgeDomainOnInterface(DtoFactory.L2FD_CTX.getValue(), web2Iface);
345         // assert state on ODL data store
346         rTx = dataBroker.newReadOnlyTransaction();
347         optLocationProvider = rTx.read(LogicalDatastoreType.CONFIGURATION,
348                 IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
349             .get();
350         Assert.assertTrue(optLocationProvider.isPresent());
351         epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
352         Assert.assertNotNull(epLocs);
353         Assert.assertEquals(4, epLocs.size());
354         assertProviderAddressEndpointLocation(client1Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
355                 DtoFactory.L2FD_CTX.getValue(), CLIENT_1_IFACE_NAME), epLocs);
356         assertProviderAddressEndpointLocation(web1Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
357                 DtoFactory.L2FD_CTX.getValue(), WEB_1_IFACE_NAME), epLocs);
358         assertProviderAddressEndpointLocation(client2Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID,
359                 DtoFactory.L2FD_CTX.getValue(), CLIENT_2_IFACE_NAME), epLocs);
360         assertProviderAddressEndpointLocation(web2Ep.getKey(), DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_2_IID,
361                 DtoFactory.L2FD_CTX.getValue(), WEB_2_IFACE_NAME), epLocs);
362         // #####################################################################################
363     }
364
365     private InstanceIdentifier<VppEndpoint> createVppEndpointIid(AddressEndpointWithLocationKey key) {
366         return InstanceIdentifier.builder(Config.class)
367             .child(VppEndpoint.class, new VppEndpointKey(key.getAddress(), key.getAddressType(), key.getContextId(),
368                     key.getContextType()))
369             .build();
370     }
371
372     private void assertProviderAddressEndpointLocation(AddressEndpointWithLocationKey expectedEpKey,
373             AbsoluteLocation expectedEpLoc, List<ProviderAddressEndpointLocation> providerEpLocs) {
374         List<ProviderAddressEndpointLocation> expectedProvEpLoc =
375                 providerEpLocs.stream()
376                     .filter(provEpLoc -> provEpLoc.getKey()
377                         .equals(KeyFactory.providerAddressEndpointLocationKey(expectedEpKey)))
378                     .collect(Collectors.toList());
379         Assert.assertFalse(expectedProvEpLoc.isEmpty());
380         Assert.assertEquals(1, expectedProvEpLoc.size());
381         Assert.assertEquals(expectedEpLoc, expectedProvEpLoc.get(0).getAbsoluteLocation());
382     }
383
384     private Interface readAndAssertInterface(String expectedInterface) throws Exception {
385         ReadOnlyTransaction rTxMount = mountPointDataBroker.newReadOnlyTransaction();
386         Optional<Interface> potentialIface = rTxMount.read(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier
387             .builder(Interfaces.class).child(Interface.class, new InterfaceKey(expectedInterface)).build()).get();
388         Assert.assertTrue(potentialIface.isPresent());
389         return potentialIface.get();
390     }
391
392     private static void assertBridgeDomainOnInterface(String expectedBridgeDomain, Interface actualIface) {
393         VppInterfaceAugmentation vppIfaceAug = actualIface.getAugmentation(VppInterfaceAugmentation.class);
394         Assert.assertNotNull(vppIfaceAug);
395         if (!Strings.isNullOrEmpty(expectedBridgeDomain)) {
396             Interconnection interconnection = vppIfaceAug.getL2().getInterconnection();
397             Assert.assertNotNull(interconnection);
398             Assert.assertTrue(interconnection instanceof BridgeBased);
399             Assert.assertEquals(expectedBridgeDomain, ((BridgeBased) interconnection).getBridgeDomain());
400         } else {
401             if (vppIfaceAug != null) {
402                 L2 l2 = vppIfaceAug.getL2();
403                 if (l2 != null) {
404                     Assert.assertNull(l2.getInterconnection());
405                 }
406             }
407         }
408     }
409
410     private void storeVppEndpoint(AddressEndpointWithLocationKey clientEp, String mac, String ifaceName,
411             InstanceIdentifier<VppEndpoint> vppEpIid) {
412         AddressEndpoint addrEp = new AddressEndpointBuilder()
413             .setKey(new AddressEndpointKey(clientEp.getAddress(), clientEp.getAddressType(), clientEp.getContextId(),
414                     clientEp.getContextType()))
415             .setTenant(TENANT)
416             .setEndpointGroup(ENDPOINT_GROUP)
417             .setChildEndpoint(Lists.newArrayList(new ChildEndpointBuilder()
418                 .setKey(new ChildEndpointKey(mac, MacAddressType.class, clientEp.getContextId(), L2BridgeDomain.class))
419                 .build()))
420             .build();
421         InstanceIdentifier<AddressEndpoint> iid = InstanceIdentifier.create(Endpoints.class)
422             .child(AddressEndpoints.class)
423             .child(AddressEndpoint.class, addrEp.getKey());
424         WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
425         wTx.put(LogicalDatastoreType.OPERATIONAL, iid, addrEp);
426         try {
427             wTx.submit().get();
428         } catch (InterruptedException | ExecutionException e) {
429             e.printStackTrace();
430         }
431
432         VppEndpoint vhostEp = new VppEndpointBuilder().setAddress(mac)
433             .setAddressType(MacAddressType.class)
434             .setContextId(clientEp.getContextId())
435             .setContextType(L2BridgeDomain.class)
436             .setVppInterfaceName(ifaceName)
437             .setVppNodeId(DtoFactory.VPP_NODE_1_IID.firstKeyOf(Node.class).getNodeId())
438             .setInterfaceTypeChoice(new VhostUserCaseBuilder().setSocket(SOCKET).build())
439             .build();
440         VppEndpointConfEvent vppEpEvent = new VppEndpointConfEvent(vppEpIid, null, vhostEp);
441         ifaceManager.vppEndpointChanged(vppEpEvent);
442     }
443
444 }