/*
* Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.ingressnat;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;
import org.opendaylight.groupbasedpolicy.dto.PolicyInfo;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowIdUtils;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.*;
import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.*;
public class IngressNatMapperFlowsTest extends MapperUtilsTest {
private IngressNatMapperFlows flows;
@Before
public void init() throws Exception {
ctx = mock(OfContext.class);
ofWriter = mock(OfWriter.class);
endpointManager = mock(EndpointManager.class);
policyManager = mock(PolicyManager.class);
policyInfo = mock(PolicyInfo.class);
tableId = 1;
flows = new IngressNatMapperFlows(NODE_ID, tableId);
OrdinalFactory.resetPolicyOrdinalValue();
}
@Test
public void testBaseFlow() {
Flow testFlow = buildFlow(FlowIdUtils.newFlowId("gotoDestinationMapper"), tableId, 50, null,
FlowUtils.gotoTableInstructions((short) 2)).build();
flows.baseFlow((short) 2, 50, ofWriter);
verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
}
@Test
public void testNatFlow_noAugmentation() {
EndpointL3 testEndpointL3 = new EndpointL3Builder().build();
flows.createNatFlow((short) 3, testEndpointL3, null, 60, ofWriter);
verifyZeroInteractions(ctx);
verifyZeroInteractions(ofWriter);
}
@Test
public void testNatFlow() throws Exception {
EndpointL3 testEndpointL3 = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, null).build();
Endpoint testEndpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0).build();
when(ctx.getEndpointManager()).thenReturn(endpointManager);
when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
InOrder order = inOrder(ctx);
order.verify(ctx, times(1)).getEndpointManager();
order.verify(ctx, times(1)).getCurrentPolicy();
verify(ctx, times(3)).getTenant(TENANT_ID);
assertNotNull(ordinals);
List<Instruction> instructions = new ArrayList<>();
Action[] ipActions = {FlowUtils.setIpv4DstAction(new Ipv4Address(IPV4_1)),
FlowUtils.setDlDstAction(new MacAddress(MAC_0))};
Action[] ordinalsAction = {FlowUtils.nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1)),
FlowUtils.nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0)),
FlowUtils.nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(3)),
FlowUtils.nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(4)),
FlowUtils.nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(5)),
FlowUtils.nxLoadTunIdAction(BigInteger.valueOf(ordinals.getTunnelId()), false)};
instructions.add(new InstructionBuilder().setOrder(0)
.setInstruction(FlowUtils.applyActionIns(ArrayUtils.addAll(ipActions, ordinalsAction))).build());
instructions.add(new InstructionBuilder().setOrder(1).setInstruction(FlowUtils.gotoTableIns((short) 2)).build());
InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
instructionsBuilder.setInstruction(instructions);
MatchBuilder matchBuilder = new MatchBuilder();
matchBuilder.setLayer3Match(new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(IPV4_0.getValue() +
IP_PREFIX_32)).build());
matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
Flow testFlow = buildFlow(new FlowId("IngressNat" + "|" + new IpAddress(new Ipv4Address(IPV4_0)).toString() +
"|" + new IpAddress(new Ipv4Address(IPV4_1)).toString() + "|" + new MacAddress(MAC_0)), tableId,
60, matchBuilder.build(), instructionsBuilder.build()).build();
flows.createNatFlow((short) 2, testEndpointL3, ordinals, 60, ofWriter);
verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
}
@Test
public void testArpFlow_noAugmentation() {
EndpointL3 testEndpointL3 = new EndpointL3Builder().build();
flows.createArpFlow(getTestIndexedTenant(), testEndpointL3, 60, ofWriter);
verifyZeroInteractions(ctx);
verifyZeroInteractions(ofWriter);
}
@Test
public void testArpFlow() {
EndpointL3 testEndpointL3 = buildL3Endpoint(IPV4_0, IPV4_1, MAC_0, null).build();
List<Instruction> instructions = new ArrayList<>();
Action[] arpActions = {nxMoveEthSrcToEthDstAction(), setDlSrcAction(new MacAddress(MAC_0)),
nxLoadArpOpAction(BigInteger.valueOf(2L)), nxMoveArpShaToArpThaAction(), nxLoadArpShaAction(new BigInteger("0")),
nxMoveArpSpaToArpTpaAction(), nxLoadArpSpaAction(IPV4_0.getValue()), outputAction(new NodeConnectorId(NODE_ID.getValue() + ":INPORT"))};
instructions.add(new InstructionBuilder().setOrder(0)
.setInstruction(FlowUtils.applyActionIns(ArrayUtils.addAll(arpActions))).build());
InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
instructionsBuilder.setInstruction(instructions);
MatchBuilder matchBuilder = new MatchBuilder();
matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.ARP));
matchBuilder.setLayer3Match(new ArpMatchBuilder().setArpOp(1).setArpTargetTransportAddress(new Ipv4Prefix(IPV4_0.getValue()
+ IP_PREFIX_32)).build());
Match match = matchBuilder.build();
Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "outside-ip-arp", match),
tableId, 60, match, instructionsBuilder.build()).build();
flows.createArpFlow(getTestIndexedTenant(), testEndpointL3, 60, ofWriter);
verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
}
@Test
public void testIngressExternalNatFlow() throws Exception {
Endpoint testEndpoint = buildEndpoint(IPV4_1, MAC_0, CONNECTOR_0).build();
when(ctx.getEndpointManager()).thenReturn(endpointManager);
when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
InOrder order = inOrder(ctx);
order.verify(ctx, times(1)).getEndpointManager();
order.verify(ctx, times(1)).getCurrentPolicy();
verify(ctx, times(3)).getTenant(TENANT_ID);
assertNotNull(ordinals);
List<Instruction> instructions = new ArrayList<>();
Action[] ordinalsAction = {FlowUtils.nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1)),
FlowUtils.nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0)),
FlowUtils.nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(3)),
FlowUtils.nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(4)),
FlowUtils.nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(5)),
FlowUtils.nxLoadTunIdAction(BigInteger.valueOf(ordinals.getTunnelId()), false)};
instructions.add(new InstructionBuilder().setOrder(0)
.setInstruction(FlowUtils.applyActionIns(ArrayUtils.addAll(ordinalsAction))).build());
instructions.add(new InstructionBuilder().setOrder(1).setInstruction(FlowUtils.gotoTableIns((short) 2)).build());
InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
instructionsBuilder.setInstruction(instructions);
MatchBuilder matchBuilder = new MatchBuilder();
matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(null, null, FlowUtils.IPv4));
matchBuilder.setLayer3Match(new Ipv4MatchBuilder().setIpv4Source(new Ipv4Prefix(IPV4_1.getValue()
+ IP_PREFIX_32)).build());
Match match = matchBuilder.build();
Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "inbound-external-ip", match), tableId, 50, match,
instructionsBuilder.build()).build();
flows.createIngressExternalNatFlows((short) 2, testEndpoint, ordinals, 50, ofWriter);
verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
}
@Test
public void testIngressExternalArpFlow() throws Exception {
Endpoint testEndpoint = buildEndpoint(IPV4_0, MAC_0, CONNECTOR_0).build();
when(ctx.getEndpointManager()).thenReturn(endpointManager);
when(ctx.getTenant(Mockito.any(TenantId.class))).thenReturn(getTestIndexedTenant());
when(ctx.getCurrentPolicy()).thenReturn(policyInfo);
OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, testEndpoint);
InOrder order = inOrder(ctx);
order.verify(ctx, times(1)).getEndpointManager();
order.verify(ctx, times(1)).getCurrentPolicy();
verify(ctx, times(3)).getTenant(TENANT_ID);
assertNotNull(ordinals);
List<Instruction> instructions = new ArrayList<>();
Action[] ordinalsAction = {FlowUtils.nxLoadRegAction(NxmNxReg0.class, BigInteger.valueOf(1)),
FlowUtils.nxLoadRegAction(NxmNxReg1.class, BigInteger.valueOf(0)),
FlowUtils.nxLoadRegAction(NxmNxReg4.class, BigInteger.valueOf(3)),
FlowUtils.nxLoadRegAction(NxmNxReg5.class, BigInteger.valueOf(4)),
FlowUtils.nxLoadRegAction(NxmNxReg6.class, BigInteger.valueOf(5)),
FlowUtils.nxLoadTunIdAction(BigInteger.valueOf(ordinals.getTunnelId()), false)};
instructions.add(new InstructionBuilder().setOrder(0)
.setInstruction(FlowUtils.applyActionIns(ArrayUtils.addAll(ordinalsAction))).build());
instructions.add(new InstructionBuilder().setOrder(1).setInstruction(FlowUtils.gotoTableIns((short) 0)).build());
InstructionsBuilder instructionsBuilder = new InstructionsBuilder();
instructionsBuilder.setInstruction(instructions);
MatchBuilder matchBuilder = new MatchBuilder();
matchBuilder.setEthernetMatch(FlowUtils.ethernetMatch(new MacAddress(MAC_0), null, FlowUtils.ARP));
Match match = matchBuilder.build();
Flow testFlow = buildFlow(FlowIdUtils.newFlowId(tableId, "inbound-external-arp", match), tableId, 30, match,
instructionsBuilder.build()).build();
flows.createIngressExternalArpFlows((short) 0, testEndpoint, ordinals, 30, ofWriter);
verify(ofWriter, times(1)).writeFlow(NODE_ID, tableId, testFlow);
}
}