blob: b056916b037c69d769b1ea7f6ab5c691f1b0e617 [file] [log] [blame]
Georgios Katsikas70671b32018-07-02 18:47:27 +02001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
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.drivers.server.devices.nic;
18
19import com.google.common.base.Strings;
20
21import org.onosproject.net.flow.DefaultFlowRule;
22import org.onosproject.net.flow.FlowRule;
23import org.onosproject.net.flow.criteria.EthTypeCriterion;
24import org.onosproject.net.flow.criteria.EthCriterion;
25import org.onosproject.net.flow.criteria.IPProtocolCriterion;
26import org.onosproject.net.flow.criteria.IPCriterion;
27import org.onosproject.net.flow.criteria.UdpPortCriterion;
28import org.onosproject.net.flow.criteria.TcpPortCriterion;
29
30import org.onosproject.net.flow.instructions.Instruction;
31import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction;
32import org.onosproject.net.flow.instructions.Instructions.MeterInstruction;
33
34import org.onlab.packet.EthType;
35import org.onlab.packet.MacAddress;
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +020036import org.onlab.packet.Ip4Address;
Georgios Katsikas70671b32018-07-02 18:47:27 +020037import org.onlab.packet.Ip4Prefix;
38
39import org.slf4j.Logger;
40
41import java.util.Objects;
42import java.util.HashSet;
43import java.util.Set;
44
45import static com.google.common.base.MoreObjects.toStringHelper;
46import static com.google.common.base.Preconditions.checkArgument;
47import static com.google.common.base.Preconditions.checkNotNull;
Georgios Katsikas13ccba62020-03-18 12:05:03 +010048import static org.onosproject.drivers.server.Constants.MSG_NIC_FLOW_RULE_CORE_ID_NEGATIVE;
49import static org.onosproject.drivers.server.Constants.MSG_NIC_FLOW_RULE_IFACE_NEGATIVE;
50import static org.onosproject.drivers.server.Constants.MSG_NIC_FLOW_RULE_IFACE_NULL;
51import static org.onosproject.drivers.server.Constants.MSG_NIC_FLOW_RULE_SCOPE_NULL;
52import static org.onosproject.drivers.server.Constants.MSG_NIC_FLOW_RULE_TC_ID_NULL;
Georgios Katsikas70671b32018-07-02 18:47:27 +020053import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_TYPE;
54import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_SRC;
55import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_DST;
56import static org.onosproject.net.flow.criteria.Criterion.Type.IP_PROTO;
57import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_SRC;
58import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
59import static org.onosproject.net.flow.criteria.Criterion.Type.UDP_SRC;
60import static org.onosproject.net.flow.criteria.Criterion.Type.UDP_DST;
61import static org.onosproject.net.flow.criteria.Criterion.Type.TCP_SRC;
62import static org.onosproject.net.flow.criteria.Criterion.Type.TCP_DST;
63import static org.onosproject.net.flow.instructions.Instruction.Type.NOACTION;
64import static org.onosproject.net.flow.instructions.Instruction.Type.QUEUE;
65import static org.onosproject.net.flow.instructions.Instruction.Type.METER;
66import static org.slf4j.LoggerFactory.getLogger;
67
68/**
69 * Implementation of an abstract NIC rule.
70 */
71public abstract class DefaultNicFlowRule extends DefaultFlowRule implements NicFlowRule {
72
73 protected static final Logger log = getLogger(DefaultNicFlowRule.class);
74
75 // Additional members that a NIC rule requires
76 protected final String trafficClassId;
77 protected final String interfaceName;
78 protected long interfaceNumber;
79 protected long cpuCoreIndex;
80 protected final NicRuleScope scope;
81
82 // Derive from FlowRule's selector
83 protected EthTypeCriterion ethTypeCriterion;
84 protected EthCriterion ethSrcAddrCriterion;
85 protected EthCriterion ethDstAddrCriterion;
86
87 protected IPProtocolCriterion ipv4ProtoCriterion;
88 protected IPCriterion ipv4SrcAddrCriterion;
89 protected IPCriterion ipv4SrcMaskCriterion;
90 protected IPCriterion ipv4DstAddrCriterion;
91 protected IPCriterion ipv4DstMaskCriterion;
92
93 protected UdpPortCriterion udpSrcPortCriterion;
94 protected UdpPortCriterion udpDstPortCriterion;
95 protected TcpPortCriterion tcpSrcPortCriterion;
96 protected TcpPortCriterion tcpDstPortCriterion;
97
98 // Derives from FlowRule's treatment
99 protected Set<NicRuleAction> actions;
100
101 protected DefaultNicFlowRule(
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100102 FlowRule flowRule,
103 String trafficClassId,
104 String interfaceName,
105 long interfaceNumber,
106 long cpuCoreIndex,
107 NicRuleScope scope) {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200108 super(flowRule);
109
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100110 checkArgument(!Strings.isNullOrEmpty(trafficClassId), MSG_NIC_FLOW_RULE_TC_ID_NULL);
111 checkNotNull(interfaceName, MSG_NIC_FLOW_RULE_IFACE_NULL);
112 checkArgument(interfaceNumber >= 0, MSG_NIC_FLOW_RULE_IFACE_NEGATIVE);
113 checkArgument(cpuCoreIndex >= 0, MSG_NIC_FLOW_RULE_CORE_ID_NEGATIVE);
114 checkNotNull(scope, MSG_NIC_FLOW_RULE_SCOPE_NULL);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200115
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100116 this.trafficClassId = trafficClassId;
117 this.interfaceName = interfaceName;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200118 this.interfaceNumber = interfaceNumber;
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100119 this.cpuCoreIndex = cpuCoreIndex;
120 this.scope = scope;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200121
122 this.populate();
123 }
124
125 protected DefaultNicFlowRule(FlowRule flowRule) {
126 super(flowRule);
127
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100128 this.trafficClassId = Builder.DEFAULT_TRAFFIC_CLASS_ID;
129 this.interfaceName = "";
Georgios Katsikas70671b32018-07-02 18:47:27 +0200130 this.interfaceNumber = Builder.DEFAULT_INTERFACE_NB;
Georgios Katsikas13ccba62020-03-18 12:05:03 +0100131 this.cpuCoreIndex = Builder.DEFAULT_CPU_CORE_INDEX;
132 this.scope = Builder.DEFAULT_RULE_SCOPE;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200133
134 this.populate();
135 }
136
137 /**
138 * Parses FlowRule's traffic selector and treatment
139 * and keeps relevant information for this NIC rule.
140 */
141 private void populate() {
142 this.ethTypeCriterion = (EthTypeCriterion) this.selector().getCriterion(ETH_TYPE);
143 this.ethSrcAddrCriterion = (EthCriterion) this.selector().getCriterion(ETH_SRC);
144 this.ethDstAddrCriterion = (EthCriterion) this.selector().getCriterion(ETH_DST);
145 this.ipv4ProtoCriterion = (IPProtocolCriterion) this.selector().getCriterion(IP_PROTO);
146 this.ipv4SrcAddrCriterion = (IPCriterion) this.selector().getCriterion(IPV4_SRC);
147 this.ipv4DstAddrCriterion = (IPCriterion) this.selector().getCriterion(IPV4_DST);
Georgios Katsikasda37cc82018-10-02 01:01:30 +0200148 this.ipv4SrcMaskCriterion = (IPCriterion) this.selector().getCriterion(IPV4_SRC);
149 this.ipv4DstMaskCriterion = (IPCriterion) this.selector().getCriterion(IPV4_DST);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200150 this.udpSrcPortCriterion = (UdpPortCriterion) this.selector().getCriterion(UDP_SRC);
151 this.udpDstPortCriterion = (UdpPortCriterion) this.selector().getCriterion(UDP_DST);
152 this.tcpSrcPortCriterion = (TcpPortCriterion) this.selector().getCriterion(TCP_SRC);
153 this.tcpDstPortCriterion = (TcpPortCriterion) this.selector().getCriterion(TCP_DST);
154
155 this.actions = new HashSet<NicRuleAction>();
156 // TODO: Expand this translator with more actions
157 for (Instruction instr : this.treatment().allInstructions()) {
158 if (instr.type() == NOACTION) {
159 this.actions.add(new NicRuleAction(NicRuleAction.Action.DROP));
160 } else if (instr.type() == QUEUE) {
161 SetQueueInstruction queueInstruction = (SetQueueInstruction) instr;
162 this.actions.add(
163 new NicRuleAction(NicRuleAction.Action.QUEUE, queueInstruction.queueId()));
164 this.interfaceNumber = queueInstruction.port().toLong();
165 } else if (instr.type() == METER) {
166 MeterInstruction meterInstruction = (MeterInstruction) instr;
167 this.actions.add(
168 new NicRuleAction(NicRuleAction.Action.METER, meterInstruction.meterId().id()));
169 }
170 }
Georgios Katsikas43ec4702018-10-12 08:46:48 +0200171
172 // This action provides basic rule match counters
Georgios Katsikas1a64c3a2020-06-03 17:30:43 +0200173 this.actions.add(new NicRuleAction(NicRuleAction.Action.COUNT));
Georgios Katsikas70671b32018-07-02 18:47:27 +0200174 }
175
176 @Override
177 public FlowRule flowRule() {
178 return this;
179 }
180
181 @Override
182 public String trafficClassId() {
183 return trafficClassId;
184 }
185
186 @Override
187 public String interfaceName() {
188 return interfaceName;
189 }
190
191 @Override
192 public long interfaceNumber() {
193 return interfaceNumber;
194 }
195
196 @Override
197 public long cpuCoreIndex() {
198 return cpuCoreIndex;
199 }
200
201 @Override
202 public NicRuleScope scope() {
203 return scope;
204 }
205
206 @Override
207 public EthType ethernetType() {
208 return (ethTypeCriterion != null) ?
209 ethTypeCriterion.ethType() : null;
210 }
211
212 @Override
213 public short ethernetTypeValue() {
214 return (ethTypeCriterion != null) ?
215 ethTypeCriterion.ethType().toShort() : -1;
216 }
217
218 @Override
219 public MacAddress ethernetSrcAddress() {
220 return (ethSrcAddrCriterion != null) ?
221 ethSrcAddrCriterion.mac() : null;
222 }
223
224 @Override
225 public MacAddress ethernetDstAddress() {
226 return (ethDstAddrCriterion != null) ?
227 ethDstAddrCriterion.mac() : null;
228 }
229
230 @Override
231 public boolean hasEthernet() {
232 return (ethernetType() != null) ||
233 (ethernetSrcAddress() != null) ||
234 (ethernetDstAddress() != null);
235 }
236
237 @Override
238 public short ipv4Protocol() {
239 return (ipv4ProtoCriterion != null) ?
240 ipv4ProtoCriterion.protocol() : -1;
241 }
242
243 @Override
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200244 public Ip4Address ipv4SrcAddress() {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200245 return (ipv4SrcAddrCriterion != null) ?
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200246 ipv4SrcAddrCriterion.ip().address().getIp4Address() : null;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200247 }
248
249 @Override
250 public Ip4Prefix ipv4SrcMask() {
251 return (ipv4SrcMaskCriterion != null) ?
252 ipv4SrcMaskCriterion.ip().getIp4Prefix() : null;
253 }
254
255 @Override
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200256 public Ip4Address ipv4DstAddress() {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200257 return (ipv4DstAddrCriterion != null) ?
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200258 ipv4DstAddrCriterion.ip().address().getIp4Address() : null;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200259 }
260
261 @Override
262 public Ip4Prefix ipv4DstMask() {
263 return (ipv4DstMaskCriterion != null) ?
264 ipv4DstMaskCriterion.ip().getIp4Prefix() : null;
265 }
266
267 @Override
268 public boolean hasIpv4() {
269 return (ipv4Protocol() > 0) ||
270 (ipv4SrcAddress() != null) ||
271 (ipv4DstAddress() != null);
272 }
273
274 @Override
275 public boolean hasIpv6() {
276 return false;
277 }
278
279 @Override
280 public int sourcePort() {
281 return ((udpSrcPortCriterion != null) ?
282 udpSrcPortCriterion.udpPort().toInt() :
283 ((tcpSrcPortCriterion != null) ?
284 tcpSrcPortCriterion.tcpPort().toInt() : -1));
285 }
286
287 @Override
288 public int destinationPort() {
289 return ((udpDstPortCriterion != null) ?
290 udpDstPortCriterion.udpPort().toInt() :
291 ((tcpDstPortCriterion != null) ?
292 tcpDstPortCriterion.tcpPort().toInt() : -1));
293 }
294
295 @Override
296 public boolean hasUdp() {
297 return (udpSrcPortCriterion != null) || (udpDstPortCriterion != null);
298 }
299
300 @Override
301 public boolean hasTcp() {
302 return (tcpSrcPortCriterion != null) || (tcpDstPortCriterion != null);
303 }
304
305 @Override
306 public boolean hasTransport() {
307 return (sourcePort() > 0) || (destinationPort() > 0);
308 }
309
310 @Override
Georgios Katsikas6dc11c12018-12-20 08:43:29 +0100311 public boolean isFullWildcard() {
312 if (((ipv4SrcAddress() != null) && !ipv4SrcAddress().isZero()) ||
313 ((ipv4DstAddress() != null) && !ipv4DstAddress().isZero()) ||
314 (ipv4Protocol() > 0) || (sourcePort() > 0) || (destinationPort() > 0)) {
Georgios Katsikas332985d2019-01-21 13:23:26 +0100315 return false;
Georgios Katsikas6dc11c12018-12-20 08:43:29 +0100316 }
Georgios Katsikas332985d2019-01-21 13:23:26 +0100317 return true;
Georgios Katsikas6dc11c12018-12-20 08:43:29 +0100318 }
319
320 @Override
Georgios Katsikas70671b32018-07-02 18:47:27 +0200321 public Set<NicRuleAction> actions() {
322 return actions;
323 }
324
325 @Override
326 public void addAction(NicRuleAction action) {
327 checkNotNull(action, "Cannot add a NULL NIC rule action");
328 if (actions == null) {
329 actions = new HashSet<NicRuleAction>();
330 }
331 actions.add(action);
332 }
333
334 @Override
335 public long queueNumber() {
336 for (NicRuleAction action : actions) {
337 if (action.actionType() == NicRuleAction.Action.QUEUE) {
338 return action.actionValue();
339 }
340 }
341
342 return (long) -1;
343 }
344
345 @Override
346 public abstract String createRule();
347
348 @Override
349 public abstract String removeRule();
350
351 @Override
352 public abstract String ruleBody();
353
354 @Override
355 public boolean equals(Object obj) {
356 if (this == obj) {
357 return true;
358 }
359
360 if (obj instanceof DefaultNicFlowRule) {
361 DefaultNicFlowRule that = (DefaultNicFlowRule) obj;
362 return Objects.equals(trafficClassId, that.trafficClassId) &&
363 Objects.equals(interfaceName, that.interfaceName) &&
364 Objects.equals(interfaceNumber, that.interfaceNumber) &&
365 Objects.equals(cpuCoreIndex, that.cpuCoreIndex) &&
366 Objects.equals(scope, that.scope) &&
367 Objects.equals(actions, that.actions) &&
368 Objects.equals(deviceId(), that.deviceId()) &&
369 Objects.equals(id(), that.id()) &&
370 Objects.equals(selector(), that.selector());
371 }
372
373 return false;
374 }
375
376 @Override
377 public int hashCode() {
378 return Objects.hash(
379 trafficClassId, interfaceName, interfaceNumber,
380 cpuCoreIndex, scope, deviceId(), id(), selector()
381 );
382 }
383
384 @Override
385 public String toString() {
386 return toStringHelper(this)
387 .omitNullValues()
388 .add("Device ID", deviceId())
389 .add("Traffic class ID", trafficClassId())
390 .add("Flow ID", id())
391 .add("Interface name", interfaceName())
392 .add("Interface number", interfaceNumber())
393 .add("CPU core index", cpuCoreIndex())
394 .add("Scope", scope())
395 .add("Traffic selector", selector())
396 .add("Traffic treatment", treatment())
397 .add("Priority", priority())
398 .add("Ethernet type", ethernetTypeValue())
399 .add("Ethernet address source", ethernetSrcAddress())
400 .add("Ethernet address destination", ethernetDstAddress())
401 .add("IP protocol", ipv4Protocol())
402 .add("IP address source", ipv4SrcAddress())
403 .add("IP mask source", ipv4SrcMask())
404 .add("IP address destination", ipv4DstAddress())
405 .add("IP mask destination", ipv4DstMask())
406 .add("Source port", sourcePort())
407 .add("Destination port", destinationPort())
408 .add("Actions", actions())
409 .toString();
410 }
411
412
413 public abstract static class Builder implements NicFlowRule.Builder {
414
415 protected FlowRule flowRule;
416
417 protected String trafficClassId;
418 protected String interfaceName;
419 protected long interfaceNumber;
420 protected long cpuCoreIndex;
421 protected NicRuleScope scope;
422
423 protected EthTypeCriterion ethTypeCriterion;
424 protected EthCriterion ethSrcAddrCriterion;
425 protected EthCriterion ethDstAddrCriterion;
426
427 protected IPProtocolCriterion ipv4ProtoCriterion;
428 protected IPCriterion ipv4SrcAddrCriterion;
429 protected IPCriterion ipv4SrcMaskCriterion;
430 protected IPCriterion ipv4DstAddrCriterion;
431 protected IPCriterion ipv4DstMaskCriterion;
432
433 protected UdpPortCriterion udpSrcPortCriterion;
434 protected UdpPortCriterion udpDstPortCriterion;
435 protected TcpPortCriterion tcpSrcPortCriterion;
436 protected TcpPortCriterion tcpDstPortCriterion;
437
438 protected Set<NicRuleAction> actions;
439
440 protected static final String DEFAULT_TRAFFIC_CLASS_ID = "tc:00001";
441 protected static final long DEFAULT_INTERFACE_NB = (long) 0;
442 protected static final long DEFAULT_CPU_CORE_INDEX = (long) 0;
443 protected static final NicRuleScope DEFAULT_RULE_SCOPE =
444 NicRuleScope.INGRESS;
445
446 protected Builder() {
447 this.flowRule = null;
448
449 this.trafficClassId = null;
450 this.interfaceName = "";
451 this.interfaceNumber = DEFAULT_INTERFACE_NB;
452 this.cpuCoreIndex = DEFAULT_CPU_CORE_INDEX;
453 this.scope = DEFAULT_RULE_SCOPE;
454
455 this.ethTypeCriterion = null;
456 this.ethSrcAddrCriterion = null;
457 this.ethDstAddrCriterion = null;
458 this.ipv4ProtoCriterion = null;
459 this.ipv4SrcAddrCriterion = null;
460 this.ipv4SrcMaskCriterion = null;
461 this.ipv4DstAddrCriterion = null;
462 this.ipv4DstMaskCriterion = null;
463 this.udpSrcPortCriterion = null;
464 this.udpDstPortCriterion = null;
465 this.tcpSrcPortCriterion = null;
466 this.tcpDstPortCriterion = null;
467
468 this.actions = new HashSet<NicRuleAction>();
469 }
470
471 @Override
472 public Builder fromFlowRule(FlowRule flowRule) {
473 this.flowRule = flowRule;
474 return this;
475 }
476
477 @Override
478 public Builder withTrafficClassId(String trafficClassId) {
479 this.trafficClassId = trafficClassId;
480 return this;
481 }
482
483 @Override
484 public Builder withInterfaceName(String interfaceName) {
485 this.interfaceName = interfaceName;
486 return this;
487 }
488
489 @Override
490 public Builder withInterfaceNumber(long interfaceNumber) {
491 this.interfaceNumber = interfaceNumber;
492 return this;
493 }
494
495 @Override
496 public Builder assignedToCpuCore(long cpuCoreIndex) {
497 this.cpuCoreIndex = cpuCoreIndex;
498 return this;
499 }
500
501 @Override
502 public Builder withScope(NicRuleScope scope) {
503 this.scope = scope;
504 return this;
505 }
506
507 @Override
508 public abstract NicFlowRule build();
509
510 }
511
512}