Merge "Exception in SubnetRoute Feature"
[netvirt.git] / vpnservice / aclservice / impl / src / test / java / org / opendaylight / netvirt / aclservice / StatelessEgressAclServiceImplTest.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.mockito.Matchers.any;
12 import static org.mockito.Mockito.doAnswer;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.when;
15
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.AclServiceTestUtils;
37 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
38 import org.opendaylight.netvirt.aclservice.utils.MethodInvocationParamSaver;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
45 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;
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.matches.ace.type.AceIpBuilder;
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.ace.ip.ace.ip.version.AceIpv4Builder;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59
60 @RunWith(MockitoJUnitRunner.class)
61 public class StatelessEgressAclServiceImplTest {
62
63     private StatelessEgressAclServiceImpl testedService;
64
65     @Mock
66     DataBroker dataBroker;
67     @Mock
68     IMdsalApiManager mdsalManager;
69     @Mock
70     WriteTransaction mockWriteTx;
71     @Mock
72     ReadOnlyTransaction mockReadTx;
73
74     MethodInvocationParamSaver<Void> installFlowValueSaver = null;
75     MethodInvocationParamSaver<Void> removeFlowValueSaver = null;
76
77     @Before
78     public void setUp() {
79         testedService = new StatelessEgressAclServiceImpl(dataBroker, mdsalManager);
80         doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
81         doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
82         doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
83         installFlowValueSaver = new MethodInvocationParamSaver<Void>(null);
84         doAnswer(installFlowValueSaver).when(mdsalManager).installFlow(any(FlowEntity.class));
85         removeFlowValueSaver = new MethodInvocationParamSaver<Void>(null);
86         doAnswer(removeFlowValueSaver).when(mdsalManager).removeFlow(any(FlowEntity.class));
87     }
88
89     @Test
90     public void addAcl__NullInterface() {
91         assertEquals(false, testedService.applyAcl(null));
92     }
93
94     @Test
95     public void addAcl__MissingInterfaceStateShouldFail() throws Exception {
96         AclInterface ai = new AclInterface();
97         ai.setPortSecurityEnabled(true);
98         ai.setDpId(BigInteger.ONE);
99         assertEquals(false, testedService.applyAcl(ai));
100     }
101
102     @Test
103     public void addAcl__SinglePort() throws Exception {
104         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
105         AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
106         assertEquals(true, testedService.applyAcl(ai));
107         assertEquals(1, installFlowValueSaver.getNumOfInvocations());
108
109         FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(0).get(0);
110         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
111                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
112         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
113         AclServiceTestUtils.verifyActionInfo(firstRangeFlow.getInstructionInfoList().get(0).getActionInfos(),
114                 ActionType.nx_resubmit, "" + NwConstants.LPORT_DISPATCHER_TABLE);
115
116     }
117
118     @Test
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());
124
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.LPORT_DISPATCHER_TABLE);
129     }
130
131     @Test
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");
143
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");
148     }
149
150     @Test
151     public void addAcl__UdpSinglePortShouldNotCreateSynRule() 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());
156     }
157
158     @Test
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 firstRangeFlow = (FlowEntity) removeFlowValueSaver.getInvocationParams(0).get(0);
165         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
166         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
167                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
168
169     }
170
171     private AclInterface stubUdpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
172             int tcpPortLower, int tcpPortUpper) {
173         AclInterface ai = new AclInterface();
174         ai.setPortSecurityEnabled(true);
175         ai.setSecurityGroups(Arrays.asList(sgUuid));
176         ai.setDpId(BigInteger.ONE);
177         ai.setLPortTag(new Integer(2));
178         stubInterfaceAcl(ifName, ai);
179
180         stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_UDP);
181         return ai;
182     }
183
184     private AclInterface stubTcpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
185             int tcpPortLower, int tcpPortUpper) {
186         AclInterface ai = new AclInterface();
187         ai.setPortSecurityEnabled(true);
188         ai.setDpId(BigInteger.ONE);
189         ai.setLPortTag(Integer.valueOf(2));
190         ai.setSecurityGroups(Arrays.asList(sgUuid));
191         stubInterfaceAcl(ifName, ai);
192
193         stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_TCP);
194         return ai;
195     }
196
197     private AclInterface stubAllowAllInterface(Uuid sgUuid, String ifName) {
198         AclInterface ai = new AclInterface();
199         ai.setPortSecurityEnabled(true);
200         ai.setSecurityGroups(Arrays.asList(sgUuid));
201         ai.setDpId(BigInteger.ONE);
202         ai.setLPortTag(new Integer(2));
203         stubInterfaceAcl(ifName, ai);
204
205         stubAccessList(sgUuid, null, -1, -1, (short)-1);
206         return ai;
207     }
208
209     private void stubInterfaceAcl(String ifName, AclInterface ai) {
210         AllowedAddressPairsBuilder aapb = new AllowedAddressPairsBuilder();
211         aapb.setIpAddress(new IpPrefixOrAddress("1.1.1.1/32".toCharArray()));
212         aapb.setMacAddress(new MacAddress("AA:BB:CC:DD:EE:FF"));
213         ai.setAllowedAddressPairs(Arrays.asList(aapb.build()));
214     }
215
216     private void stubAccessList(Uuid sgUuid, String ipv4PrefixStr, int portLower, int portUpper, short protocol) {
217         AclBuilder ab = new AclBuilder();
218         ab.setAclName("AAA");
219         ab.setKey(new AclKey(sgUuid.getValue(),Ipv4Acl.class));
220
221         AceIpBuilder aceIpBuilder = new AceIpBuilder();
222         if (portLower != -1 && portUpper != -1) {
223             DestinationPortRangeBuilder dprb = new DestinationPortRangeBuilder();
224             dprb.setLowerPort(new PortNumber(portLower));
225             dprb.setUpperPort(new PortNumber(portUpper));
226             aceIpBuilder.setDestinationPortRange(dprb.build());
227         }
228         if (ipv4PrefixStr != null) {
229             AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
230             Ipv4Prefix ipv4Prefix = new Ipv4Prefix(ipv4PrefixStr);
231             aceIpv4Builder.setSourceIpv4Network(ipv4Prefix);
232             aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
233         }
234         if (protocol != -1) {
235             aceIpBuilder.setProtocol(protocol);
236         }
237         MatchesBuilder matches = new MatchesBuilder();
238         matches.setAceType(aceIpBuilder.build());
239         AceBuilder aceBuilder = new AceBuilder();
240         aceBuilder.setMatches(matches.build());
241         SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
242         securityRuleAttrBuilder.setDirection(DirectionEgress.class);
243         aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
244         AccessListEntriesBuilder aleb = new AccessListEntriesBuilder();
245         aleb.setAce(Arrays.asList(aceBuilder.build()));
246         ab.setAccessListEntries(aleb.build());
247
248         InstanceIdentifier<Acl> aclKey = AclServiceUtils.getAclInstanceIdentifier(sgUuid.getValue());
249         when(mockReadTx.read(LogicalDatastoreType.CONFIGURATION, aclKey))
250             .thenReturn(Futures.immediateCheckedFuture(Optional.of(ab.build())));
251     }
252 }