2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
\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
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
\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.rev100924.IpAddress;
\r
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.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
53 import java.math.BigInteger;
\r
54 import java.util.ArrayList;
\r
55 import java.util.List;
\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.nxLoadTunIPv4Action;
\r
79 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxLoadTunIdAction;
\r
80 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
\r
82 public class ChainActionFlowsTest extends MapperUtilsTest {
\r
85 private final ArgumentCaptor<NodeId> nodeIdCaptor = ArgumentCaptor.forClass(NodeId.class);
\r
86 private final ArgumentCaptor<Short> tableIdCaptor = ArgumentCaptor.forClass(Short.class);
\r
87 private final ArgumentCaptor<Flow> flowCaptor = ArgumentCaptor.forClass(Flow.class);
\r
90 public void init() {
\r
91 ctx = mock(OfContext.class);
\r
92 endpointManager = mock(EndpointManager.class);
\r
93 switchManager = mock(SwitchManager.class);
\r
94 policyManager = mock(PolicyManager.class);
\r
95 policyInfo = mock(PolicyInfo.class);
\r
96 ofWriter = mock(OfWriter.class);
\r
100 public void createChainTunnelFlows_directionIn() throws Exception {
\r
102 TenantBuilder tenantBuilder = buildTenant();
\r
103 Tenant tenant = tenantBuilder.build();
\r
105 EndpointBuilder sourceEndpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
\r
106 Endpoint sourceEndpoint = sourceEndpointBuilder.build();
\r
107 EgKey sourceEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_0);
\r
108 // Destination Endpoint
\r
109 EndpointBuilder destinationEndpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
\r
110 Endpoint destinationEndpoint = destinationEndpointBuilder.build();
\r
111 EgKey destinationEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_1);
\r
113 SfcNshHeaderBuilder nshHeaderBuilder = new SfcNshHeaderBuilder();
\r
114 nshHeaderBuilder.setNshNsiFromChain((short) 250);
\r
115 nshHeaderBuilder.setNshNspFromChain(27L);
\r
116 SfcNshHeader nshHeader = nshHeaderBuilder.build();
\r
118 when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
\r
119 when(ctx.getEndpointManager()).thenReturn(endpointManager);
\r
120 when(ctx.getSwitchManager()).thenReturn(switchManager);
\r
121 when(ctx.getPolicyManager()).thenReturn(policyManager);
\r
122 when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
\r
123 when(switchManager.getTunnelPort(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(CONNECTOR_2);
\r
124 when(switchManager.getTunnelIP(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(new IpAddress(IPV4_2));
\r
125 when(policyManager.getTABLEID_PORTSECURITY()).thenReturn((short) 4);
\r
126 when(policyManager.getTABLEID_SOURCE_MAPPER()).thenReturn((short) 2);
\r
129 NetworkElements netElements = new NetworkElements(sourceEndpoint, destinationEndpoint, sourceEgKey,
\r
130 destinationEgKey, NODE_ID, ctx);
\r
131 assertNotNull(netElements);
\r
133 ChainActionFlows.createChainTunnelFlows(nshHeader, netElements, ofWriter, ctx, HasDirection.Direction.In);
\r
135 // Verify flows and capture arguments
\r
136 verify(ofWriter, times(4)).writeFlow(nodeIdCaptor.capture(), tableIdCaptor.capture(), flowCaptor.capture());
\r
139 for (NodeId capturedNodeId : nodeIdCaptor.getAllValues()) {
\r
140 assertEquals(capturedNodeId, NODE_ID);
\r
144 List<Short> tableIds = tableIdCaptor.getAllValues();
\r
145 Short expectedTableIds[] = {4, 2, 0, 2};
\r
146 assertArrayEquals(expectedTableIds, tableIds.toArray());
\r
149 List<Flow> flows = flowCaptor.getAllValues();
\r
150 assertNotNull(flows);
\r
151 assertTrue(flows.size() == 4);
\r
152 assertEquals(flows.get(0), allowFromChainTestFlow());
\r
153 assertEquals(flows.get(1), createChainTunnelTestFlow(netElements).get(0)); // contains only 1 entry
\r
154 assertEquals(flows.get(2), allowFromChainTunnelTestFlow());
\r
155 assertEquals(flows.get(3), createChainBroadcastTestFlow());
\r
159 public void createChainTunnelFlows_directionOut() throws Exception {
\r
161 TenantBuilder tenantBuilder = buildTenant();
\r
162 Tenant tenant = tenantBuilder.build();
\r
164 EndpointBuilder sourceEndpointBuilder = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0);
\r
165 Endpoint sourceEndpoint = sourceEndpointBuilder.build();
\r
166 EgKey sourceEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_0);
\r
167 // Destination Endpoint
\r
168 EndpointBuilder destinationEndpointBuilder = buildEndpoint(IPV4_1, MAC_1, CONNECTOR_1);
\r
169 Endpoint destinationEndpoint = destinationEndpointBuilder.build();
\r
170 EgKey destinationEgKey = new EgKey(tenant.getId(), ENDPOINT_GROUP_1);
\r
172 SfcNshHeaderBuilder nshHeaderBuilder = new SfcNshHeaderBuilder();
\r
173 nshHeaderBuilder.setNshNsiToChain((short) 255);
\r
174 nshHeaderBuilder.setNshNspToChain(27L);
\r
175 nshHeaderBuilder.setNshTunIpDst(IPV4_2);
\r
176 SfcNshHeader nshHeader = nshHeaderBuilder.build();
\r
178 when(ctx.getTenant(any(TenantId.class))).thenReturn(getTestIndexedTenant());
\r
179 when(ctx.getEndpointManager()).thenReturn(endpointManager);
\r
180 when(ctx.getSwitchManager()).thenReturn(switchManager);
\r
181 when(ctx.getPolicyManager()).thenReturn(policyManager);
\r
182 when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
\r
183 when(switchManager.getTunnelPort(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(CONNECTOR_2);
\r
184 when(switchManager.getTunnelIP(NODE_ID, TunnelTypeVxlanGpe.class)).thenReturn(new IpAddress(IPV4_2));
\r
185 when(policyManager.getTABLEID_EXTERNAL_MAPPER()).thenReturn((short) 6);
\r
189 NetworkElements netElements = new NetworkElements(sourceEndpoint, destinationEndpoint, sourceEgKey,
\r
190 destinationEgKey, NODE_ID, ctx);
\r
191 assertNotNull(netElements);
\r
193 ChainActionFlows.createChainTunnelFlows(nshHeader, netElements, ofWriter, ctx, HasDirection.Direction.Out);
\r
195 // Verify flows and capture arguments
\r
196 verify(ofWriter, times(1)).writeFlow(NODE_ID, (short) 6, createExternalTestFlow());
\r
199 private Flow allowFromChainTestFlow() {
\r
200 MatchBuilder matchBuilder = new MatchBuilder();
\r
201 FlowUtils.addNxNshc1RegMatch(matchBuilder, 0L);
\r
202 FlowUtils.addNxNsiMatch(matchBuilder, (short) 250);
\r
203 FlowUtils.addNxNspMatch(matchBuilder, 27L);
\r
204 Match match = matchBuilder.setInPort(CONNECTOR_2).build();
\r
206 FlowId flowId = FlowIdUtils.newFlowId((short) 4, "chainport", match);
\r
207 FlowBuilder flowBuilder = new FlowBuilder().setTableId((short) 4).setBarrier(false).setHardTimeout(0)
\r
208 .setIdleTimeout(0).setId(flowId).setPriority(1200).setMatch(match)
\r
209 .setInstructions(FlowUtils.gotoTableInstructions((short) 2));
\r
210 return flowBuilder.build();
\r
213 private List<Flow> createChainTunnelTestFlow(NetworkElements networkElements) {
\r
214 Preconditions.checkNotNull(networkElements);
\r
215 List<Flow> flows = new ArrayList<>();
\r
216 Action segReg = nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1L));
\r
217 Action scgReg = nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0xffffff));
\r
218 Action bdReg = nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(0L));
\r
219 Action fdReg = nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(0L));
\r
220 Action vrfReg = nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(0L));
\r
221 for (L3Address address : networkElements.getDstEp().getL3Address()) {
\r
222 Layer3Match l3Match = new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix(address.getIpAddress()
\r
223 .getIpv4Address().getValue() + IP_PREFIX_32)).build();
\r
224 MatchBuilder mb = new MatchBuilder().setInPort(CONNECTOR_2).setLayer3Match(l3Match)
\r
225 .setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
\r
226 addNxTunIdMatch(mb, 2);
\r
227 addNxNspMatch(mb, 27L);
\r
228 addNxNsiMatch(mb, (short) 250);
\r
229 Match match = mb.build();
\r
230 FlowId flowId = FlowIdUtils.newFlowId((short) 2, "chaintunnel", match);
\r
231 FlowBuilder flowBuilder = base((short) 2).setId(flowId).setPriority(150).setMatch(match).setInstructions(
\r
232 instructions(applyActionIns(segReg, scgReg, bdReg, fdReg, vrfReg),
\r
233 gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
\r
234 flows.add(flowBuilder.build());
\r
236 assertTrue(flows.size() == 1);
\r
240 private Flow allowFromChainTunnelTestFlow() {
\r
241 MatchBuilder matchBuilder = new MatchBuilder().setInPort(CONNECTOR_2);
\r
242 addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg1.class, 0xffffffL));
\r
243 Match match = matchBuilder.build();
\r
244 FlowId flowId = FlowIdUtils.newFlowId((short) 0, "chainport", match);
\r
245 FlowBuilder flowBuilder = base((short) 0).setId(flowId).setMatch(match)
\r
246 .setPriority(65000).setInstructions(instructions(applyActionIns(nxOutputRegAction(NxmNxReg7.class))));
\r
247 return flowBuilder.build();
\r
250 private Flow createChainBroadcastTestFlow() {
\r
251 MatchBuilder matchBuilder = new MatchBuilder().setInPort(CONNECTOR_2);
\r
252 addNxNsiMatch(matchBuilder, (short) 250);
\r
253 addNxNspMatch(matchBuilder, 27L);
\r
254 addNxTunIdMatch(matchBuilder, 0);
\r
255 Match match = matchBuilder.build();
\r
256 FlowId flowId = FlowIdUtils.newFlowId((short) 2, "chainbroadcast", match);
\r
257 FlowBuilder flowBuilder = base((short) 2).setId(flowId).setPriority(150).setMatch(match)
\r
258 .setInstructions(instructions(applyActionIns(nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(0))),
\r
259 gotoTableIns(ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER())));
\r
260 return flowBuilder.build();
\r
263 private Flow createExternalTestFlow() {
\r
264 Action loadC1 = nxLoadNshc1RegAction(null);
\r
265 Action loadC2 = nxLoadNshc2RegAction(2L);
\r
266 Action loadChainTunVnId = nxLoadTunIdAction(BigInteger.valueOf(2L), false);
\r
267 Action loadChainTunDest = nxLoadTunIPv4Action(IPV4_2.getValue(), false);
\r
268 Action outputAction = FlowUtils.createActionResubmit(null, (short) 0);
\r
270 MatchBuilder matchBuilder = new MatchBuilder();
\r
271 addNxRegMatch(matchBuilder, RegMatch.of(NxmNxReg6.class, 0L));
\r
272 addNxTunIdMatch(matchBuilder, 2);
\r
273 addNxNspMatch(matchBuilder, 27L);
\r
274 addNxNsiMatch(matchBuilder, (short) 255);
\r
277 Match match = matchBuilder.build();
\r
278 FlowId flowId = FlowIdUtils.newFlowId(((short) 6), "chainexternal", match);
\r
279 FlowBuilder flowBuilder = base((short) 6).setId(flowId).setPriority(1000).setMatch(match)
\r
280 .setInstructions(instructions(applyActionIns(loadC1, loadC2, loadChainTunDest, loadChainTunVnId,
\r
282 return flowBuilder.build();
\r