2ce69efde16bf152dc02a52cb7d3c8306eea9d23
[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.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.Ignore;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.Mock;
25 import org.mockito.runners.MockitoJUnitRunner;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
28 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.genius.mdsalutil.ActionType;
31 import org.opendaylight.genius.mdsalutil.FlowEntity;
32 import org.opendaylight.genius.mdsalutil.MatchFieldType;
33 import org.opendaylight.genius.mdsalutil.NwConstants;
34 import org.opendaylight.genius.mdsalutil.NxMatchFieldType;
35 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
36 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
37 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
38 import org.opendaylight.netvirt.aclservice.utils.AclServiceTestUtils;
39 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
40 import org.opendaylight.netvirt.aclservice.utils.MethodInvocationParamSaver;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.Ipv4Acl;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclBuilder;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.AclKey;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntriesBuilder;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceBuilder;
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.MatchesBuilder;
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.AceIpBuilder;
49 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;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160218.acl.transport.header.fields.DestinationPortRangeBuilder;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.config.rev160806.AclserviceConfig;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.IpPrefixOrAddress;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttrBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairsBuilder;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62
63 @RunWith(MockitoJUnitRunner.class)
64 public class LearnEgressAclServiceImplTest {
65
66     LearnEgressAclServiceImpl testedService;
67
68     @Mock DataBroker dataBroker;
69     @Mock IMdsalApiManager mdsalManager;
70     @Mock WriteTransaction mockWriteTx;
71     @Mock ReadOnlyTransaction mockReadTx;
72     @Mock AclserviceConfig config;
73
74     MethodInvocationParamSaver<Void> installFlowValueSaver = null;
75     MethodInvocationParamSaver<Void> removeFlowValueSaver = null;
76
77     @Before
78     public void setUp() {
79         AclDataUtil aclDataUtil = new AclDataUtil();
80         AclServiceUtils aclServiceUtils = new AclServiceUtils(aclDataUtil, config);
81         testedService = new LearnEgressAclServiceImpl(dataBroker, mdsalManager, aclDataUtil, aclServiceUtils);
82         doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
83         doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
84         doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
85         installFlowValueSaver = new MethodInvocationParamSaver<>(null);
86         doAnswer(installFlowValueSaver).when(mdsalManager).installFlow(any(FlowEntity.class));
87         removeFlowValueSaver = new MethodInvocationParamSaver<>(null);
88         doAnswer(installFlowValueSaver).when(mdsalManager).removeFlow(any(FlowEntity.class));
89
90     }
91
92     @Test
93     public void addAcl__NullInterface() {
94         assertEquals(false, testedService.applyAcl(null));
95     }
96
97     @Test
98     public void addAcl__MissingInterfaceStateShouldFail() throws Exception {
99         AclInterface ai = new AclInterface();
100         ai.setPortSecurityEnabled(true);
101         ai.setDpId(BigInteger.ONE);
102         assertEquals(false, testedService.applyAcl(ai));
103     }
104
105     @Test
106     public void addAcl__SinglePort() throws Exception {
107         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
108         AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
109         assertEquals(true, testedService.applyAcl(ai));
110         assertEquals(7, installFlowValueSaver.getNumOfInvocations());
111
112         FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(6).get(0);
113         AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
114                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
115         AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
116                 ActionType.learn);
117
118     }
119
120     @Test
121     public void addAcl__AllowAll() throws Exception {
122         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
123         AclInterface ai = stubAllowAllInterface(sgUuid, "if_name");
124         assertEquals(true, testedService.applyAcl(ai));
125         assertEquals(7, installFlowValueSaver.getNumOfInvocations());
126
127         FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(6).get(0);
128         AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
129                 ActionType.learn);
130     }
131
132     @Test
133     public void addAcl__MultipleRanges() throws Exception {
134         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
135         AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 84);
136         assertEquals(true, testedService.applyAcl(ai));
137         assertEquals(8, installFlowValueSaver.getNumOfInvocations());
138         FlowEntity firstRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(6).get(0);
139         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
140                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65532");
141
142         FlowEntity secondRangeFlow = (FlowEntity) installFlowValueSaver.getInvocationParams(7).get(0);
143         AclServiceTestUtils.verifyMatchInfo(secondRangeFlow.getMatchInfoList(),
144                 NxMatchFieldType.nx_tcp_dst_with_mask, "84", "65535");
145     }
146
147     @Test
148     public void addAcl__UdpSinglePortShouldNotCreateSynRule() throws Exception {
149         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
150         AclInterface ai = stubUdpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
151         assertEquals(true, testedService.applyAcl(ai));
152         assertEquals(7, installFlowValueSaver.getNumOfInvocations());
153         FlowEntity flow = (FlowEntity) installFlowValueSaver.getInvocationParams(6).get(0);
154         AclServiceTestUtils.verifyMatchInfo(flow.getMatchInfoList(),
155                 NxMatchFieldType.nx_udp_dst_with_mask, "80", "65535");
156         AclServiceTestUtils.verifyActionTypeExist(flow.getInstructionInfoList().get(0).getActionInfos(),
157                 ActionType.learn);
158     }
159
160     @Test
161     @Ignore
162     public void removeAcl__SinglePort() throws Exception {
163         Uuid sgUuid = new Uuid("12345678-1234-1234-1234-123456789012");
164         AclInterface ai = stubTcpAclInterface(sgUuid, "if_name", "1.1.1.1/32", 80, 80);
165         assertEquals(true, testedService.removeAcl(ai));
166         assertEquals(5, removeFlowValueSaver.getNumOfInvocations());
167         FlowEntity firstRangeFlow = (FlowEntity) removeFlowValueSaver.getInvocationParams(4).get(0);
168         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(), MatchFieldType.tcp_flags, "2");
169         AclServiceTestUtils.verifyMatchInfo(firstRangeFlow.getMatchInfoList(),
170                 NxMatchFieldType.nx_tcp_dst_with_mask, "80", "65535");
171
172     }
173
174     private AclInterface stubUdpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
175             int tcpPortLower, int tcpPortUpper) {
176         AclInterface ai = new AclInterface();
177         ai.setPortSecurityEnabled(true);
178         ai.setSecurityGroups(Arrays.asList(sgUuid));
179         ai.setDpId(BigInteger.ONE);
180         ai.setLPortTag(new Integer(2));
181         stubInterfaceAcl(ifName, ai);
182
183         stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_UDP);
184         return ai;
185     }
186
187     private AclInterface stubTcpAclInterface(Uuid sgUuid, String ifName, String ipv4PrefixStr,
188             int tcpPortLower, int tcpPortUpper) {
189         AclInterface ai = new AclInterface();
190         ai.setPortSecurityEnabled(true);
191         ai.setDpId(BigInteger.ONE);
192         ai.setLPortTag(Integer.valueOf(2));
193         ai.setSecurityGroups(Arrays.asList(sgUuid));
194         stubInterfaceAcl(ifName, ai);
195
196         stubAccessList(sgUuid, ipv4PrefixStr, tcpPortLower, tcpPortUpper, (short)NwConstants.IP_PROT_TCP);
197         return ai;
198     }
199
200     private void stubInterfaceAcl(String ifName, AclInterface ai) {
201         AllowedAddressPairsBuilder aapb = new AllowedAddressPairsBuilder();
202         aapb.setIpAddress(new IpPrefixOrAddress("1.1.1.1/32".toCharArray()));
203         aapb.setMacAddress(new MacAddress("AA:BB:CC:DD:EE:FF"));
204         ai.setAllowedAddressPairs(Arrays.asList(aapb.build()));
205     }
206
207     private AclInterface stubAllowAllInterface(Uuid sgUuid, String ifName) {
208         AclInterface ai = new AclInterface();
209         ai.setPortSecurityEnabled(true);
210         ai.setSecurityGroups(Arrays.asList(sgUuid));
211         ai.setDpId(BigInteger.ONE);
212         ai.setLPortTag(new Integer(2));
213         stubInterfaceAcl(ifName, ai);
214
215         stubAccessList(sgUuid, null, -1, -1, (short)-1);
216         return ai;
217     }
218
219     private void stubAccessList(Uuid sgUuid, String ipv4PrefixStr, int portLower, int portUpper, short protocol) {
220         AclBuilder ab = new AclBuilder();
221         ab.setAclName("AAA");
222         ab.setKey(new AclKey(sgUuid.getValue(),Ipv4Acl.class));
223
224         AceIpBuilder aceIpBuilder = new AceIpBuilder();
225         if (portLower != -1 && portUpper != -1) {
226             DestinationPortRangeBuilder dprb = new DestinationPortRangeBuilder();
227             dprb.setLowerPort(new PortNumber(portLower));
228             dprb.setUpperPort(new PortNumber(portUpper));
229             aceIpBuilder.setDestinationPortRange(dprb.build());
230         }
231         if (ipv4PrefixStr != null) {
232             AceIpv4Builder aceIpv4Builder = new AceIpv4Builder();
233             Ipv4Prefix ipv4Prefix = new Ipv4Prefix(ipv4PrefixStr);
234             aceIpv4Builder.setSourceIpv4Network(ipv4Prefix);
235             aceIpBuilder.setAceIpVersion(aceIpv4Builder.build());
236         }
237         if (protocol != -1) {
238             aceIpBuilder.setProtocol(protocol);
239         }
240         MatchesBuilder matches = new MatchesBuilder();
241         matches.setAceType(aceIpBuilder.build());
242         AceBuilder aceBuilder = new AceBuilder();
243         aceBuilder.setMatches(matches.build());
244         SecurityRuleAttrBuilder securityRuleAttrBuilder = new SecurityRuleAttrBuilder();
245         securityRuleAttrBuilder.setDirection(DirectionEgress.class);
246         aceBuilder.addAugmentation(SecurityRuleAttr.class, securityRuleAttrBuilder.build());
247         AccessListEntriesBuilder aleb = new AccessListEntriesBuilder();
248         aleb.setAce(Arrays.asList(aceBuilder.build()));
249         ab.setAccessListEntries(aleb.build());
250
251         InstanceIdentifier<Acl> aclKey = AclServiceUtils.getAclInstanceIdentifier(sgUuid.getValue());
252         when(mockReadTx.read(LogicalDatastoreType.CONFIGURATION, aclKey))
253             .thenReturn(Futures.immediateCheckedFuture(Optional.of(ab.build())));
254     }
255 }