1bc05cc9fa833baba92853e2eed5e170e8940b8a
[netvirt.git] / vpnservice / aclservice / impl / src / test / java / org / opendaylight / netvirt / aclservice / LearnEgressAclServiceImplTest.java
1 /*
2  * Copyright (c) 2016 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.aclservice;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.Matchers.any;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.when;
16
17 import com.google.common.base.Optional;
18 import com.google.common.util.concurrent.Futures;
19
20 import java.math.BigInteger;
21 import java.util.Arrays;
22
23 import java.util.Collections;
24 import org.junit.Before;
25 import org.junit.Ignore;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 import org.mockito.Mock;
29 import org.mockito.runners.MockitoJUnitRunner;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
32 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.genius.mdsalutil.FlowEntity;
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.genius.mdsalutil.matches.MatchTcpFlags;
40 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
41 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
42 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
43 import org.opendaylight.netvirt.aclservice.utils.AclServiceTestUtils;
44 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
45 import org.opendaylight.netvirt.aclservice.utils.MethodInvocationParamSaver;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
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.MatchesBuilder;
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.AceIpBuilder;
54 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;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
66 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
67
68 @RunWith(MockitoJUnitRunner.class)
69 public class LearnEgressAclServiceImplTest {
70
71     LearnEgressAclServiceImpl testedService;
72
73     @Mock DataBroker dataBroker;
74     @Mock IMdsalApiManager mdsalManager;
75     @Mock WriteTransaction mockWriteTx;
76     @Mock ReadOnlyTransaction mockReadTx;
77     @Mock AclserviceConfig config;
78
79     MethodInvocationParamSaver<Void> installFlowValueSaver = null;
80     MethodInvocationParamSaver<Void> removeFlowValueSaver = null;
81
82     final Integer tcpFinIdleTimeoutValue = 60;
83
84     @Before
85     public void setUp() {
86         AclDataUtil aclDataUtil = new AclDataUtil();
87         AclServiceUtils aclServiceUtils = new AclServiceUtils(aclDataUtil, config);
88         testedService = new LearnEgressAclServiceImpl(dataBroker, mdsalManager, aclDataUtil, aclServiceUtils);
89         doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
90         doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
91         doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
92         installFlowValueSaver = new MethodInvocationParamSaver<>(null);
93         doAnswer(installFlowValueSaver).when(mdsalManager).installFlow(any(FlowEntity.class));
94         removeFlowValueSaver = new MethodInvocationParamSaver<>(null);
95         doAnswer(installFlowValueSaver).when(mdsalManager).removeFlow(any(FlowEntity.class));
96         doReturn(tcpFinIdleTimeoutValue).when(config).getSecurityGroupTcpFinIdleTimeout();
97     }
98
99     @Test
100     public void addAcl__NullInterface() {
101         assertEquals(false, testedService.applyAcl(null));
102     }
103
104     @Test
105     public void addAcl__MissingInterfaceStateShouldFail() throws Exception {
106         AclInterface ai = new AclInterface();
107         ai.setPortSecurityEnabled(true);
108         ai.setDpId(BigInteger.ONE);
109         assertEquals(false, testedService.applyAcl(ai));
110     }
111
112     @Test
113     public void addAcl__SinglePort() throws Exception {
114         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
115         AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
116         assertEquals(true, testedService.applyAcl(ai));
117         assertEquals(10, installFlowValueSaver.getNumOfInvocations());
118
119         FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
120         AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
121                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
122         AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
123                 ActionLearn.class);
124
125         // verify that tcpFinIdleTimeout is used for TCP
126         AclServiceTestUtils.verifyActionLearn(flow.getInstructionInfoList().get(0).getActionInfos(),
127                 new ActionLearn(
128                         0,
129                         0,
130                         AclConstants.PROTO_MATCH_PRIORITY,
131                         AclConstants.COOKIE_ACL_BASE,
132                         AclConstants.LEARN_DELETE_LEARNED_FLAG_VALUE,
133                         NwConstants.EGRESS_LEARN_TABLE,
134                         tcpFinIdleTimeoutValue,
135                         0,
136                         Collections.emptyList()));
137     }
138
139     @Test
140     public void addAcl__AllowAll() throws Exception {
141         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
142         AclInterface ai = stubAllowAllInterface(sgUuid, "if_name");
143         assertEquals(true, testedService.applyAcl(ai));
144         assertEquals(10, installFlowValueSaver.getNumOfInvocations());
145
146         FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
147         AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
148                 ActionLearn.class);
149     }
150
151     @Test
152     public void addAcl__MultipleRanges() throws Exception {
153         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
154         AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 84);
155         assertEquals(true, testedService.applyAcl(ai));
156         assertEquals(11, installFlowValueSaver.getNumOfInvocations());
157         FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
158         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
159                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65532");
160
161         FlowEntity secondRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(10).get(0);
162         AclServiceTestUtils.verifyMatchInfo(secondRangeFlow.getMatchInfoList(),
163                 NxMatchFieldType.nx_tcp_dst_with_mask, "84", "65535");
164     }
165
166     @Test
167     public void addAcl__UdpSinglePortShouldNotCreateSynRule() throws Exception {
168         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
169         AclInterface ai = stubUdpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
170         assertEquals(true, testedService.applyAcl(ai));
171         assertEquals(10, installFlowValueSaver.getNumOfInvocations());
172         FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(9).get(0);
173         AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
174                 NxMatchFieldType.nx_udp_dst_with_mask, "80", "65535");
175         AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
176                 ActionLearn.class);
177
178         // verify that even though tcpFinIdleTimeout is set to non-zero, it is not used for UDP
179         AclServiceTestUtils.verifyActionLearn(flow.getInstructionInfoList().get(0).getActionInfos(),
180                 new ActionLearn(
181                         0,
182                         0,
183                         AclConstants.PROTO_MATCH_PRIORITY,
184                         AclConstants.COOKIE_ACL_BASE,
185                         AclConstants.LEARN_DELETE_LEARNED_FLAG_VALUE,
186                         NwConstants.EGRESS_LEARN_TABLE,
187                         0,
188                         0,
189                         Collections.emptyList()));
190     }
191
192     @Test
193     @Ignore
194     public void removeAcl__SinglePort() throws Exception {
195         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
196         AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
197         assertEquals(true, testedService.removeAcl(ai));
198         assertEquals(5, removeFlowValueSaver.getNumOfInvocations());
199         FlowEntity firstRangeFlow = (FlowEntity) removeFlowValueSaver.getInvocationParams(4).get(0);
200         assertTrue(firstRangeFlow.getMatchInfoList().contains(new MatchTcpFlags(2)));
201         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
202                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
203     }
204
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);
213
214         stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_UDP);
215         return ai;
216     }
217
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);
226
227         stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_TCP);
228         return ai;
229     }
230
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()));
236     }
237
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);
245
246         stubAccessList(sgUuid, null, -1, -1, (short)-1);
247         return ai;
248     }
249
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));
254
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());
261         }
262         if (ipv4PrefixStr != null) {
263             AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
264             Ipv4Prefix ipv4Prefix = new Ipv4Prefix(ipv4PrefixStr);
265             aceIpv4Builder.setSourceIpv4Network(ipv4Prefix);
266             aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
267         }
268         if (protocol != -1) {
269             aceIpBuilder.setProtocol(protocol);
270         }
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());
281
282         InstanceIdentifier<Acl> aclKey = AclServiceUtils.getAclInstanceIdentifier(sgUuid.getValue());
283         when(mockReadTx.read(LogicalDatastoreType.CONFIGURATION, aclKey))
284             .thenReturn(Futures.immediateCheckedFuture(Optional.of(ab.build())));
285     }
286 }