2 * Copyright (c) 2017 Cisco Systems, 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
9 package org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl;
11 import java.util.AbstractMap;
12 import java.util.ArrayList;
13 import java.util.List;
15 import java.util.concurrent.locks.ReentrantLock;
17 import org.junit.Assert;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.mockito.Mockito;
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
25 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppPathMapper;
26 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;
27 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
28 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
29 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
30 import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroupKey;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
41 import com.google.common.base.Optional;
42 import com.google.common.collect.Sets;
43 import com.google.common.collect.Sets.SetView;
45 public class AclManagerTest extends TestResources {
47 private PolicyContext ctx;
48 private MountedDataBrokerProvider mountedDataProviderMock;
49 private DataBroker mountPointDataBroker;
50 private AclManager aclManager;
54 ctx = super.createPolicyContext(createAddressEndpoints(), createRendEps(), createRuleGroups(),
56 mountedDataProviderMock = Mockito.mock(MountedDataBrokerProvider.class);
57 mountPointDataBroker = getDataBroker();
58 aclManager = new AclManager(mountedDataProviderMock, Mockito.mock(InterfaceManager.class));
59 Mockito.when(mountedDataProviderMock.resolveDataBrokerForMountPoint(Mockito.any(InstanceIdentifier.class)))
60 .thenReturn(Optional.of(mountPointDataBroker));
61 VbdNetconfTransaction.NODE_DATA_BROKER_MAP.put(VppIidFactory.getNetconfNodeIid(new NodeId("node1")),
62 new AbstractMap.SimpleEntry<DataBroker, ReentrantLock>(mountPointDataBroker, new ReentrantLock()));
66 public void oneEndpointChanged() {
67 List<Acl> acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp1.getKey())), true);
68 Assert.assertEquals(6, acls.size());
70 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
71 Assert.assertEquals(2 + 4, acl.getAccessListEntries().getAce().size());
73 Assert.assertEquals(2 + 2, acl.getAccessListEntries().getAce().size());
76 acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp1.getKey())), false);
77 Assert.assertEquals(6, acls.size());
79 System.out.println("DEBUGX " + acl);
80 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
81 acl.getAccessListEntries().getAce().forEach(ace -> {
82 System.out.println("DEBUG1 " + ace);
85 * TODO rules were not removed, entire ACL is removed elsewhere when interface at
86 * NODE1_CONNECTOR_1 detaches from bridge domain.
88 Assert.assertEquals(6, acl.getAccessListEntries().getAce().size());
90 Assert.assertEquals(2, acl.getAccessListEntries().getAce().size());
96 public void oneEndpointChanged_createRulesOnlyForChangedEpInPeer() {
97 List<Acl> acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp2.getKey())), true);
98 Assert.assertEquals(acls.size(), 4);
100 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
101 Assert.assertEquals(2 + 4, acl.getAccessListEntries().getAce().size());
103 Assert.assertEquals(2 + 2, acl.getAccessListEntries().getAce().size());
106 acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp2.getKey())), false);
107 Assert.assertEquals(acls.size(), 4);
108 acls.forEach(acl -> {
109 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
110 // Peer is updated 4 rules went to 2.
111 Assert.assertEquals(2, acl.getAccessListEntries().getAce().size());
113 // Entire ACL is removed elsewhere -> no update of rules needed.
114 Assert.assertEquals(4, acl.getAccessListEntries().getAce().size());
120 * Tests DHCP rules configuration. There should be no entries for DHCP servers serving different
122 * hosts should only have rules for accessing DHCP server in their subnet.
125 public void dhcpDifferentSubnets() {
126 final String ep4Mac = "20:00:00:00:00:02";
127 final String ep4Ip = "20.0.0.2/32";
128 final ContextId l2BdId2 = new ContextId("l2BridgeDomainId2");
129 final String node1Connector4 =
130 "/ietf-interfaces:interfaces/ietf-interfaces:interface[ietf-interfaces:name='nodeConnector4']";
131 final AddressEndpointWithLocation l2DhcpEp = l2AddressEndpointWithLocation(ep4Mac, l2BdId2, ep4Ip, L3_CTX_ID);
132 final AddressEndpointWithLocation l3DhcpEp = appendLocationToEndpoint(
133 l3AddressEndpointWithLocation(ep4Mac, l2BdId2, ep4Ip, L3_CTX_ID), NODE1, node1Connector4);
134 List<AddressEndpointWithLocation> addrEps = createAddressEndpoints();
135 addrEps.add(l2DhcpEp);
136 addrEps.add(l3DhcpEp);
137 List<RendererEndpoint> rEps = new ArrayList<>();
138 // DHCP from different subnet
139 rEps.add(createRendEndpoint(rendererEndpointKey(l3DhcpEp.getKey()), SECURITY_GROUP.SERVER,
140 peerEndpointKey(l3AddrEp2.getKey()), peerEndpointKey(l3AddrEp3.getKey())));
141 // DHCP from local subnet
142 rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp1.getKey()), SECURITY_GROUP.SERVER,
143 peerEndpointKey(l3AddrEp2.getKey()), peerEndpointKey(l3AddrEp3.getKey())));
144 rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp2.getKey()), SECURITY_GROUP.CLIENT,
145 peerEndpointKey(l3AddrEp1.getKey()), peerEndpointKey(l3DhcpEp.getKey())));
146 rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp3.getKey()), SECURITY_GROUP.CLIENT,
147 peerEndpointKey(l3AddrEp1.getKey()), peerEndpointKey(l3DhcpEp.getKey())));
148 ctx = super.createPolicyContext(addrEps, rEps, createRuleGroupsDhcpTest(), createForwarding());
149 List<Acl> acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp2.getKey())), true);
150 Assert.assertEquals(acls.size(), 6);
151 acls.forEach(acl -> {
152 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(node1Connector4).get())) {
153 Assert.assertEquals(2, acl.getAccessListEntries().getAce().size());
154 } else if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
155 Assert.assertEquals(6, acl.getAccessListEntries().getAce().size());
157 Assert.assertEquals(4, acl.getAccessListEntries().getAce().size());
164 * Metadata use case. DHCP endpoint and metadata endpoint are on the same access interface and
165 * so their entries meet in one ACL.
168 public void oneEndpointChanged_metadataUseCase() {
169 createContextFormetadataUseCase();
170 List<Acl> acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp2.getKey())), true);
171 Assert.assertEquals(acls.size(), 4);
172 acls.forEach(acl -> {
173 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
174 Assert.assertEquals(10, acl.getAccessListEntries().getAce().size());
176 Assert.assertEquals(6, acl.getAccessListEntries().getAce().size());
179 acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp2.getKey())), false);
180 Assert.assertEquals(acls.size(), 4);
181 acls.forEach(acl -> {
182 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
183 Assert.assertEquals(2, acl.getAccessListEntries().getAce().size());
185 // Entire ACL is removed elsewhere -> no update of rules needed.
186 Assert.assertEquals(6, acl.getAccessListEntries().getAce().size());
191 public void createContextFormetadataUseCase() {
192 String ep4Mac = "11:11:22:22:44:44";
193 String ep4Ip = "10.0.0.40/32";
194 final AddressEndpointWithLocation l2MetadataEp =
195 l2AddressEndpointWithLocation(ep4Mac, L2_BD_ID, ep4Ip, L3_CTX_ID);
196 final AddressEndpointWithLocation l3MetadataEp = appendLocationToEndpoint(
197 l3AddressEndpointWithLocation(ep4Mac, L2_BD_ID, ep4Ip, L3_CTX_ID), NODE1, NODE1_CONNECTOR_1);
198 List<AddressEndpointWithLocation> addrEps = createAddressEndpoints();
199 addrEps.add(l2MetadataEp);
200 addrEps.add(l3MetadataEp);
201 List<RendererEndpoint> rEps = new ArrayList<>();
202 rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp1.getKey()), SECURITY_GROUP.SERVER,
203 peerEndpointKey(l3AddrEp2.getKey()), peerEndpointKey(l3AddrEp3.getKey())));
204 rEps.add(createRendEndpoint(rendererEndpointKey(l3MetadataEp.getKey()), SECURITY_GROUP.SERVER,
205 peerEndpointKey(l3AddrEp2.getKey()), peerEndpointKey(l3AddrEp3.getKey())));
206 rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp2.getKey()), SECURITY_GROUP.CLIENT,
207 peerEndpointKey(l3AddrEp1.getKey()), peerEndpointKey(l3MetadataEp.getKey())));
208 rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp3.getKey()), SECURITY_GROUP.CLIENT,
209 peerEndpointKey(l3AddrEp1.getKey()), peerEndpointKey(l3MetadataEp.getKey())));
210 ctx = super.createPolicyContext(addrEps, rEps, createRuleGroups(), createForwarding());
213 public List<Acl> processChangedEndpoints(Set<RendererEndpointKey> changedEndpoints, boolean created) {
214 aclManager.cacheEndpointsByInterfaces(ctx);
215 SetView<RendererEndpointKey> deltaEndpoints = Sets.difference(changedEndpoints, Sets.newHashSet());
216 SetView<RuleGroupKey> deltaRules = Sets.intersection(Sets.newHashSet(), Sets.newHashSet());
217 aclManager.resolveRulesToConfigure(ctx, deltaEndpoints, deltaRules, created);
218 ReadOnlyTransaction rTx = mountPointDataBroker.newReadOnlyTransaction();
219 Optional<AccessLists> readAccessLists = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
220 InstanceIdentifier.builder(AccessLists.class).build(), rTx);
222 Assert.assertTrue(readAccessLists.isPresent());
223 return readAccessLists.get().getAcl();
227 public void oneRuleChanged() {
228 processAndAssertChangedRules(Sets.newHashSet(new RuleGroupKey(CONTRACT_ID, SUBJECT_NAME, TENANT_ID)), true);
229 processAndAssertChangedRules(Sets.newHashSet(new RuleGroupKey(CONTRACT_ID, SUBJECT_NAME, TENANT_ID)), false);
233 public void twoRulesChanged() {
234 processAndAssertChangedRules(Sets.newHashSet(new RuleGroupKey(CONTRACT_ID, SUBJECT_NAME, TENANT_ID),
235 new RuleGroupKey(CONTRACT_ID, SUBJECT_NAME2, TENANT_ID)), true);
236 processAndAssertChangedRules(Sets.newHashSet(new RuleGroupKey(CONTRACT_ID, SUBJECT_NAME, TENANT_ID),
237 new RuleGroupKey(CONTRACT_ID, SUBJECT_NAME2, TENANT_ID)), false);
240 public void processAndAssertChangedRules(Set<RuleGroupKey> createdRuleGroups, boolean created) {
241 aclManager.cacheEndpointsByInterfaces(ctx);
242 SetView<RendererEndpointKey> deltaRendEp = Sets.intersection(Sets.newHashSet(), Sets.newHashSet());
243 SetView<RuleGroupKey> deltaRuleGroups = Sets.difference(createdRuleGroups, Sets.newHashSet());
244 aclManager.resolveRulesToConfigure(ctx, deltaRendEp, deltaRuleGroups, created);
245 ReadOnlyTransaction rTx = mountPointDataBroker.newReadOnlyTransaction();
246 Optional<AccessLists> readAccessLists = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
247 InstanceIdentifier.builder(AccessLists.class).build(), rTx);
249 Assert.assertTrue(readAccessLists.isPresent());
250 List<Acl> acls = readAccessLists.get().getAcl();
251 Assert.assertEquals(acls.size(), 6);
252 acls.forEach(acl -> {
254 if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) {
255 diff = 2 * createdRuleGroups.size() * ((created) ? 1 : 0);
257 diff = createdRuleGroups.size() * ((created) ? 1 : 0);
259 Assert.assertEquals(2 + diff, acl.getAccessListEntries().getAce().size());