blob: 9c04d8f931eebad40c861940901d3f0fbed2ad2e [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.pipelines.fabric.pipeliner;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onlab.packet.UDP;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.pipelines.fabric.FabricConstants;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test cases for fabric.p4 pipeline forwarding control block.
*/
public class FabricForwardingPipelineTest extends FabricPipelinerTest {
private ForwardingObjectiveTranslator translator;
@Before
public void setup() {
super.doSetup();
translator = new ForwardingObjectiveTranslator(DEVICE_ID, capabilitiesHashed);
}
/**
* Test versatile flag of forwarding objective with ARP match.
*/
@Test
public void testAclArp() {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.punt()
.build();
// ARP
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_ARP)
.build();
ForwardingObjective fwd = DefaultForwardingObjective.builder()
.withSelector(selector)
.withPriority(PRIORITY)
.fromApp(APP_ID)
.makePermanent()
.withFlag(ForwardingObjective.Flag.VERSATILE)
.withTreatment(treatment)
.add();
ObjectiveTranslation result = translator.translate(fwd);
List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
assertEquals(1, flowRulesInstalled.size());
assertTrue(groupsInstalled.isEmpty());
FlowRule actualFlowRule = flowRulesInstalled.get(0);
PiAction piAction = PiAction.builder()
.withId(FabricConstants.FABRIC_INGRESS_ACL_CLONE_TO_CPU)
.build();
FlowRule expectedFlowRule = DefaultFlowRule.builder()
.forDevice(DEVICE_ID)
.forTable(FabricConstants.FABRIC_INGRESS_ACL_ACL)
.withPriority(PRIORITY)
.makePermanent()
.withSelector(selector)
.withTreatment(DefaultTrafficTreatment.builder()
.piTableAction(piAction).build())
.fromApp(APP_ID)
.build();
assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
}
/**
* Test versatile flag of forwarding objective with DHCP match.
*/
@Test
public void testAclDhcp() {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.wipeDeferred()
.punt()
.build();
// DHCP
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPProtocol(IPv4.PROTOCOL_UDP)
.matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT))
.matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
.build();
ForwardingObjective fwd = DefaultForwardingObjective.builder()
.withSelector(selector)
.withPriority(PRIORITY)
.fromApp(APP_ID)
.makePermanent()
.withFlag(ForwardingObjective.Flag.VERSATILE)
.withTreatment(treatment)
.add();
ObjectiveTranslation result = translator.translate(fwd);
List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
assertEquals(1, flowRulesInstalled.size());
assertTrue(groupsInstalled.isEmpty());
FlowRule actualFlowRule = flowRulesInstalled.get(0);
PiAction piAction = PiAction.builder()
.withId(FabricConstants.FABRIC_INGRESS_ACL_PUNT_TO_CPU)
.build();
FlowRule expectedFlowRule = DefaultFlowRule.builder()
.forDevice(DEVICE_ID)
.forTable(FabricConstants.FABRIC_INGRESS_ACL_ACL)
.withPriority(PRIORITY)
.makePermanent()
.withSelector(selector)
.withTreatment(DefaultTrafficTreatment.builder()
.piTableAction(piAction).build())
.fromApp(APP_ID)
.build();
assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
}
/**
* Test programming L2 unicast rule to bridging table.
*/
@Test
public void testL2Unicast() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchVlanId(VLAN_100)
.matchEthDst(HOST_MAC)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING,
buildExpectedSelector(selector), selector, NEXT_ID_1);
}
@Test
public void testL2Broadcast() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchVlanId(VLAN_100)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING,
selector, selector, NEXT_ID_1);
}
@Test
public void testIPv4Unicast() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(IPV4_UNICAST_ADDR)
.build();
TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
.matchIPDst(IPV4_UNICAST_ADDR)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4,
expectedSelector, selector, NEXT_ID_1);
}
@Test
public void testIPv4UnicastWithNoNextId() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(IPV4_UNICAST_ADDR)
.build();
TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
.matchIPDst(IPV4_UNICAST_ADDR)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4,
expectedSelector, selector, null);
}
@Test
@Ignore
public void testIPv4Multicast() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchVlanId(VLAN_100)
.matchIPDst(IPV4_MCAST_ADDR)
.build();
TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
.matchIPDst(IPV4_MCAST_ADDR)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4,
expectedSelector, selector, NEXT_ID_1);
}
@Test
@Ignore
public void testIPv6Unicast() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV6)
.matchIPDst(IPV6_UNICAST_ADDR)
.build();
TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
.matchIPDst(IPV6_UNICAST_ADDR)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V6,
expectedSelector, selector, NEXT_ID_1);
}
@Test
@Ignore
public void testIPv6Multicast() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV6)
.matchVlanId(VLAN_100)
.matchIPDst(IPV6_MCAST_ADDR)
.build();
TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
.matchIPDst(IPV6_MCAST_ADDR)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V6,
expectedSelector, selector, NEXT_ID_1);
}
@Test
public void testMpls() throws FabricPipelinerException {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.MPLS_UNICAST)
.matchMplsLabel(MPLS_10)
.matchMplsBos(true)
.build();
TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
.matchMplsLabel(MPLS_10)
.build();
PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID, NEXT_ID_1);
PiAction setNextIdAction = PiAction.builder()
.withId(FabricConstants.FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT)
.withParameter(nextIdParam)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.piTableAction(setNextIdAction)
.build();
testSpecificForward(FabricConstants.FABRIC_INGRESS_FORWARDING_MPLS,
expectedSelector, selector, NEXT_ID_1, treatment);
}
private void testSpecificForward(PiTableId expectedTableId, TrafficSelector expectedSelector,
TrafficSelector selector, Integer nextId) throws FabricPipelinerException {
TrafficTreatment setNextIdTreatment;
if (nextId == null) {
// Ref: RoutingRulePopulator.java->revokeIpRuleForRouter
setNextIdTreatment = DefaultTrafficTreatment.builder().
piTableAction(PiAction.builder()
.withId(FabricConstants.FABRIC_INGRESS_FORWARDING_NOP_ROUTING_V4)
.build())
.build();
} else {
PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID, nextId);
PiAction.Builder setNextIdAction = PiAction.builder()
.withParameter(nextIdParam);
if (expectedTableId.equals(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING)) {
setNextIdAction.withId(FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING);
} else if (expectedTableId.equals(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4)) {
setNextIdAction.withId(FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V4);
} else if (expectedTableId.equals(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V6)) {
setNextIdAction.withId(FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V6);
}
setNextIdTreatment = DefaultTrafficTreatment.builder()
.piTableAction(setNextIdAction.build())
.build();
}
testSpecificForward(expectedTableId, expectedSelector, selector, nextId, setNextIdTreatment);
}
private void testSpecificForward(PiTableId expectedTableId, TrafficSelector expectedSelector,
TrafficSelector selector, Integer nextId, TrafficTreatment treatment)
throws FabricPipelinerException {
ForwardingObjective.Builder fwd = DefaultForwardingObjective.builder()
.withSelector(selector)
.withPriority(PRIORITY)
.fromApp(APP_ID)
.makePermanent()
.withTreatment(treatment)
.withFlag(ForwardingObjective.Flag.SPECIFIC);
if (nextId != null) {
fwd.nextStep(nextId);
}
ObjectiveTranslation actualTranslation = translator.translate(fwd.add());
FlowRule expectedFlowRule = DefaultFlowRule.builder()
.forDevice(DEVICE_ID)
.forTable(expectedTableId)
.withPriority(PRIORITY)
.makePermanent()
.withSelector(expectedSelector)
.withTreatment(treatment)
.fromApp(APP_ID)
.build();
ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
.addFlowRule(expectedFlowRule)
.build();
assertEquals(expectedTranslation, actualTranslation);
}
private TrafficSelector buildExpectedSelector(TrafficSelector selector) {
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
selector.criteria().forEach(c -> {
if (c.type() == Criterion.Type.ETH_DST) {
sbuilder.matchEthDstMasked(((EthCriterion) c).mac(), MacAddress.EXACT_MASK);
} else {
sbuilder.add(c);
}
});
return sbuilder.build();
}
}