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;
19 import java.math.BigInteger;
20 import java.util.Arrays;
22 import java.util.Collections;
23 import org.junit.Before;
24 import org.junit.Ignore;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27 import org.mockito.Mock;
28 import org.mockito.runners.MockitoJUnitRunner;
29 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
30 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
31 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.genius.mdsalutil.FlowEntity;
34 import org.opendaylight.genius.mdsalutil.MatchFieldType;
35 import org.opendaylight.genius.mdsalutil.NwConstants;
36 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
37 import org.opendaylight.genius.mdsalutil.actions.ActionLearn;
38 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
39 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
40 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
41 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
42 import org.opendaylight.netvirt.aclservice.utils.AclServiceTestUtils;
43 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
44 import org.opendaylight.netvirt.aclservice.utils.MethodInvocationParamSaver;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
51 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;
52 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;
53 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;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
65 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
67 @RunWith(MockitoJUnitRunner.class)
68 public class LearnEgressAclServiceImplTest {
70 LearnEgressAclServiceImpl testedService;
72 @Mock DataBroker dataBroker;
73 @Mock IMdsalApiManager mdsalManager;
74 @Mock WriteTransaction mockWriteTx;
75 @Mock ReadOnlyTransaction mockReadTx;
76 @Mock AclserviceConfig config;
78 MethodInvocationParamSaver<Void> installFlowValueSaver = null;
79 MethodInvocationParamSaver<Void> removeFlowValueSaver = null;
81 final Integer tcpFinIdleTimeoutValue = 60;
85 AclDataUtil aclDataUtil = new AclDataUtil();
86 AclServiceUtils aclServiceUtils = new AclServiceUtils(aclDataUtil, config);
87 testedService = new LearnEgressAclServiceImpl(dataBroker, mdsalManager, aclDataUtil, aclServiceUtils);
88 doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
89 doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
90 doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
91 installFlowValueSaver = new MethodInvocationParamSaver<>(null);
92 doAnswer(installFlowValueSaver).when(mdsalManager).installFlow(any(FlowEntity.class));
93 removeFlowValueSaver = new MethodInvocationParamSaver<>(null);
94 doAnswer(installFlowValueSaver).when(mdsalManager).removeFlow(any(FlowEntity.class));
95 doReturn(tcpFinIdleTimeoutValue).when(config).getSecurityGroupTcpFinIdleTimeout();
99 public void addAcl__NullInterface() {
100 assertEquals(false, testedService.applyAcl(null));
104 public void addAcl__MissingInterfaceStateShouldFail() throws Exception {
105 AclInterface ai = new AclInterface();
106 ai.setPortSecurityEnabled(true);
107 ai.setDpId(BigInteger.ONE);
108 assertEquals(false, testedService.applyAcl(ai));
112 public void addAcl__SinglePort() throws Exception {
113 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
114 AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
115 assertEquals(true, testedService.applyAcl(ai));
116 assertEquals(10, installFlowValueSaver.getNumOfInvocations());
118 FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
119 AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
120 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
121 AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
124 // verify that tcpFinIdleTimeout is used for TCP
125 AclServiceTestUtils.verifyActionLearn(flow.getInstructionInfoList().get(0).getActionInfos(),
129 AclConstants.PROTO_MATCH_PRIORITY,
130 AclConstants.COOKIE_ACL_BASE,
131 AclConstants.LEARN_DELETE_LEARNED_FLAG_VALUE,
132 NwConstants.EGRESS_LEARN_TABLE,
133 tcpFinIdleTimeoutValue,
135 Collections.emptyList()));
139 public void addAcl__AllowAll() throws Exception {
140 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
141 AclInterface ai = stubAllowAllInterface(sgUuid, "if_name");
142 assertEquals(true, testedService.applyAcl(ai));
143 assertEquals(10, installFlowValueSaver.getNumOfInvocations());
145 FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
146 AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
151 public void addAcl__MultipleRanges() throws Exception {
152 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
153 AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 84);
154 assertEquals(true, testedService.applyAcl(ai));
155 assertEquals(11, installFlowValueSaver.getNumOfInvocations());
156 FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
157 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
158 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65532");
160 FlowEntity secondRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(10).get(0);
161 AclServiceTestUtils.verifyMatchInfo(secondRangeFlow.getMatchInfoList(),
162 NxMatchFieldType.nx_tcp_dst_with_mask, "84", "65535");
166 public void addAcl__UdpSinglePortShouldNotCreateSynRule() throws Exception {
167 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
168 AclInterface ai = stubUdpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
169 assertEquals(true, testedService.applyAcl(ai));
170 assertEquals(10, installFlowValueSaver.getNumOfInvocations());
171 FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
172 AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
173 NxMatchFieldType.nx_udp_dst_with_mask, "80", "65535");
174 AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
177 // verify that even though tcpFinIdleTimeout is set to non-zero, it is not used for UDP
178 AclServiceTestUtils.verifyActionLearn(flow.getInstructionInfoList().get(0).getActionInfos(),
182 AclConstants.PROTO_MATCH_PRIORITY,
183 AclConstants.COOKIE_ACL_BASE,
184 AclConstants.LEARN_DELETE_LEARNED_FLAG_VALUE,
185 NwConstants.EGRESS_LEARN_TABLE,
188 Collections.emptyList()));
193 public void removeAcl__SinglePort() throws Exception {
194 Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
195 AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
196 assertEquals(true, testedService.removeAcl(ai));
197 assertEquals(5, removeFlowValueSaver.getNumOfInvocations());
198 FlowEntity firstRangeFlow = (FlowEntity) removeFlowValueSaver.getInvocationParams(4).get(0);
199 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
200 AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
201 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
205 private AclInterface stubUdpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
206 int tcpPortLower, int tcpPortUpper) {
207 AclInterface ai = new AclInterface();
208 ai.setPortSecurityEnabled(true);
209 ai.setSecurityGroups(Arrays.asList(sgUuid));
210 ai.setDpId(BigInteger.ONE);
211 ai.setLPortTag(new Integer(2));
212 stubInterfaceAcl(ifName, ai);
214 stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_UDP);
218 private AclInterface stubTcpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
219 int tcpPortLower, int tcpPortUpper) {
220 AclInterface ai = new AclInterface();
221 ai.setPortSecurityEnabled(true);
222 ai.setDpId(BigInteger.ONE);
223 ai.setLPortTag(Integer.valueOf(2));
224 ai.setSecurityGroups(Arrays.asList(sgUuid));
225 stubInterfaceAcl(ifName, ai);
227 stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_TCP);
231 private void stubInterfaceAcl(String ifName, AclInterface ai) {
232 AllowedAddressPairsBuilder aapb = new AllowedAddressPairsBuilder();
233 aapb.setIpAddress(new IpPrefixOrAddress("1.1.1.1/32".toCharArray()));
234 aapb.setMacAddress(new MacAddress("AA:BB:CC:DD:EE:FF"));
235 ai.setAllowedAddressPairs(Arrays.asList(aapb.build()));
238 private AclInterface stubAllowAllInterface(Uuid sgUuid, String ifName) {
239 AclInterface ai = new AclInterface();
240 ai.setPortSecurityEnabled(true);
241 ai.setSecurityGroups(Arrays.asList(sgUuid));
242 ai.setDpId(BigInteger.ONE);
243 ai.setLPortTag(new Integer(2));
244 stubInterfaceAcl(ifName, ai);
246 stubAccessList(sgUuid, null, -1, -1, (short)-1);
250 private void stubAccessList(Uuid sgUuid, String ipv4PrefixStr, int portLower, int portUpper, short protocol) {
251 AclBuilder ab = new AclBuilder();
252 ab.setAclName("AAA");
253 ab.setKey(new AclKey(sgUuid.getValue(),Ipv4Acl.class));
255 AceIpBuilder aceIpBuilder = new AceIpBuilder();
256 if (portLower != -1 && portUpper != -1) {
257 DestinationPortRangeBuilder dprb = new DestinationPortRangeBuilder();
258 dprb.setLowerPort(new PortNumber(portLower));
259 dprb.setUpperPort(new PortNumber(portUpper));
260 aceIpBuilder.setDestinationPortRange(dprb.build());
262 if (ipv4PrefixStr != null) {
263 AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
264 Ipv4Prefix ipv4Prefix = new Ipv4Prefix(ipv4PrefixStr);
265 aceIpv4Builder.setSourceIpv4Network(ipv4Prefix);
266 aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
268 if (protocol != -1) {
269 aceIpBuilder.setProtocol(protocol);
271 MatchesBuilder matches = new MatchesBuilder();
272 matches.setAceType(aceIpBuilder.build());
273 AceBuilder aceBuilder = new AceBuilder();
274 aceBuilder.setMatches(matches.build());
275 SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
276 securityRuleAttrBuilder.setDirection(DirectionEgress.class);
277 aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
278 AccessListEntriesBuilder aleb = new AccessListEntriesBuilder();
279 aleb.setAce(Arrays.asList(aceBuilder.build()));
280 ab.setAccessListEntries(aleb.build());
282 InstanceIdentifier<Acl> aclKey = AclServiceUtils.getAclInstanceIdentifier(sgUuid.getValue());
283 when(mockReadTx.read(LogicalDatastoreType.CONFIGURATION, aclKey))
284 .thenReturn(Futures.immediateCheckedFuture(Optional.of(ab.build())));