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