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.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
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.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
84 public class ChainActionFlowsTest extends MapperUtilsTest {
\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
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
102 public void createChainTunnelFlows_directionIn() throws Exception {
\r
104 TenantBuilder tenantBuilder = buildTenant();
\r
105 Tenant tenant = tenantBuilder.build();
\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
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
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
132 NetworkElements netElements = new NetworkElements(sourceEndpoint, destinationEndpoint, sourceEgKey,
\r
133 destinationEgKey, NODE_ID, ctx);
\r
134 assertNotNull(netElements);
\r
136 ChainActionFlows.createChainTunnelFlows(nshHeader, netElements, ofWriter, ctx, HasDirection.Direction.In);
\r
138 // Verify flows and capture arguments
\r
139 verify(ofWriter, times(4)).writeFlow(nodeIdCaptor.capture(), tableIdCaptor.capture(), flowCaptor.capture());
\r
142 for (NodeId capturedNodeId : nodeIdCaptor.getAllValues()) {
\r
143 assertEquals(capturedNodeId, NODE_ID);
\r
147 List<Short> tableIds = tableIdCaptor.getAllValues();
\r
148 Short expectedTableIds[] = {4, 2, 0, 2};
\r
149 assertArrayEquals(expectedTableIds, tableIds.toArray());
\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
162 public void createChainTunnelFlows_directionOut() throws Exception {
\r
164 TenantBuilder tenantBuilder = buildTenant();
\r
165 Tenant tenant = tenantBuilder.build();
\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
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
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
193 NetworkElements netElements = new NetworkElements(sourceEndpoint, destinationEndpoint, sourceEgKey,
\r
194 destinationEgKey, NODE_ID, ctx);
\r
195 assertNotNull(netElements);
\r
197 ChainActionFlows.createChainTunnelFlows(nshHeader, netElements, ofWriter, ctx, HasDirection.Direction.Out);
\r
199 // Verify flows and capture arguments
\r
200 verify(ofWriter, times(1)).writeFlow(NODE_ID, (short) 6, createExternalTestFlow(netElements));
\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
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
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
240 assertTrue(flows.size() == 1);
\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
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
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
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
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
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
291 return flowBuilder.build();
\r