Support new actions in new ovs nsh patches
[groupbasedpolicy.git] / renderers / ofoverlay / src / test / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / ChainActionFlowsTest.java
1 /*\r
2  * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;\r
10 \r
11 import com.google.common.base.Preconditions;\r
12 import org.junit.Before;\r
13 import org.junit.Test;\r
14 import org.mockito.ArgumentCaptor;\r
15 import org.mockito.Captor;\r
16 import org.opendaylight.groupbasedpolicy.dto.EgKey;\r
17 import org.opendaylight.groupbasedpolicy.dto.PolicyInfo;\r
18 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;\r
19 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;\r
20 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;\r
21 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;\r
22 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;\r
23 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.policyenforcer.NetworkElements;\r
24 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;\r
25 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcNshHeader;\r
26 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.sfcutils.SfcNshHeader.SfcNshHeaderBuilder;\r
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;\r
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;\r
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;\r
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;\r
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;\r
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;\r
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.TenantBuilder;\r
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;\r
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;\r
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;\r
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;\r
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;\r
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;\r
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;\r
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;\r
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlanGpe;\r
52 \r
53 import java.math.BigInteger;\r
54 import java.util.ArrayList;\r
55 import java.util.List;\r
56 \r
57 import static org.junit.Assert.assertArrayEquals;\r
58 import static org.junit.Assert.assertEquals;\r
59 import static org.junit.Assert.assertNotNull;\r
60 import static org.junit.Assert.assertTrue;\r
61 import static org.mockito.Mockito.any;\r
62 import static org.mockito.Mockito.mock;\r
63 import static org.mockito.Mockito.times;\r
64 import static org.mockito.Mockito.verify;\r
65 import static org.mockito.Mockito.when;\r
66 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;\r
67 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxNsiMatch;\r
68 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxNspMatch;\r
69 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxRegMatch;\r
70 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.addNxTunIdMatch;\r
71 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.applyActionIns;\r
72 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.base;\r
73 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.gotoTableIns;\r
74 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.instructions;\r
75 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc1RegAction;\r
76 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadNshc2RegAction;\r
77 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadRegAction;\r
78 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunGpeNpAction;\r
79 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIPv4Action;\r
80 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;\r
81 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;\r
82 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxPopNshAction;\r
83 \r
84 public class ChainActionFlowsTest extends MapperUtilsTest {\r
85 \r
86     @Captor\r
87     private final ArgumentCaptor<NodeId> nodeIdCaptor = ArgumentCaptor.forClass(NodeId.class);\r
88     private final ArgumentCaptor<Short> tableIdCaptor = ArgumentCaptor.forClass(Short.class);\r
89     private final ArgumentCaptor<Flow> flowCaptor = ArgumentCaptor.forClass(Flow.class);\r
90 \r
91     @Before\r
92     public void init() {\r
93         ctx = mock(OfContext.class);\r
94         endpointManager = mock(EndpointManager.class);\r
95         switchManager = mock(SwitchManager.class);\r
96         policyManager = mock(PolicyManager.class);\r
97         policyInfo = mock(PolicyInfo.class);\r
98         ofWriter = mock(OfWriter.class);\r
99     }\r
100 \r
101     @Test\r
102     public void createChainTunnelFlows_directionIn() throws Exception {\r
103         // Tenant\r
104         TenantBuilder tenantBuilder = buildTenant();\r
105         Tenant tenant = tenantBuilder.build();\r
106         // Source Endpoint\r
107         EndpointBuilder sourceEndpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);\r
108         Endpoint sourceEndpoint = sourceEndpointBuilder.build();\r
109         EgKey sourceEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_0);\r
110         // Destination Endpoint\r
111         EndpointBuilder destinationEndpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);\r
112         Endpoint destinationEndpoint = destinationEndpointBuilder.build();\r
113         EgKey destinationEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_1);\r
114         // Nsh header\r
115         SfcNshHeaderBuilder nshHeaderBuilder = new SfcNshHeaderBuilder();\r
116         nshHeaderBuilder.setNshMetaC1(Long.valueOf(0L));\r
117         nshHeaderBuilder.setNshNsiFromChain((short) 250);\r
118         nshHeaderBuilder.setNshNspFromChain(27L);\r
119         SfcNshHeader nshHeader = nshHeaderBuilder.build();\r
120 \r
121         when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());\r
122         when(ctx.getEndpointManager()).thenReturn(endpointManager);\r
123         when(ctx.getSwitchManager()).thenReturn(switchManager);\r
124         when(ctx.getPolicyManager()).thenReturn(policyManager);\r
125         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);\r
126         when(switchManager.getTunnelPort(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(CONNECTOR_2);\r
127         when(switchManager.getTunnelIP(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(new IpAddress(IPV4_2));\r
128         when(policyManager.getTABLEID_PORTSECURITY()).thenReturn((short) 4);\r
129         when(policyManager.getTABLEID_SOURCE_MAPPER()).thenReturn((short) 2);\r
130 \r
131         // Net elements\r
132         NetworkElements netElements = new NetworkElements(sourceEndpoint, destinationEndpoint, sourceEgKey,\r
133                 destinationEgKey, NODE_ID, ctx);\r
134         assertNotNull(netElements);\r
135 \r
136         ChainActionFlows.createChainTunnelFlows(nshHeader, netElements, ofWriter, ctx, HasDirection.Direction.In);\r
137 \r
138         // Verify flows and capture arguments\r
139         verify(ofWriter, times(4)).writeFlow(nodeIdCaptor.capture(), tableIdCaptor.capture(), flowCaptor.capture());\r
140 \r
141         // Verify nodeIds\r
142         for (NodeId capturedNodeId : nodeIdCaptor.getAllValues()) {\r
143             assertEquals(capturedNodeId, NODE_ID);\r
144         }\r
145 \r
146         // Verify tableIds\r
147         List<Short> tableIds = tableIdCaptor.getAllValues();\r
148         Short expectedTableIds[] = {4, 2, 0, 2};\r
149         assertArrayEquals(expectedTableIds, tableIds.toArray());\r
150 \r
151         // Verify flows\r
152         List<Flow> flows = flowCaptor.getAllValues();\r
153         assertNotNull(flows);\r
154         assertTrue(flows.size() == 4);\r
155         assertEquals(flows.get(0), allowFromChainTestFlow());\r
156         assertEquals(flows.get(1), createChainTunnelTestFlow(netElements).get(0)); // contains only 1 entry\r
157         assertEquals(flows.get(2), allowFromChainTunnelTestFlow());\r
158         assertEquals(flows.get(3), createChainBroadcastTestFlow());\r
159     }\r
160 \r
161     @Test\r
162     public void createChainTunnelFlows_directionOut() throws Exception {\r
163         // Tenant\r
164         TenantBuilder tenantBuilder = buildTenant();\r
165         Tenant tenant = tenantBuilder.build();\r
166         // Source Endpoint\r
167         EndpointBuilder sourceEndpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);\r
168         Endpoint sourceEndpoint = sourceEndpointBuilder.build();\r
169         EgKey sourceEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_0);\r
170         // Destination Endpoint\r
171         EndpointBuilder destinationEndpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);\r
172         Endpoint destinationEndpoint = destinationEndpointBuilder.build();\r
173         EgKey destinationEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_1);\r
174         // Nsh header\r
175         SfcNshHeaderBuilder nshHeaderBuilder = new SfcNshHeaderBuilder();\r
176         nshHeaderBuilder.setNshMetaC1(Long.valueOf(0L));\r
177         nshHeaderBuilder.setNshNsiToChain((short) 255);\r
178         nshHeaderBuilder.setNshNspToChain(27L);\r
179         nshHeaderBuilder.setNshTunIpDst(IPV4_2);\r
180         SfcNshHeader nshHeader = nshHeaderBuilder.build();\r
181 \r
182         when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());\r
183         when(ctx.getEndpointManager()).thenReturn(endpointManager);\r
184         when(ctx.getSwitchManager()).thenReturn(switchManager);\r
185         when(ctx.getPolicyManager()).thenReturn(policyManager);\r
186         when(ctx.getCurrentPolicy()).thenReturn(policyInfo);\r
187         when(switchManager.getTunnelPort(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(CONNECTOR_2);\r
188         when(switchManager.getTunnelIP(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(new IpAddress(IPV4_2));\r
189         when(policyManager.getTABLEID_EXTERNAL_MAPPER()).thenReturn((short) 6);\r
190 \r
191 \r
192         // Net elements\r
193         NetworkElements netElements = new NetworkElements(sourceEndpoint, destinationEndpoint, sourceEgKey,\r
194                 destinationEgKey, NODE_ID, ctx);\r
195         assertNotNull(netElements);\r
196 \r
197         ChainActionFlows.createChainTunnelFlows(nshHeader, netElements, ofWriter, ctx, HasDirection.Direction.Out);\r
198 \r
199         // Verify flows and capture arguments\r
200         verify(ofWriter, times(1)).writeFlow(NODE_ID, (short) 6, createExternalTestFlow(netElements));\r
201     }\r
202 \r
203     private Flow allowFromChainTestFlow() {\r
204         MatchBuilder matchBuilder = new MatchBuilder();\r
205         FlowUtils.addNxNshc1RegMatch(matchBuilder, 0L);\r
206         FlowUtils.addNxNsiMatch(matchBuilder, (short) 250);\r
207         FlowUtils.addNxNspMatch(matchBuilder, 27L);\r
208         Match match = matchBuilder.setInPort(CONNECTOR_2).build();\r
209 \r
210         FlowId flowId = FlowIdUtils.newFlowId((short) 4, "chainport", match);\r
211         FlowBuilder flowBuilder = new FlowBuilder().setTableId((short) 4).setBarrier(false).setHardTimeout(0)\r
212                 .setIdleTimeout(0).setId(flowId).setPriority(1200).setMatch(match)\r
213                 .setInstructions(FlowUtils.gotoTableInstructions((short) 2));\r
214         return flowBuilder.build();\r
215     }\r
216 \r
217     private List<Flow> createChainTunnelTestFlow(NetworkElements networkElements) {\r
218         Preconditions.checkNotNull(networkElements);\r
219         List<Flow> flows = new ArrayList<>();\r
220         Action segReg = nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1L));\r
221         Action scgReg = nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0xffffff));\r
222         Action bdReg = nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(3L));\r
223         Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(4L));\r
224         Action vrfReg = nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(5L));\r
225         for (L3Address address : networkElements.getDstEp().getL3Address()) {\r
226             Layer3Match l3Match = new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix(address.getIpAddress()\r
227                     .getIpv4Address().getValue() + IP_PREFIX_32)).build();\r
228             MatchBuilder mb = new MatchBuilder().setInPort(CONNECTOR_2).setLayer3Match(l3Match)\r
229                     .setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));\r
230             addNxTunIdMatch(mb, networkElements.getSrcEpOrdinals().getTunnelId());\r
231             addNxNspMatch(mb, 27L);\r
232             addNxNsiMatch(mb, (short) 250);\r
233             Match match = mb.build();\r
234             FlowId flowId = FlowIdUtils.newFlowId((short) 2, "chaintunnel", match);\r
235             FlowBuilder flowBuilder = base((short) 2).setId(flowId).setPriority(150).setMatch(match).setInstructions(\r
236                     instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg),\r
237                             gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));\r
238             flows.add(flowBuilder.build());\r
239         }\r
240         assertTrue(flows.size() == 1);\r
241         return flows;\r
242     }\r
243 \r
244     private Flow allowFromChainTunnelTestFlow() {\r
245         MatchBuilder matchBuilder = new MatchBuilder().setInPort(CONNECTOR_2);\r
246         addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg1.class, 0xffffffL));\r
247         Match match = matchBuilder.build();\r
248         FlowId flowId = FlowIdUtils.newFlowId((short) 0, "chainport", match);\r
249         FlowBuilder flowBuilder = base((short) 0).setId(flowId).setMatch(match)\r
250                 .setPriority(65000).setInstructions(instructions(applyActionIns(nxPopNshAction(), nxOutputRegAction(NxmNxReg7.class))));\r
251         return flowBuilder.build();\r
252     }\r
253 \r
254     private Flow createChainBroadcastTestFlow() {\r
255         MatchBuilder matchBuilder = new MatchBuilder().setInPort(CONNECTOR_2);\r
256         addNxNsiMatch(matchBuilder, (short) 250);\r
257         addNxNspMatch(matchBuilder, 27L);\r
258         addNxTunIdMatch(matchBuilder, 4);\r
259         Match match = matchBuilder.build();\r
260         FlowId flowId = FlowIdUtils.newFlowId((short) 2, "chainbroadcast", match);\r
261         FlowBuilder flowBuilder = base((short) 2).setId(flowId).setPriority(150).setMatch(match)\r
262                 .setInstructions(instructions(applyActionIns(nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(4))),\r
263                         gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));\r
264         return flowBuilder.build();\r
265     }\r
266 \r
267     private Flow createExternalTestFlow(NetworkElements networkElements) {\r
268         int matchTunnelId = networkElements.getSrcEpOrdinals().getTunnelId();\r
269         long setTunnelId = networkElements.getDstEpOrdinals().getTunnelId();\r
270         final short TUN_GPE_NP_NSH = 0x4;\r
271 \r
272         Action loadC1 = nxLoadNshc1RegAction(Long.valueOf(0));\r
273         Action loadC2 = nxLoadNshc2RegAction(setTunnelId);\r
274         Action loadChainTunVnId = nxLoadTunIdAction(BigInteger.valueOf(setTunnelId), false);\r
275         Action loadChainTunDest = nxLoadTunIPv4Action(IPV4_2.getValue(), false);\r
276         Action loadTunGpeNp = nxLoadTunGpeNpAction(BigInteger.valueOf(TUN_GPE_NP_NSH), false);\r
277         Action outputAction = FlowUtils.createActionResubmit(null, (short) 0);\r
278 \r
279         MatchBuilder matchBuilder = new MatchBuilder();\r
280         addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, 5L));\r
281         addNxTunIdMatch(matchBuilder, matchTunnelId);\r
282         addNxNspMatch(matchBuilder, 27L);\r
283         addNxNsiMatch(matchBuilder, (short) 255);\r
284 \r
285 \r
286         Match match = matchBuilder.build();\r
287         FlowId flowId = FlowIdUtils.newFlowId(((short) 6), "chainexternal", match);\r
288         FlowBuilder flowBuilder = base((short) 6).setId(flowId).setPriority(1000).setMatch(match)\r
289                 .setInstructions(instructions(applyActionIns(loadC1, loadC2, loadChainTunDest, loadChainTunVnId, loadTunGpeNp,\r
290                         outputAction)));\r
291         return flowBuilder.build();\r
292     }\r
293 }\r