2 * Copyright (c) 2016 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.aclservice;
10 import static org.junit.Assert.assertEquals;
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Mockito.doAnswer;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.when;
16 import com.google.common.base.Optional;
17 import com.google.common.util.concurrent.Futures;
18 import java.math.BigInteger;
19 import java.util.Arrays;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.mockito.Mock;
24 import org.mockito.runners.MockitoJUnitRunner;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
27 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.genius.mdsalutil.ActionType;
30 import org.opendaylight.genius.mdsalutil.FlowEntity;
31 import org.opendaylight.genius.mdsalutil.MatchFieldType;
32 import org.opendaylight.genius.mdsalutil.NwConstants;
33 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
34 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
35 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
36 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
37 import org.opendaylight.netvirt.aclservice.utils.AclServiceTestUtils;
38 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
39 import org.opendaylight.netvirt.aclservice.utils.MethodInvocationParamSaver;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.MatchesBuilder;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIpBuilder;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4Builder;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 @RunWith(MockitoJUnitRunner.class)
62 public class StatelessIngressAclServiceImplTest {
64 private StatelessIngressAclServiceImpl testedService;
67 DataBroker dataBroker;
69 IMdsalApiManager mdsalManager;
71 WriteTransaction mockWriteTx;
73 ReadOnlyTransaction mockReadTx;
75 MethodInvocationParamSaver<Void> installFlowValueSaver = null;
76 MethodInvocationParamSaver<Void> removeFlowValueSaver = null;
80 testedService = new StatelessIngressAclServiceImpl(dataBroker, mdsalManager);
81 doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
82 doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
83 doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
84 installFlowValueSaver = new MethodInvocationParamSaver<Void>(null);
85 doAnswer(installFlowValueSaver).when(mdsalManager).installFlow(any(FlowEntity.class));
86 removeFlowValueSaver = new MethodInvocationParamSaver<Void>(null);
87 doAnswer(removeFlowValueSaver).when(mdsalManager).removeFlow(any(FlowEntity.class));
91 public void addAcl__NullInterface() {
92 assertEquals(false, testedService.applyAcl(null));
96 public void addAcl__MissingInterfaceStateShouldFail() throws Exception {
97 AclInterface ai = new AclInterface();
98 ai.setPortSecurityEnabled(true);
99 ai.setDpId(BigInteger.ONE);
100 assertEquals(false, testedService.applyAcl(ai));
104 public void addAcl__SinglePort() throws Exception {
105 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
106 AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
107 assertEquals(true, testedService.applyAcl(ai));
108 assertEquals(1, installFlowValueSaver.getNumOfInvocations());
110 FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(0).get(0);
111 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
112 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
113 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
114 AclServiceTestUtils.verifyActionInfo(firstRangeFlow.getInstructionInfoList().get(0).getActionInfos(),
115 ActionType.nx_resubmit, "" + NwConstants.EGRESS_LPORT_DISPATCHER_TABLE);
119 public void addAcl__AllowAll() throws Exception {
120 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
121 AclInterface ai = stubAllowAllInterface(sgUuid, "if_name");
122 assertEquals(true, testedService.applyAcl(ai));
123 assertEquals(1, installFlowValueSaver.getNumOfInvocations());
125 FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(0).get(0);
126 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
127 AclServiceTestUtils.verifyActionInfo(firstRangeFlow.getInstructionInfoList().get(0).getActionInfos(),
128 ActionType.nx_resubmit, "" + NwConstants.EGRESS_LPORT_DISPATCHER_TABLE);
132 public void addAcl__MultipleRanges() throws Exception {
133 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
134 AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 84);
135 assertEquals(true, testedService.applyAcl(ai));
136 assertEquals(2, installFlowValueSaver.getNumOfInvocations());
137 FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(0).get(0);
138 // should have been 80-83 will be fixed as part of the port range support
139 // https://bugs.opendaylight.org/show_bug.cgi?id=6200
140 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
141 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65532");
142 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
144 FlowEntity secondRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(1).get(0);
145 AclServiceTestUtils.verifyMatchInfo(secondRangeFlow.getMatchInfoList(),
146 NxMatchFieldType.nx_tcp_dst_with_mask, "84", "65535");
147 AclServiceTestUtils.verifyMatchInfo(secondRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
151 public void addAcl__UdpSinglePortShouldDoNothing() throws Exception {
152 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
153 AclInterface ai = stubUdpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
154 assertEquals(true, testedService.applyAcl(ai));
155 assertEquals(0, installFlowValueSaver.getNumOfInvocations());
159 public void removeAcl__SinglePort() throws Exception {
160 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
161 AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
162 assertEquals(true, testedService.removeAcl(ai));
163 assertEquals(1, removeFlowValueSaver.getNumOfInvocations());
164 FlowEntity firstSynFlow = (FlowEntity) removeFlowValueSaver.getInvocationParams(0).get(0);
165 AclServiceTestUtils.verifyMatchInfo(firstSynFlow.getMatchInfoList(),
166 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
167 AclServiceTestUtils.verifyMatchInfo(firstSynFlow.getMatchInfoList(), MatchFieldType.tcp_flags,
168 AclConstants.TCP_FLAG_SYN + "");
172 private AclInterface stubUdpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
173 int tcpPortLower, int tcpPortUpper) {
174 AclInterface ai = new AclInterface();
175 ai.setPortSecurityEnabled(true);
176 ai.setSecurityGroups(Arrays.asList(sgUuid));
177 ai.setDpId(BigInteger.ONE);
178 ai.setLPortTag(new Integer(2));
179 stubInterfaceAcl(ifName, ai);
181 stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_UDP);
185 private AclInterface stubTcpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
186 int tcpPortLower, int tcpPortUpper) {
187 AclInterface ai = new AclInterface();
188 ai.setPortSecurityEnabled(true);
189 ai.setDpId(BigInteger.ONE);
190 ai.setLPortTag(Integer.valueOf(2));
191 ai.setSecurityGroups(Arrays.asList(sgUuid));
192 stubInterfaceAcl(ifName, ai);
194 stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_TCP);
198 private AclInterface stubAllowAllInterface(Uuid sgUuid, String ifName) {
199 AclInterface ai = new AclInterface();
200 ai.setPortSecurityEnabled(true);
201 ai.setSecurityGroups(Arrays.asList(sgUuid));
202 ai.setDpId(BigInteger.ONE);
203 ai.setLPortTag(new Integer(2));
204 stubInterfaceAcl(ifName, ai);
206 stubAccessList(sgUuid, null, -1, -1, (short)-1);
210 private void stubInterfaceAcl(String ifName, AclInterface ai) {
211 AllowedAddressPairsBuilder aapb = new AllowedAddressPairsBuilder();
212 aapb.setIpAddress(new IpPrefixOrAddress("1.1.1.1/32".toCharArray()));
213 aapb.setMacAddress(new MacAddress("AA:BB:CC:DD:EE:FF"));
214 ai.setAllowedAddressPairs(Arrays.asList(aapb.build()));
217 private void stubAccessList(Uuid sgUuid, String ipv4PrefixStr, int portLower, int portUpper, short protocol) {
218 AclBuilder ab = new AclBuilder();
219 ab.setAclName("AAA");
220 ab.setKey(new AclKey(sgUuid.getValue(),Ipv4Acl.class));
222 AceIpBuilder aceIpBuilder = new AceIpBuilder();
223 if (portLower != -1 && portUpper != -1) {
224 DestinationPortRangeBuilder dprb = new DestinationPortRangeBuilder();
225 dprb.setLowerPort(new PortNumber(portLower));
226 dprb.setUpperPort(new PortNumber(portUpper));
227 aceIpBuilder.setDestinationPortRange(dprb.build());
229 AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
230 if (ipv4PrefixStr != null) {
231 Ipv4Prefix ipv4Prefix = new Ipv4Prefix(ipv4PrefixStr);
232 aceIpv4Builder.setDestinationIpv4Network(ipv4Prefix);
233 aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
235 if (protocol != -1) {
236 aceIpBuilder.setProtocol(protocol);
238 MatchesBuilder matches = new MatchesBuilder();
239 matches.setAceType(aceIpBuilder.build());
240 AceBuilder aceBuilder = new AceBuilder();
241 aceBuilder.setMatches(matches.build());
242 SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
243 securityRuleAttrBuilder.setDirection(DirectionIngress.class);
244 aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
245 AccessListEntriesBuilder aleb = new AccessListEntriesBuilder();
246 aleb.setAce(Arrays.asList(aceBuilder.build()));
247 ab.setAccessListEntries(aleb.build());
249 InstanceIdentifier<Acl> aclKey = AclServiceUtils.getAclInstanceIdentifier(sgUuid.getValue());
250 when(mockReadTx.read(LogicalDatastoreType.CONFIGURATION, aclKey))
251 .thenReturn(Futures.immediateCheckedFuture(Optional.of(ab.build())));