blob: 04233315126d534526e3bacc03d59683a5469b84 [file] [log] [blame]
Carmelo Cascone00a59962017-06-16 17:51:49 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Carmelo Cascone00a59962017-06-16 17:51:49 +09003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.net.pi.impl;
18
19import com.google.common.testing.EqualsTester;
20import org.junit.Before;
21import org.junit.Test;
22import org.onlab.packet.MacAddress;
Carmelo Cascone07d72712017-07-14 15:57:47 -040023import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
Carmelo Cascone00a59962017-06-16 17:51:49 +090024import org.onosproject.core.ApplicationId;
25import org.onosproject.core.DefaultApplicationId;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.PortNumber;
28import org.onosproject.net.flow.DefaultFlowRule;
29import org.onosproject.net.flow.DefaultTrafficSelector;
30import org.onosproject.net.flow.DefaultTrafficTreatment;
31import org.onosproject.net.flow.FlowRule;
32import org.onosproject.net.flow.TrafficSelector;
33import org.onosproject.net.flow.TrafficTreatment;
Carmelo Cascone07d72712017-07-14 15:57:47 -040034import org.onosproject.net.pi.model.DefaultPiPipeconf;
Carmelo Cascone00a59962017-06-16 17:51:49 +090035import org.onosproject.net.pi.model.PiPipeconf;
Carmelo Cascone07d72712017-07-14 15:57:47 -040036import org.onosproject.net.pi.model.PiPipeconfId;
37import org.onosproject.net.pi.model.PiPipelineInterpreter;
Carmelo Cascone00a59962017-06-16 17:51:49 +090038import org.onosproject.net.pi.runtime.PiTableEntry;
39import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
40
41import java.util.Optional;
42import java.util.Random;
43
44import static org.hamcrest.CoreMatchers.equalTo;
45import static org.hamcrest.CoreMatchers.is;
46import static org.hamcrest.MatcherAssert.assertThat;
47import static org.onosproject.net.pi.impl.MockInterpreter.*;
48
49/**
50 * Tests for {@link PiFlowRuleTranslator}.
51 */
52@SuppressWarnings("ConstantConditions")
53public class PiFlowRuleTranslatorTest {
54
Carmelo Cascone07d72712017-07-14 15:57:47 -040055 private static final String BMV2_JSON_PATH = "/org/onosproject/net/pi/impl/default.json";
Yi Tseng0c2841c2017-08-15 10:54:14 -070056 private static final short IN_PORT_MASK = 0x01ff; // 9-bit mask
57 private static final short ETH_TYPE_MASK = (short) 0xffff;
Carmelo Cascone07d72712017-07-14 15:57:47 -040058
Carmelo Cascone00a59962017-06-16 17:51:49 +090059 private Random random = new Random();
60 private PiPipeconf pipeconf;
61
62 @Before
63 public void setUp() throws Exception {
Carmelo Cascone07d72712017-07-14 15:57:47 -040064 pipeconf = DefaultPiPipeconf.builder()
65 .withId(new PiPipeconfId("mock-pipeconf"))
Carmelo Cascone31d3e442017-07-18 16:58:51 -040066 .withPipelineModel(Bmv2PipelineModelParser.parse(this.getClass().getResource(BMV2_JSON_PATH)))
Carmelo Cascone07d72712017-07-14 15:57:47 -040067 .addBehaviour(PiPipelineInterpreter.class, MockInterpreter.class)
68 .build();
Carmelo Cascone00a59962017-06-16 17:51:49 +090069 }
70
71 @Test
72 public void testTranslate() throws Exception {
73
74 DeviceId deviceId = DeviceId.NONE;
75 ApplicationId appId = new DefaultApplicationId(1, "test");
76 int tableId = 0;
77 MacAddress ethDstMac = MacAddress.valueOf(random.nextLong());
78 MacAddress ethSrcMac = MacAddress.valueOf(random.nextLong());
79 short ethType = (short) (0x0000FFFF & random.nextInt());
80 short outPort = (short) random.nextInt(65);
81 short inPort = (short) random.nextInt(65);
82 int timeout = random.nextInt(100);
83 int priority = random.nextInt(100);
84
85 TrafficSelector matchInPort1 = DefaultTrafficSelector
86 .builder()
87 .matchInPort(PortNumber.portNumber(inPort))
88 .matchEthDst(ethDstMac)
89 .matchEthSrc(ethSrcMac)
90 .matchEthType(ethType)
91 .build();
92
93 TrafficTreatment outPort2 = DefaultTrafficTreatment
94 .builder()
95 .setOutput(PortNumber.portNumber(outPort))
96 .build();
97
98 FlowRule rule1 = DefaultFlowRule.builder()
99 .forDevice(deviceId)
100 .forTable(tableId)
101 .fromApp(appId)
102 .withSelector(matchInPort1)
103 .withTreatment(outPort2)
104 .makeTemporary(timeout)
105 .withPriority(priority)
106 .build();
107
108 FlowRule rule2 = DefaultFlowRule.builder()
109 .forDevice(deviceId)
110 .forTable(tableId)
111 .fromApp(appId)
112 .withSelector(matchInPort1)
113 .withTreatment(outPort2)
114 .makeTemporary(timeout)
115 .withPriority(priority)
116 .build();
117
118 PiTableEntry entry1 = PiFlowRuleTranslator.translateFlowRule(rule1, pipeconf, null);
119 PiTableEntry entry2 = PiFlowRuleTranslator.translateFlowRule(rule1, pipeconf, null);
120
121 // check equality, i.e. same rules must produce same entries
122 new EqualsTester()
123 .addEqualityGroup(rule1, rule2)
124 .addEqualityGroup(entry1, entry2)
125 .testEquals();
126
127 int numMatchParams = pipeconf.pipelineModel().table(TABLE0).get().matchFields().size();
128 // parse values stored in entry1
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200129 PiTernaryFieldMatch inPortParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(IN_PORT_ID).get();
130 PiTernaryFieldMatch ethDstParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(ETH_DST_ID).get();
131 PiTernaryFieldMatch ethSrcParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(ETH_SRC_ID).get();
132 PiTernaryFieldMatch ethTypeParam = (PiTernaryFieldMatch) entry1.matchKey().fieldMatch(ETH_TYPE_ID).get();
Carmelo Cascone00a59962017-06-16 17:51:49 +0900133 Optional<Double> expectedTimeout = pipeconf.pipelineModel().table(TABLE0).get().supportsAging()
134 ? Optional.of((double) rule1.timeout()) : Optional.empty();
135
136 // check that the number of parameters in the entry is the same as the number of table keys
137 assertThat("Incorrect number of match parameters",
Carmelo Cascone0e896a02017-07-31 07:22:27 +0200138 entry1.matchKey().fieldMatches().size(), is(equalTo(numMatchParams)));
Carmelo Cascone00a59962017-06-16 17:51:49 +0900139
140 // check that values stored in entry are the same used for the flow rule
141 assertThat("Incorrect inPort match param value",
142 inPortParam.value().asReadOnlyBuffer().getShort(), is(equalTo(inPort)));
Yi Tseng0c2841c2017-08-15 10:54:14 -0700143 assertThat("Incorrect inPort match param mask",
144 inPortParam.mask().asReadOnlyBuffer().getShort(), is(equalTo(IN_PORT_MASK)));
Carmelo Cascone00a59962017-06-16 17:51:49 +0900145 assertThat("Incorrect ethDestMac match param value",
146 ethDstParam.value().asArray(), is(equalTo(ethDstMac.toBytes())));
Yi Tseng0c2841c2017-08-15 10:54:14 -0700147 assertThat("Incorrect ethDestMac match param mask",
148 ethDstParam.mask().asArray(), is(equalTo(MacAddress.BROADCAST.toBytes())));
Carmelo Cascone00a59962017-06-16 17:51:49 +0900149 assertThat("Incorrect ethSrcMac match param value",
150 ethSrcParam.value().asArray(), is(equalTo(ethSrcMac.toBytes())));
Yi Tseng0c2841c2017-08-15 10:54:14 -0700151 assertThat("Incorrect ethSrcMac match param mask",
152 ethSrcParam.mask().asArray(), is(equalTo(MacAddress.BROADCAST.toBytes())));
Carmelo Cascone00a59962017-06-16 17:51:49 +0900153 assertThat("Incorrect ethType match param value",
154 ethTypeParam.value().asReadOnlyBuffer().getShort(), is(equalTo(ethType)));
Yi Tseng0c2841c2017-08-15 10:54:14 -0700155 assertThat("Incorrect ethType match param mask",
156 ethTypeParam.mask().asReadOnlyBuffer().getShort(), is(equalTo(ETH_TYPE_MASK)));
Carmelo Cascone00a59962017-06-16 17:51:49 +0900157 assertThat("Incorrect priority value",
Carmelo Cascone2cad9ef2017-08-01 21:52:07 +0200158 entry1.priority().get(), is(equalTo(Integer.MAX_VALUE - rule1.priority())));
Carmelo Cascone00a59962017-06-16 17:51:49 +0900159 assertThat("Incorrect timeout value",
160 entry1.timeout(), is(equalTo(expectedTimeout)));
161
162 }
163}