blob: d330dcd2030e6206a37cf54f326388645c896d36 [file] [log] [blame]
Thomas Vachuska83e090e2014-10-22 14:25:35 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska83e090e2014-10-22 14:25:35 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska83e090e2014-10-22 14:25:35 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska83e090e2014-10-22 14:25:35 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.flow.instructions;
alshabib55a55d92014-09-16 11:59:31 -070017
Steffen Gebertba2d3b72015-10-22 11:14:31 +020018import com.google.common.base.MoreObjects;
Cem Türker3baff672017-10-12 15:09:01 +030019import com.google.common.collect.ImmutableMap;
alshabib7b808c52015-06-26 14:22:24 -070020import org.onlab.packet.EthType;
Jonathan Hart54b406b2015-03-06 16:24:14 -080021import org.onlab.packet.IpAddress;
22import org.onlab.packet.MacAddress;
23import org.onlab.packet.MplsLabel;
Hyunsun Mooncf732fb2015-08-22 21:04:23 -070024import org.onlab.packet.TpPort;
Jonathan Hart54b406b2015-03-06 16:24:14 -080025import org.onlab.packet.VlanId;
sangho8995ac52015-02-04 11:29:03 -080026import org.onosproject.core.GroupId;
Jonathan Hart3c259162015-10-21 21:31:19 -070027import org.onosproject.net.DeviceId;
Sho SHIMIZU2e7ac842015-05-05 15:45:38 -070028import org.onosproject.net.Lambda;
Sho SHIMIZUe9e12752015-05-05 14:45:40 -070029import org.onosproject.net.OchSignal;
Yafit Hadar52d81552015-10-07 12:26:52 +030030import org.onosproject.net.OduSignalId;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.PortNumber;
Cem Türker3baff672017-10-12 15:09:01 +030032import org.onosproject.net.flow.StatTriggerField;
33import org.onosproject.net.flow.StatTriggerFlag;
Sho SHIMIZU2e7ac842015-05-05 15:45:38 -070034import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
Yafit Hadar52d81552015-10-07 12:26:52 +030035import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType;
37import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
lishuai3cce60b2015-12-01 19:35:16 +080038import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction;
39import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction;
40import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction;
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080041import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
sangho3f97a17d2015-01-29 22:56:29 -080042import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModTtlInstruction;
Hyunsun Moonc8bd97c2015-07-18 22:47:33 -070043import org.onosproject.net.flow.instructions.L4ModificationInstruction.L4SubType;
44import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
alshabib10c810b2015-08-18 16:59:04 -070045import org.onosproject.net.meter.MeterId;
Frank Wangdf383212017-06-23 09:17:41 +080046import org.onosproject.net.pi.runtime.PiTableAction;
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -080047
Cem Türker3baff672017-10-12 15:09:01 +030048import java.util.Map;
Jonathan Hart54b406b2015-03-06 16:24:14 -080049import java.util.Objects;
50
51import static com.google.common.base.MoreObjects.toStringHelper;
Yi Tseng29b4f222021-07-28 17:00:46 -070052import static com.google.common.base.Preconditions.checkArgument;
Jonathan Hart54b406b2015-03-06 16:24:14 -080053import static com.google.common.base.Preconditions.checkNotNull;
alshabib64231f62014-09-16 17:58:36 -070054
alshabib55a55d92014-09-16 11:59:31 -070055/**
56 * Factory class for creating various traffic treatment instructions.
57 */
58public final class Instructions {
59
Jonathan Hartc7840bd2016-01-21 23:26:29 -080060 private static final String SEPARATOR = ":";
61
alshabib55a55d92014-09-16 11:59:31 -070062 // Ban construction
63 private Instructions() {}
64
65 /**
66 * Creates an output instruction using the specified port number. This can
67 * include logical ports such as CONTROLLER, FLOOD, etc.
68 *
69 * @param number port number
70 * @return output instruction
71 */
72 public static OutputInstruction createOutput(final PortNumber number) {
73 checkNotNull(number, "PortNumber cannot be null");
74 return new OutputInstruction(number);
75 }
76
77 /**
Charles Chan7efabeb2015-09-28 15:12:19 -070078 * Creates a no action instruction.
79 *
80 * @return no action instruction
81 */
82 public static NoActionInstruction createNoAction() {
83 return new NoActionInstruction();
84 }
85
86 /**
sangho8995ac52015-02-04 11:29:03 -080087 * Creates a group instruction.
88 *
89 * @param groupId Group Id
90 * @return group instruction
91 */
92 public static GroupInstruction createGroup(final GroupId groupId) {
93 checkNotNull(groupId, "GroupId cannot be null");
94 return new GroupInstruction(groupId);
95 }
96
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +020097 /**
98 * Creates a set-queue instruction.
99 *
100 * @param queueId Queue Id
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200101 * @param port Port number
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200102 * @return set-queue instruction
103 */
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200104 public static SetQueueInstruction setQueue(final long queueId, final PortNumber port) {
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200105 return new SetQueueInstruction(queueId, port);
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200106 }
107
Jian Li1ef82db2016-03-03 14:43:21 -0800108 /**
109 * Creates a meter instruction.
110 *
111 * @param meterId Meter Id
112 * @return meter instruction
113 */
alshabib10c810b2015-08-18 16:59:04 -0700114 public static MeterInstruction meterTraffic(final MeterId meterId) {
115 checkNotNull(meterId, "meter id cannot be null");
116 return new MeterInstruction(meterId);
117 }
118
sangho8995ac52015-02-04 11:29:03 -0800119 /**
Sho SHIMIZUe9e12752015-05-05 14:45:40 -0700120 * Creates an L0 modification with the specified OCh signal.
121 *
122 * @param lambda OCh signal
123 * @return an L0 modification
124 */
Sho SHIMIZU2e7ac842015-05-05 15:45:38 -0700125 public static L0ModificationInstruction modL0Lambda(Lambda lambda) {
Sho SHIMIZUe9e12752015-05-05 14:45:40 -0700126 checkNotNull(lambda, "L0 OCh signal cannot be null");
Sho SHIMIZU2e7ac842015-05-05 15:45:38 -0700127
Sho SHIMIZUa114d892016-03-11 16:48:19 -0800128 if (lambda instanceof OchSignal) {
Sho SHIMIZU2e7ac842015-05-05 15:45:38 -0700129 return new ModOchSignalInstruction((OchSignal) lambda);
130 } else {
131 throw new UnsupportedOperationException(String.format("Unsupported type: %s", lambda));
132 }
Sho SHIMIZUe9e12752015-05-05 14:45:40 -0700133 }
134
135 /**
Yafit Hadar52d81552015-10-07 12:26:52 +0300136 * Creates an L1 modification with the specified ODU signal Id.
137 *
138 * @param oduSignalId ODU Signal Id
139 * @return a L1 modification
140 */
141 public static L1ModificationInstruction modL1OduSignalId(OduSignalId oduSignalId) {
142 checkNotNull(oduSignalId, "L1 ODU signal ID cannot be null");
143 return new ModOduSignalIdInstruction(oduSignalId);
144 }
145 /**
alshabib55a55d92014-09-16 11:59:31 -0700146 * Creates a l2 src modification.
Jonathan Hart54b406b2015-03-06 16:24:14 -0800147 *
148 * @param addr the mac address to modify to
alshabib55a55d92014-09-16 11:59:31 -0700149 * @return a l2 modification
150 */
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700151 public static L2ModificationInstruction modL2Src(MacAddress addr) {
alshabib55a55d92014-09-16 11:59:31 -0700152 checkNotNull(addr, "Src l2 address cannot be null");
alshabibd17abc22015-04-21 18:26:35 -0700153 return new L2ModificationInstruction.ModEtherInstruction(
154 L2ModificationInstruction.L2SubType.ETH_SRC, addr);
alshabib55a55d92014-09-16 11:59:31 -0700155 }
156
157 /**
158 * Creates a L2 dst modification.
Jonathan Hart54b406b2015-03-06 16:24:14 -0800159 *
160 * @param addr the mac address to modify to
alshabib55a55d92014-09-16 11:59:31 -0700161 * @return a L2 modification
162 */
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700163 public static L2ModificationInstruction modL2Dst(MacAddress addr) {
alshabib55a55d92014-09-16 11:59:31 -0700164 checkNotNull(addr, "Dst l2 address cannot be null");
alshabibd17abc22015-04-21 18:26:35 -0700165 return new L2ModificationInstruction.ModEtherInstruction(
166 L2ModificationInstruction.L2SubType.ETH_DST, addr);
alshabib55a55d92014-09-16 11:59:31 -0700167 }
168
169 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800170 * Creates a VLAN ID modification.
171 *
172 * @param vlanId the VLAN ID to modify to
alshabib7410fea2014-09-16 13:48:39 -0700173 * @return a L2 modification
174 */
Ayaka Koshibea9c199f2014-09-16 16:21:40 -0700175 public static L2ModificationInstruction modVlanId(VlanId vlanId) {
alshabib55a55d92014-09-16 11:59:31 -0700176 checkNotNull(vlanId, "VLAN id cannot be null");
alshabibd17abc22015-04-21 18:26:35 -0700177 return new L2ModificationInstruction.ModVlanIdInstruction(vlanId);
alshabib55a55d92014-09-16 11:59:31 -0700178 }
179
alshabib7410fea2014-09-16 13:48:39 -0700180 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800181 * Creates a VLAN PCP modification.
182 *
183 * @param vlanPcp the PCP to modify to
alshabib7410fea2014-09-16 13:48:39 -0700184 * @return a L2 modification
185 */
186 public static L2ModificationInstruction modVlanPcp(Byte vlanPcp) {
187 checkNotNull(vlanPcp, "VLAN Pcp cannot be null");
alshabibd17abc22015-04-21 18:26:35 -0700188 return new L2ModificationInstruction.ModVlanPcpInstruction(vlanPcp);
alshabib7410fea2014-09-16 13:48:39 -0700189 }
190
191 /**
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800192 * Creates a MPLS label modification.
Jonathan Hart54b406b2015-03-06 16:24:14 -0800193 *
194 * @param mplsLabel MPLS label to set
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800195 * @return a L2 Modification
196 */
Michele Santuari4b6019e2014-12-19 11:31:45 +0100197 public static L2ModificationInstruction modMplsLabel(MplsLabel mplsLabel) {
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800198 checkNotNull(mplsLabel, "MPLS label cannot be null");
alshabibd17abc22015-04-21 18:26:35 -0700199 return new L2ModificationInstruction.ModMplsLabelInstruction(mplsLabel);
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800200 }
sangho3f97a17d2015-01-29 22:56:29 -0800201
202 /**
Saurav Das73a7dd42015-08-19 22:20:31 -0700203 * Creates a MPLS BOS bit modification.
204 *
205 * @param mplsBos MPLS BOS bit to set (true) or unset (false)
206 * @return a L2 Modification
207 */
208 public static L2ModificationInstruction modMplsBos(boolean mplsBos) {
209 return new L2ModificationInstruction.ModMplsBosInstruction(mplsBos);
210 }
211
212 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800213 * Creates a MPLS decrement TTL modification.
sangho3f97a17d2015-01-29 22:56:29 -0800214 *
215 * @return a L2 Modification
216 */
217 public static L2ModificationInstruction decMplsTtl() {
alshabibd17abc22015-04-21 18:26:35 -0700218 return new L2ModificationInstruction.ModMplsTtlInstruction();
sangho3f97a17d2015-01-29 22:56:29 -0800219 }
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800220
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800221 /**
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800222 * Creates a L3 IPv4 src modification.
223 *
224 * @param addr the IPv4 address to modify to
alshabib7410fea2014-09-16 13:48:39 -0700225 * @return a L3 modification
226 */
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700227 public static L3ModificationInstruction modL3Src(IpAddress addr) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800228 checkNotNull(addr, "Src l3 IPv4 address cannot be null");
229 return new ModIPInstruction(L3SubType.IPV4_SRC, addr);
alshabib7410fea2014-09-16 13:48:39 -0700230 }
231
232 /**
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800233 * Creates a L3 IPv4 dst modification.
234 *
235 * @param addr the IPv4 address to modify to
alshabib7410fea2014-09-16 13:48:39 -0700236 * @return a L3 modification
237 */
Pavlin Radoslavov855ea2d2014-10-30 15:32:39 -0700238 public static L3ModificationInstruction modL3Dst(IpAddress addr) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800239 checkNotNull(addr, "Dst l3 IPv4 address cannot be null");
240 return new ModIPInstruction(L3SubType.IPV4_DST, addr);
241 }
242
243 /**
244 * Creates a L3 IPv6 src modification.
245 *
246 * @param addr the IPv6 address to modify to
247 * @return a L3 modification
248 */
249 public static L3ModificationInstruction modL3IPv6Src(IpAddress addr) {
250 checkNotNull(addr, "Src l3 IPv6 address cannot be null");
251 return new ModIPInstruction(L3SubType.IPV6_SRC, addr);
252 }
253
254 /**
255 * Creates a L3 IPv6 dst modification.
256 *
257 * @param addr the IPv6 address to modify to
258 * @return a L3 modification
259 */
260 public static L3ModificationInstruction modL3IPv6Dst(IpAddress addr) {
261 checkNotNull(addr, "Dst l3 IPv6 address cannot be null");
262 return new ModIPInstruction(L3SubType.IPV6_DST, addr);
263 }
264
265 /**
266 * Creates a L3 IPv6 Flow Label modification.
267 *
268 * @param flowLabel the IPv6 flow label to modify to (20 bits)
269 * @return a L3 modification
270 */
271 public static L3ModificationInstruction modL3IPv6FlowLabel(int flowLabel) {
272 return new ModIPv6FlowLabelInstruction(flowLabel);
alshabib7410fea2014-09-16 13:48:39 -0700273 }
274
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800275 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800276 * Creates a L3 decrement TTL modification.
277 *
sangho3f97a17d2015-01-29 22:56:29 -0800278 * @return a L3 modification
279 */
280 public static L3ModificationInstruction decNwTtl() {
281 return new ModTtlInstruction(L3SubType.DEC_TTL);
282 }
283
284 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800285 * Creates a L3 copy TTL to outer header modification.
286 *
sangho3f97a17d2015-01-29 22:56:29 -0800287 * @return a L3 modification
288 */
289 public static L3ModificationInstruction copyTtlOut() {
290 return new ModTtlInstruction(L3SubType.TTL_OUT);
291 }
292
293 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800294 * Creates a L3 copy TTL to inner header modification.
295 *
sangho3f97a17d2015-01-29 22:56:29 -0800296 * @return a L3 modification
297 */
298 public static L3ModificationInstruction copyTtlIn() {
299 return new ModTtlInstruction(L3SubType.TTL_IN);
300 }
301
302 /**
lishuai3cce60b2015-12-01 19:35:16 +0800303 * Creates a L3 ARP IP src modification.
304 *
305 * @param addr the ip address to modify to
306 * @return a L3 modification
307 */
308 public static L3ModificationInstruction modArpSpa(IpAddress addr) {
309 checkNotNull(addr, "Src l3 ARP IP address cannot be null");
310 return new ModArpIPInstruction(L3SubType.ARP_SPA, addr);
311 }
312
313 /**
314 * Creates a l3 ARP Ether src modification.
315 *
316 * @param addr the mac address to modify to
317 * @return a l3 modification
318 */
319 public static L3ModificationInstruction modArpSha(MacAddress addr) {
320 checkNotNull(addr, "Src l3 ARP address cannot be null");
321 return new ModArpEthInstruction(L3SubType.ARP_SHA, addr);
322 }
323
324 /**
souvikdas95c94223a2020-09-23 00:32:12 -0500325 * Creates a L3 ARP IP src modification.
326 *
327 * @param addr the ip address to modify to
328 * @return a L3 modification
329 */
330 public static L3ModificationInstruction modArpTpa(IpAddress addr) {
331 checkNotNull(addr, "Dst l3 ARP IP address cannot be null");
332 return new ModArpIPInstruction(L3SubType.ARP_TPA, addr);
333 }
334
335 /**
336 * Creates a l3 ARP Ether src modification.
337 *
338 * @param addr the mac address to modify to
339 * @return a l3 modification
340 */
341 public static L3ModificationInstruction modArpTha(MacAddress addr) {
342 checkNotNull(addr, "Dst l3 ARP address cannot be null");
343 return new ModArpEthInstruction(L3SubType.ARP_THA, addr);
344 }
345
346 /**
lishuai3cce60b2015-12-01 19:35:16 +0800347 * Creates a l3 ARP operation modification.
348 *
349 * @param op the ARP operation to modify to
350 * @return a l3 modification
351 */
352 public static L3ModificationInstruction modL3ArpOp(short op) {
lishuai3cce60b2015-12-01 19:35:16 +0800353 return new ModArpOpInstruction(L3SubType.ARP_OP, op);
354 }
355
356 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800357 * Creates a push MPLS header instruction.
358 *
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800359 * @return a L2 modification.
360 */
361 public static Instruction pushMpls() {
Jian Li11260a02016-05-19 13:07:22 -0700362 return new L2ModificationInstruction.ModMplsHeaderInstruction(
alshabibd17abc22015-04-21 18:26:35 -0700363 L2ModificationInstruction.L2SubType.MPLS_PUSH,
alshabib7b808c52015-06-26 14:22:24 -0700364 EthType.EtherType.MPLS_UNICAST.ethType());
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800365 }
366
367 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800368 * Creates a pop MPLS header instruction.
369 *
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800370 * @return a L2 modification.
371 */
372 public static Instruction popMpls() {
Jian Li11260a02016-05-19 13:07:22 -0700373 return new L2ModificationInstruction.ModMplsHeaderInstruction(
alshabibd17abc22015-04-21 18:26:35 -0700374 L2ModificationInstruction.L2SubType.MPLS_POP,
alshabib7b808c52015-06-26 14:22:24 -0700375 EthType.EtherType.MPLS_UNICAST.ethType());
Praseed Balakrishnan8c67d172014-11-10 10:15:41 -0800376 }
alshabib7410fea2014-09-16 13:48:39 -0700377
sangho3f97a17d2015-01-29 22:56:29 -0800378 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800379 * Creates a pop MPLS header instruction with a particular ethertype.
sangho3f97a17d2015-01-29 22:56:29 -0800380 *
381 * @param etherType Ethernet type to set
382 * @return a L2 modification.
alshabib7b808c52015-06-26 14:22:24 -0700383 */
384 public static Instruction popMpls(EthType etherType) {
385 checkNotNull(etherType, "Ethernet type cannot be null");
Jian Li11260a02016-05-19 13:07:22 -0700386 return new L2ModificationInstruction.ModMplsHeaderInstruction(
alshabibd17abc22015-04-21 18:26:35 -0700387 L2ModificationInstruction.L2SubType.MPLS_POP, etherType);
sangho3f97a17d2015-01-29 22:56:29 -0800388 }
389
Saurav Dasfbe25c52015-03-04 11:12:00 -0800390 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800391 * Creates a pop VLAN header instruction.
392 *
393 * @return a L2 modification
Saurav Dasfbe25c52015-03-04 11:12:00 -0800394 */
395 public static Instruction popVlan() {
Jian Li11260a02016-05-19 13:07:22 -0700396 return new L2ModificationInstruction.ModVlanHeaderInstruction(
alshabibd17abc22015-04-21 18:26:35 -0700397 L2ModificationInstruction.L2SubType.VLAN_POP);
Saurav Dasfbe25c52015-03-04 11:12:00 -0800398 }
399
400 /**
Jonathan Hart54b406b2015-03-06 16:24:14 -0800401 * Creates a push VLAN header instruction.
402 *
403 * @return a L2 modification
404 */
405 public static Instruction pushVlan() {
Jian Li11260a02016-05-19 13:07:22 -0700406 return new L2ModificationInstruction.ModVlanHeaderInstruction(
alshabib7b808c52015-06-26 14:22:24 -0700407 L2ModificationInstruction.L2SubType.VLAN_PUSH,
408 EthType.EtherType.VLAN.ethType());
Jonathan Hart54b406b2015-03-06 16:24:14 -0800409 }
410
411 /**
Konstantinos Kanonakis9215ff22016-11-04 13:28:11 -0500412 * Creates a push VLAN header instruction using the supplied Ethernet type.
413 *
414 * @param ethType the Ethernet type to use
415 * @return a L2 modification
416 */
417 public static Instruction pushVlan(EthType ethType) {
418 return new L2ModificationInstruction.ModVlanHeaderInstruction(
419 L2ModificationInstruction.L2SubType.VLAN_PUSH,
420 ethType);
421 }
422
423 /**
alshabibd17abc22015-04-21 18:26:35 -0700424 * Sends the packet to the table id.
Jonathan Hart54b406b2015-03-06 16:24:14 -0800425 *
alshabibd17abc22015-04-21 18:26:35 -0700426 * @param tableId flow rule table id
Thomas Vachuska3e2b6512015-03-05 09:25:03 -0800427 * @return table type transition instruction
Saurav Dasfbe25c52015-03-04 11:12:00 -0800428 */
alshabibd17abc22015-04-21 18:26:35 -0700429 public static Instruction transition(Integer tableId) {
430 checkNotNull(tableId, "Table id cannot be null");
431 return new TableTypeTransition(tableId);
alshabib9af70072015-02-09 14:34:16 -0800432 }
433
Yuta HIGUCHI6a479642015-02-08 01:28:50 -0800434 /**
Saurav Das86af8f12015-05-25 23:55:33 -0700435 * Writes metadata to associate with a packet.
436 *
437 * @param metadata the metadata value to write
438 * @param metadataMask the bits to mask for the metadata value
439 * @return metadata instruction
440 */
441 public static Instruction writeMetadata(long metadata, long metadataMask) {
442 return new MetadataInstruction(metadata, metadataMask);
443 }
444
445 /**
Hyunsun Moona08c5d02015-07-14 17:53:00 -0700446 * Creates a Tunnel ID modification.
447 *
448 * @param tunnelId the Tunnel ID to modify to
449 * @return a L2 modification
450 */
451 public static L2ModificationInstruction modTunnelId(long tunnelId) {
Hyunsun Moona08c5d02015-07-14 17:53:00 -0700452 return new L2ModificationInstruction.ModTunnelIdInstruction(tunnelId);
453 }
454
455 /**
Hyunsun Moonc8bd97c2015-07-18 22:47:33 -0700456 * Creates a TCP src modification.
457 *
458 * @param port the TCP port number to modify to
459 * @return a L4 modification
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700460 */
461 public static L4ModificationInstruction modTcpSrc(TpPort port) {
462 checkNotNull(port, "Src TCP port cannot be null");
Hyunsun Moonc8bd97c2015-07-18 22:47:33 -0700463 return new ModTransportPortInstruction(L4SubType.TCP_SRC, port);
464 }
465
466 /**
467 * Creates a TCP dst modification.
468 *
469 * @param port the TCP port number to modify to
470 * @return a L4 modification
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700471 */
472 public static L4ModificationInstruction modTcpDst(TpPort port) {
473 checkNotNull(port, "Dst TCP port cannot be null");
Hyunsun Moonc8bd97c2015-07-18 22:47:33 -0700474 return new ModTransportPortInstruction(L4SubType.TCP_DST, port);
475 }
476
477 /**
478 * Creates a UDP src modification.
479 *
480 * @param port the UDP port number to modify to
481 * @return a L4 modification
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700482 */
483 public static L4ModificationInstruction modUdpSrc(TpPort port) {
484 checkNotNull(port, "Src UDP port cannot be null");
Hyunsun Moonc8bd97c2015-07-18 22:47:33 -0700485 return new ModTransportPortInstruction(L4SubType.UDP_SRC, port);
486 }
487
488 /**
489 * Creates a UDP dst modification.
490 *
491 * @param port the UDP port number to modify to
492 * @return a L4 modification
Hyunsun Mooncf732fb2015-08-22 21:04:23 -0700493 */
494 public static L4ModificationInstruction modUdpDst(TpPort port) {
495 checkNotNull(port, "Dst UDP port cannot be null");
Hyunsun Moonc8bd97c2015-07-18 22:47:33 -0700496 return new ModTransportPortInstruction(L4SubType.UDP_DST, port);
497 }
498
499 /**
Frank Wangdf383212017-06-23 09:17:41 +0800500 * Creates a protocol independent instruction.
501 *
502 * @param piTableAction protocol independent instruction
503 * @return extension instruction
504 */
505 public static PiInstruction piTableAction(PiTableAction piTableAction) {
506 checkNotNull(piTableAction, "PiTableAction instruction cannot be null");
507 return new PiInstruction(piTableAction);
508 }
509
510 /**
Thiago Santos4a69ef82018-08-21 21:18:05 -0700511 * Creates an IP DSCP modification.
512 *
Rory Savagedaeb9492020-02-18 14:35:50 -0500513 * @param ipDscp the DSCP value to modify to
Thiago Santos4a69ef82018-08-21 21:18:05 -0700514 * @return a L3 modification
515 */
Rory Savagedaeb9492020-02-18 14:35:50 -0500516 public static Instruction modIpDscp(byte ipDscp) {
517 return new L3ModificationInstruction.ModDscpInstruction(L3SubType.IP_DSCP, ipDscp);
Thiago Santos4a69ef82018-08-21 21:18:05 -0700518 }
519
520 /**
Jonathan Hart3c259162015-10-21 21:31:19 -0700521 * Creates an extension instruction.
522 *
523 * @param extension extension instruction
524 * @param deviceId device ID
525 * @return extension instruction
526 */
alshabib880b6442015-11-23 22:13:04 -0800527 public static ExtensionInstructionWrapper extension(ExtensionTreatment extension,
Jonathan Hart3c259162015-10-21 21:31:19 -0700528 DeviceId deviceId) {
529 checkNotNull(extension, "Extension instruction cannot be null");
530 checkNotNull(deviceId, "Device ID cannot be null");
531 return new ExtensionInstructionWrapper(extension, deviceId);
532 }
533
534 /**
Cem Türker3baff672017-10-12 15:09:01 +0300535 * Creates a stat trigger instruction.
536 *
537 * @param statTriggerMap map keeps stat trigger threshold
538 * @param flag stat trigger flag
539 * @return stat trigger instruction
540 */
541 public static StatTriggerInstruction statTrigger(Map<StatTriggerField, Long> statTriggerMap,
542 StatTriggerFlag flag) {
543 checkNotNull(statTriggerMap, "Stat trigger map cannot be null");
544 checkNotNull(flag, "Stat trigger flag cannot be null");
545 return new StatTriggerInstruction(statTriggerMap, flag);
546 }
547
548 /**
Yi Tseng29b4f222021-07-28 17:00:46 -0700549 * Creates a truncate instruction.
550 *
551 * @param maxLen the maximum frame length in bytes, must be a positive integer
552 * @return truncate instruction
553 */
554 public static TruncateInstruction truncate(int maxLen) {
555 checkArgument(maxLen > 0, "Truncate max length must be a positive integer.");
556 return new TruncateInstruction(maxLen);
557 }
558
559 /**
Charles Chan7efabeb2015-09-28 15:12:19 -0700560 * No Action instruction.
561 */
562 public static final class NoActionInstruction implements Instruction {
563
564 private NoActionInstruction() {}
565
566 @Override
567 public Type type() {
568 return Type.NOACTION;
569 }
570
571 @Override
572 public String toString() {
Jonathan Hartc7840bd2016-01-21 23:26:29 -0800573 return type().toString();
Charles Chan7efabeb2015-09-28 15:12:19 -0700574 }
575
576 @Override
577 public int hashCode() {
HIGUCHI Yutaca9cc8e2015-10-29 23:26:51 -0700578 return type().ordinal();
Charles Chan7efabeb2015-09-28 15:12:19 -0700579 }
580
581 @Override
582 public boolean equals(Object obj) {
583 if (this == obj) {
584 return true;
585 }
586 if (obj instanceof NoActionInstruction) {
587 return true;
588 }
589 return false;
590 }
591 }
592
593 /**
Yuta HIGUCHI6a479642015-02-08 01:28:50 -0800594 * Output Instruction.
sangho8995ac52015-02-04 11:29:03 -0800595 */
alshabib55a55d92014-09-16 11:59:31 -0700596 public static final class OutputInstruction implements Instruction {
597 private final PortNumber port;
598
599 private OutputInstruction(PortNumber port) {
600 this.port = port;
601 }
602
603 public PortNumber port() {
604 return port;
605 }
606
607 @Override
608 public Type type() {
609 return Type.OUTPUT;
610 }
Jonathan Hartc7840bd2016-01-21 23:26:29 -0800611
alshabib99b8fdc2014-09-25 14:30:22 -0700612 @Override
613 public String toString() {
Jonathan Hartc7840bd2016-01-21 23:26:29 -0800614 return type().toString() + SEPARATOR + port.toString();
alshabib99b8fdc2014-09-25 14:30:22 -0700615 }
alshabib8ca53902014-10-07 13:11:17 -0700616
617 @Override
618 public int hashCode() {
Thomas Vachuska6c8eff32015-05-27 16:11:44 -0700619 return Objects.hash(type().ordinal(), port);
alshabib8ca53902014-10-07 13:11:17 -0700620 }
621
622 @Override
623 public boolean equals(Object obj) {
624 if (this == obj) {
625 return true;
626 }
627 if (obj instanceof OutputInstruction) {
628 OutputInstruction that = (OutputInstruction) obj;
Yuta HIGUCHI4ce65292014-11-01 12:09:55 -0700629 return Objects.equals(port, that.port);
alshabib8ca53902014-10-07 13:11:17 -0700630
631 }
632 return false;
633 }
alshabib55a55d92014-09-16 11:59:31 -0700634 }
635
Yuta HIGUCHI6a479642015-02-08 01:28:50 -0800636 /**
637 * Group Instruction.
sangho8995ac52015-02-04 11:29:03 -0800638 */
sangho8995ac52015-02-04 11:29:03 -0800639 public static final class GroupInstruction implements Instruction {
640 private final GroupId groupId;
641
642 private GroupInstruction(GroupId groupId) {
643 this.groupId = groupId;
644 }
645
646 public GroupId groupId() {
647 return groupId;
648 }
649
650 @Override
651 public Type type() {
652 return Type.GROUP;
653 }
alshabib9af70072015-02-09 14:34:16 -0800654
sangho8995ac52015-02-04 11:29:03 -0800655 @Override
656 public String toString() {
Saurav Das0fd79d92016-03-07 10:58:36 -0800657 return type().toString() + SEPARATOR + "0x" + Integer.toHexString(groupId.id());
sangho8995ac52015-02-04 11:29:03 -0800658 }
659
660 @Override
661 public int hashCode() {
Thomas Vachuska6c8eff32015-05-27 16:11:44 -0700662 return Objects.hash(type().ordinal(), groupId);
sangho8995ac52015-02-04 11:29:03 -0800663 }
664
665 @Override
666 public boolean equals(Object obj) {
667 if (this == obj) {
668 return true;
669 }
670 if (obj instanceof GroupInstruction) {
671 GroupInstruction that = (GroupInstruction) obj;
672 return Objects.equals(groupId, that.groupId);
673
674 }
675 return false;
676 }
677 }
678
Saurav Das86af8f12015-05-25 23:55:33 -0700679 /**
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200680 * Set-Queue Instruction.
681 */
682 public static final class SetQueueInstruction implements Instruction {
683 private final long queueId;
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200684 private final PortNumber port;
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200685
686 private SetQueueInstruction(long queueId) {
687 this.queueId = queueId;
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200688 this.port = null;
689 }
690
691 private SetQueueInstruction(long queueId, PortNumber port) {
692 this.queueId = queueId;
693 this.port = port;
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200694 }
695
696 public long queueId() {
697 return queueId;
698 }
699
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200700 public PortNumber port() {
701 return port;
702 }
703
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200704 @Override
705 public Type type() {
706 return Type.QUEUE;
707 }
708
709 @Override
710 public String toString() {
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200711 MoreObjects.ToStringHelper toStringHelper = toStringHelper(type().toString());
712 toStringHelper.add("queueId", queueId);
713
714 if (port() != null) {
715 toStringHelper.add("port", port);
716 }
717 return toStringHelper.toString();
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200718 }
719
720 @Override
721 public int hashCode() {
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200722 return Objects.hash(type().ordinal(), queueId, port);
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200723 }
724
725 @Override
726 public boolean equals(Object obj) {
727 if (this == obj) {
728 return true;
729 }
730 if (obj instanceof SetQueueInstruction) {
731 SetQueueInstruction that = (SetQueueInstruction) obj;
Steffen Gebertba2d3b72015-10-22 11:14:31 +0200732 return Objects.equals(queueId, that.queueId) && Objects.equals(port, that.port);
Steffen Gebertbbfdaaa2015-09-29 11:01:46 +0200733
734 }
735 return false;
736 }
737 }
738
739 /**
alshabib10c810b2015-08-18 16:59:04 -0700740 * A meter instruction.
741 */
742 public static final class MeterInstruction implements Instruction {
743 private final MeterId meterId;
744
745 private MeterInstruction(MeterId meterId) {
746 this.meterId = meterId;
747 }
748
749 public MeterId meterId() {
750 return meterId;
751 }
752
753 @Override
754 public Type type() {
755 return Type.METER;
756 }
757
758 @Override
759 public String toString() {
Jonathan Hartc7840bd2016-01-21 23:26:29 -0800760 return type().toString() + SEPARATOR + meterId.id();
alshabib10c810b2015-08-18 16:59:04 -0700761 }
762
763 @Override
764 public int hashCode() {
765 return Objects.hash(type().ordinal(), meterId);
766 }
767
768 @Override
769 public boolean equals(Object obj) {
770 if (this == obj) {
771 return true;
772 }
773 if (obj instanceof MeterInstruction) {
774 MeterInstruction that = (MeterInstruction) obj;
775 return Objects.equals(meterId, that.meterId);
776
777 }
778 return false;
779 }
780 }
781
782 /**
Saurav Das86af8f12015-05-25 23:55:33 -0700783 * Transition instruction.
784 */
alshabibd17abc22015-04-21 18:26:35 -0700785 public static class TableTypeTransition implements Instruction {
786 private final Integer tableId;
787
788 TableTypeTransition(Integer tableId) {
789 this.tableId = tableId;
alshabib9af70072015-02-09 14:34:16 -0800790 }
791
792 @Override
793 public Type type() {
794 return Type.TABLE;
795 }
796
alshabibd17abc22015-04-21 18:26:35 -0700797 public Integer tableId() {
798 return this.tableId;
alshabib9af70072015-02-09 14:34:16 -0800799 }
800
801 @Override
802 public String toString() {
Jonathan Hartc7840bd2016-01-21 23:26:29 -0800803 return type().toString() + SEPARATOR + this.tableId;
alshabib9af70072015-02-09 14:34:16 -0800804 }
805
806 @Override
807 public int hashCode() {
Thomas Vachuska6c8eff32015-05-27 16:11:44 -0700808 return Objects.hash(type().ordinal(), tableId);
alshabib9af70072015-02-09 14:34:16 -0800809 }
810
811 @Override
812 public boolean equals(Object obj) {
813 if (this == obj) {
814 return true;
815 }
816 if (obj instanceof TableTypeTransition) {
817 TableTypeTransition that = (TableTypeTransition) obj;
alshabibd17abc22015-04-21 18:26:35 -0700818 return Objects.equals(tableId, that.tableId);
alshabib9af70072015-02-09 14:34:16 -0800819
820 }
821 return false;
822 }
Saurav Das86af8f12015-05-25 23:55:33 -0700823 }
alshabib9af70072015-02-09 14:34:16 -0800824
Saurav Das86af8f12015-05-25 23:55:33 -0700825 /**
826 * Metadata instruction.
827 */
828 public static class MetadataInstruction implements Instruction {
829 private final long metadata;
830 private final long metadataMask;
831
832 MetadataInstruction(long metadata, long metadataMask) {
833 this.metadata = metadata;
834 this.metadataMask = metadataMask;
835 }
836
837 @Override
838 public Type type() {
839 return Type.METADATA;
840 }
841
842 public long metadata() {
843 return this.metadata;
844 }
845
846 public long metadataMask() {
847 return this.metadataMask;
848 }
849
850 @Override
851 public String toString() {
Jonathan Hartc7840bd2016-01-21 23:26:29 -0800852 return type().toString() + SEPARATOR +
853 Long.toHexString(this.metadata) + "/" +
854 Long.toHexString(this.metadataMask);
Saurav Das86af8f12015-05-25 23:55:33 -0700855 }
856
857 @Override
858 public int hashCode() {
Thomas Vachuska6c8eff32015-05-27 16:11:44 -0700859 return Objects.hash(type().ordinal(), metadata, metadataMask);
Saurav Das86af8f12015-05-25 23:55:33 -0700860 }
861
862 @Override
863 public boolean equals(Object obj) {
864 if (this == obj) {
865 return true;
866 }
867 if (obj instanceof MetadataInstruction) {
868 MetadataInstruction that = (MetadataInstruction) obj;
869 return Objects.equals(metadata, that.metadata) &&
870 Objects.equals(metadataMask, that.metadataMask);
871
872 }
873 return false;
874 }
alshabib9af70072015-02-09 14:34:16 -0800875 }
Saurav Das73a7dd42015-08-19 22:20:31 -0700876
Jonathan Hart3c259162015-10-21 21:31:19 -0700877 /**
878 * Extension instruction.
879 */
880 public static class ExtensionInstructionWrapper implements Instruction {
alshabib880b6442015-11-23 22:13:04 -0800881 private final ExtensionTreatment extensionTreatment;
Jonathan Hart3c259162015-10-21 21:31:19 -0700882 private final DeviceId deviceId;
883
alshabib880b6442015-11-23 22:13:04 -0800884 ExtensionInstructionWrapper(ExtensionTreatment extension, DeviceId deviceId) {
885 extensionTreatment = extension;
Jonathan Hart3c259162015-10-21 21:31:19 -0700886 this.deviceId = deviceId;
887 }
888
alshabib880b6442015-11-23 22:13:04 -0800889 public ExtensionTreatment extensionInstruction() {
890 return extensionTreatment;
Jonathan Hart3c259162015-10-21 21:31:19 -0700891 }
892
893 public DeviceId deviceId() {
894 return deviceId;
895 }
896
897 @Override
898 public Type type() {
899 return Type.EXTENSION;
900 }
901
902 @Override
903 public String toString() {
Jonathan Hartc7840bd2016-01-21 23:26:29 -0800904 return type().toString() + SEPARATOR + deviceId + "/" + extensionTreatment;
Jonathan Hart3c259162015-10-21 21:31:19 -0700905 }
906
907 @Override
908 public int hashCode() {
alshabib880b6442015-11-23 22:13:04 -0800909 return Objects.hash(type().ordinal(), extensionTreatment, deviceId);
Jonathan Hart3c259162015-10-21 21:31:19 -0700910 }
911
912 @Override
913 public boolean equals(Object obj) {
914 if (this == obj) {
915 return true;
916 }
917 if (obj instanceof ExtensionInstructionWrapper) {
918 ExtensionInstructionWrapper that = (ExtensionInstructionWrapper) obj;
alshabib880b6442015-11-23 22:13:04 -0800919 return Objects.equals(extensionTreatment, that.extensionTreatment)
Jonathan Hart3c259162015-10-21 21:31:19 -0700920 && Objects.equals(deviceId, that.deviceId);
921
922 }
923 return false;
924 }
925 }
926
Cem Türker3baff672017-10-12 15:09:01 +0300927 public static class StatTriggerInstruction implements Instruction {
928 private Map<StatTriggerField, Long> statTriggerFieldMap;
929 private StatTriggerFlag statTriggerFlag;
930
931
932 StatTriggerInstruction(Map<StatTriggerField, Long> statTriggerMap,
933 StatTriggerFlag flag) {
934 this.statTriggerFieldMap = ImmutableMap.copyOf(statTriggerMap);
935 this.statTriggerFlag = flag;
936 }
937
938 public Map<StatTriggerField, Long> getStatTriggerFieldMap() {
939 return statTriggerFieldMap;
940 }
941
942 public StatTriggerFlag getStatTriggerFlag() {
943 return statTriggerFlag;
944 }
945
946 public Long getStatValue(StatTriggerField field) {
947 return statTriggerFieldMap.get(field);
948 }
949
950 @Override
951 public Type type() {
952 return Type.STAT_TRIGGER;
953 }
954
955 @Override
956 public String toString() {
957 return "StatTriggerInstruction{" +
958 "statTriggerFieldMap=" + statTriggerFieldMap +
959 ", statTriggerFlag=" + statTriggerFlag +
960 '}';
961 }
962
963 @Override
964 public boolean equals(Object o) {
965 if (this == o) {
966 return true;
967 }
968 if (o == null || getClass() != o.getClass()) {
969 return false;
970 }
971
972 StatTriggerInstruction that = (StatTriggerInstruction) o;
973
974 if (!Objects.equals(statTriggerFieldMap, that.statTriggerFieldMap)) {
975 return false;
976 }
977
978 return statTriggerFlag == that.statTriggerFlag;
979 }
980
981 @Override
982 public int hashCode() {
983 int result = statTriggerFieldMap != null ? statTriggerFieldMap.hashCode() : 0;
984 result = 31 * result + (statTriggerFlag != null ? statTriggerFlag.hashCode() : 0);
985 return result;
986 }
987 }
988
Yi Tseng29b4f222021-07-28 17:00:46 -0700989 public static final class TruncateInstruction implements Instruction {
990 private int maxLen;
991
992 public TruncateInstruction(int maxLen) {
993 this.maxLen = maxLen;
994 }
995
996 public int maxLen() {
997 return maxLen;
998 }
999
1000 @Override
1001 public Type type() {
1002 return Type.TRUNCATE;
1003 }
1004
1005 @Override
1006 public boolean equals(Object o) {
1007 if (this == o) {
1008 return true;
1009 }
1010 if (o == null || getClass() != o.getClass()) {
1011 return false;
1012 }
1013 TruncateInstruction that = (TruncateInstruction) o;
1014 return maxLen == that.maxLen;
1015 }
1016
1017 @Override
1018 public int hashCode() {
1019 return com.google.common.base.Objects.hashCode(maxLen);
1020 }
1021
1022 @Override
1023 public String toString() {
1024 return type() + SEPARATOR + maxLen;
1025 }
1026 }
alshabib55a55d92014-09-16 11:59:31 -07001027}
alshabib8ca53902014-10-07 13:11:17 -07001028
1029