blob: abbf0b84d475cd7d7db075849094b4856e9b1166 [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;
48import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_TYPE;
49import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_SRC;
50import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_DST;
51import static org.onosproject.net.flow.criteria.Criterion.Type.IP_PROTO;
52import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_SRC;
53import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
54import static org.onosproject.net.flow.criteria.Criterion.Type.UDP_SRC;
55import static org.onosproject.net.flow.criteria.Criterion.Type.UDP_DST;
56import static org.onosproject.net.flow.criteria.Criterion.Type.TCP_SRC;
57import static org.onosproject.net.flow.criteria.Criterion.Type.TCP_DST;
58import static org.onosproject.net.flow.instructions.Instruction.Type.NOACTION;
59import static org.onosproject.net.flow.instructions.Instruction.Type.QUEUE;
60import static org.onosproject.net.flow.instructions.Instruction.Type.METER;
61import static org.slf4j.LoggerFactory.getLogger;
62
63/**
64 * Implementation of an abstract NIC rule.
65 */
66public abstract class DefaultNicFlowRule extends DefaultFlowRule implements NicFlowRule {
67
68 protected static final Logger log = getLogger(DefaultNicFlowRule.class);
69
70 // Additional members that a NIC rule requires
71 protected final String trafficClassId;
72 protected final String interfaceName;
73 protected long interfaceNumber;
74 protected long cpuCoreIndex;
75 protected final NicRuleScope scope;
76
77 // Derive from FlowRule's selector
78 protected EthTypeCriterion ethTypeCriterion;
79 protected EthCriterion ethSrcAddrCriterion;
80 protected EthCriterion ethDstAddrCriterion;
81
82 protected IPProtocolCriterion ipv4ProtoCriterion;
83 protected IPCriterion ipv4SrcAddrCriterion;
84 protected IPCriterion ipv4SrcMaskCriterion;
85 protected IPCriterion ipv4DstAddrCriterion;
86 protected IPCriterion ipv4DstMaskCriterion;
87
88 protected UdpPortCriterion udpSrcPortCriterion;
89 protected UdpPortCriterion udpDstPortCriterion;
90 protected TcpPortCriterion tcpSrcPortCriterion;
91 protected TcpPortCriterion tcpDstPortCriterion;
92
93 // Derives from FlowRule's treatment
94 protected Set<NicRuleAction> actions;
95
96 protected DefaultNicFlowRule(
97 FlowRule flowRule,
98 String trafficClassId,
99 String interfaceName,
100 long interfaceNumber,
101 long cpuCoreIndex,
102 NicRuleScope scope) {
103 super(flowRule);
104
Thomas Vachuska98f4e2c2018-07-09 10:45:04 -0700105 checkArgument(!Strings.isNullOrEmpty(trafficClassId),
Georgios Katsikas70671b32018-07-02 18:47:27 +0200106 "NIC rule's traffic class ID is NULL or empty");
107 checkNotNull(interfaceName,
108 "NIC rule's interface name is NULL");
109 checkArgument(interfaceNumber >= 0,
110 "NIC rule's interface number must not be negative");
111 checkArgument(cpuCoreIndex >= 0,
112 "NIC rule's CPU core index must not be negative");
113 checkNotNull(scope, "NIC rule's scope is NULL");
114
115 this.trafficClassId = trafficClassId;
116 this.interfaceName = interfaceName;
117 this.interfaceNumber = interfaceNumber;
118 this.cpuCoreIndex = cpuCoreIndex;
119 this.scope = scope;
120
121 this.populate();
122 }
123
124 protected DefaultNicFlowRule(FlowRule flowRule) {
125 super(flowRule);
126
127 this.trafficClassId = Builder.DEFAULT_TRAFFIC_CLASS_ID;
128 this.interfaceName = "";
129 this.interfaceNumber = Builder.DEFAULT_INTERFACE_NB;
130 this.cpuCoreIndex = Builder.DEFAULT_CPU_CORE_INDEX;
131 this.scope = Builder.DEFAULT_RULE_SCOPE;
132
133 this.populate();
134 }
135
136 /**
137 * Parses FlowRule's traffic selector and treatment
138 * and keeps relevant information for this NIC rule.
139 */
140 private void populate() {
141 this.ethTypeCriterion = (EthTypeCriterion) this.selector().getCriterion(ETH_TYPE);
142 this.ethSrcAddrCriterion = (EthCriterion) this.selector().getCriterion(ETH_SRC);
143 this.ethDstAddrCriterion = (EthCriterion) this.selector().getCriterion(ETH_DST);
144 this.ipv4ProtoCriterion = (IPProtocolCriterion) this.selector().getCriterion(IP_PROTO);
145 this.ipv4SrcAddrCriterion = (IPCriterion) this.selector().getCriterion(IPV4_SRC);
146 this.ipv4DstAddrCriterion = (IPCriterion) this.selector().getCriterion(IPV4_DST);
Georgios Katsikasda37cc82018-10-02 01:01:30 +0200147 this.ipv4SrcMaskCriterion = (IPCriterion) this.selector().getCriterion(IPV4_SRC);
148 this.ipv4DstMaskCriterion = (IPCriterion) this.selector().getCriterion(IPV4_DST);
Georgios Katsikas70671b32018-07-02 18:47:27 +0200149 this.udpSrcPortCriterion = (UdpPortCriterion) this.selector().getCriterion(UDP_SRC);
150 this.udpDstPortCriterion = (UdpPortCriterion) this.selector().getCriterion(UDP_DST);
151 this.tcpSrcPortCriterion = (TcpPortCriterion) this.selector().getCriterion(TCP_SRC);
152 this.tcpDstPortCriterion = (TcpPortCriterion) this.selector().getCriterion(TCP_DST);
153
154 this.actions = new HashSet<NicRuleAction>();
155 // TODO: Expand this translator with more actions
156 for (Instruction instr : this.treatment().allInstructions()) {
157 if (instr.type() == NOACTION) {
158 this.actions.add(new NicRuleAction(NicRuleAction.Action.DROP));
159 } else if (instr.type() == QUEUE) {
160 SetQueueInstruction queueInstruction = (SetQueueInstruction) instr;
161 this.actions.add(
162 new NicRuleAction(NicRuleAction.Action.QUEUE, queueInstruction.queueId()));
163 this.interfaceNumber = queueInstruction.port().toLong();
164 } else if (instr.type() == METER) {
165 MeterInstruction meterInstruction = (MeterInstruction) instr;
166 this.actions.add(
167 new NicRuleAction(NicRuleAction.Action.METER, meterInstruction.meterId().id()));
168 }
169 }
170 }
171
172 @Override
173 public FlowRule flowRule() {
174 return this;
175 }
176
177 @Override
178 public String trafficClassId() {
179 return trafficClassId;
180 }
181
182 @Override
183 public String interfaceName() {
184 return interfaceName;
185 }
186
187 @Override
188 public long interfaceNumber() {
189 return interfaceNumber;
190 }
191
192 @Override
193 public long cpuCoreIndex() {
194 return cpuCoreIndex;
195 }
196
197 @Override
198 public NicRuleScope scope() {
199 return scope;
200 }
201
202 @Override
203 public EthType ethernetType() {
204 return (ethTypeCriterion != null) ?
205 ethTypeCriterion.ethType() : null;
206 }
207
208 @Override
209 public short ethernetTypeValue() {
210 return (ethTypeCriterion != null) ?
211 ethTypeCriterion.ethType().toShort() : -1;
212 }
213
214 @Override
215 public MacAddress ethernetSrcAddress() {
216 return (ethSrcAddrCriterion != null) ?
217 ethSrcAddrCriterion.mac() : null;
218 }
219
220 @Override
221 public MacAddress ethernetDstAddress() {
222 return (ethDstAddrCriterion != null) ?
223 ethDstAddrCriterion.mac() : null;
224 }
225
226 @Override
227 public boolean hasEthernet() {
228 return (ethernetType() != null) ||
229 (ethernetSrcAddress() != null) ||
230 (ethernetDstAddress() != null);
231 }
232
233 @Override
234 public short ipv4Protocol() {
235 return (ipv4ProtoCriterion != null) ?
236 ipv4ProtoCriterion.protocol() : -1;
237 }
238
239 @Override
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200240 public Ip4Address ipv4SrcAddress() {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200241 return (ipv4SrcAddrCriterion != null) ?
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200242 ipv4SrcAddrCriterion.ip().address().getIp4Address() : null;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200243 }
244
245 @Override
246 public Ip4Prefix ipv4SrcMask() {
247 return (ipv4SrcMaskCriterion != null) ?
248 ipv4SrcMaskCriterion.ip().getIp4Prefix() : null;
249 }
250
251 @Override
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200252 public Ip4Address ipv4DstAddress() {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200253 return (ipv4DstAddrCriterion != null) ?
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200254 ipv4DstAddrCriterion.ip().address().getIp4Address() : null;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200255 }
256
257 @Override
258 public Ip4Prefix ipv4DstMask() {
259 return (ipv4DstMaskCriterion != null) ?
260 ipv4DstMaskCriterion.ip().getIp4Prefix() : null;
261 }
262
263 @Override
264 public boolean hasIpv4() {
265 return (ipv4Protocol() > 0) ||
266 (ipv4SrcAddress() != null) ||
267 (ipv4DstAddress() != null);
268 }
269
270 @Override
271 public boolean hasIpv6() {
272 return false;
273 }
274
275 @Override
276 public int sourcePort() {
277 return ((udpSrcPortCriterion != null) ?
278 udpSrcPortCriterion.udpPort().toInt() :
279 ((tcpSrcPortCriterion != null) ?
280 tcpSrcPortCriterion.tcpPort().toInt() : -1));
281 }
282
283 @Override
284 public int destinationPort() {
285 return ((udpDstPortCriterion != null) ?
286 udpDstPortCriterion.udpPort().toInt() :
287 ((tcpDstPortCriterion != null) ?
288 tcpDstPortCriterion.tcpPort().toInt() : -1));
289 }
290
291 @Override
292 public boolean hasUdp() {
293 return (udpSrcPortCriterion != null) || (udpDstPortCriterion != null);
294 }
295
296 @Override
297 public boolean hasTcp() {
298 return (tcpSrcPortCriterion != null) || (tcpDstPortCriterion != null);
299 }
300
301 @Override
302 public boolean hasTransport() {
303 return (sourcePort() > 0) || (destinationPort() > 0);
304 }
305
306 @Override
307 public Set<NicRuleAction> actions() {
308 return actions;
309 }
310
311 @Override
312 public void addAction(NicRuleAction action) {
313 checkNotNull(action, "Cannot add a NULL NIC rule action");
314 if (actions == null) {
315 actions = new HashSet<NicRuleAction>();
316 }
317 actions.add(action);
318 }
319
320 @Override
321 public long queueNumber() {
322 for (NicRuleAction action : actions) {
323 if (action.actionType() == NicRuleAction.Action.QUEUE) {
324 return action.actionValue();
325 }
326 }
327
328 return (long) -1;
329 }
330
331 @Override
332 public abstract String createRule();
333
334 @Override
335 public abstract String removeRule();
336
337 @Override
338 public abstract String ruleBody();
339
340 @Override
341 public boolean equals(Object obj) {
342 if (this == obj) {
343 return true;
344 }
345
346 if (obj instanceof DefaultNicFlowRule) {
347 DefaultNicFlowRule that = (DefaultNicFlowRule) obj;
348 return Objects.equals(trafficClassId, that.trafficClassId) &&
349 Objects.equals(interfaceName, that.interfaceName) &&
350 Objects.equals(interfaceNumber, that.interfaceNumber) &&
351 Objects.equals(cpuCoreIndex, that.cpuCoreIndex) &&
352 Objects.equals(scope, that.scope) &&
353 Objects.equals(actions, that.actions) &&
354 Objects.equals(deviceId(), that.deviceId()) &&
355 Objects.equals(id(), that.id()) &&
356 Objects.equals(selector(), that.selector());
357 }
358
359 return false;
360 }
361
362 @Override
363 public int hashCode() {
364 return Objects.hash(
365 trafficClassId, interfaceName, interfaceNumber,
366 cpuCoreIndex, scope, deviceId(), id(), selector()
367 );
368 }
369
370 @Override
371 public String toString() {
372 return toStringHelper(this)
373 .omitNullValues()
374 .add("Device ID", deviceId())
375 .add("Traffic class ID", trafficClassId())
376 .add("Flow ID", id())
377 .add("Interface name", interfaceName())
378 .add("Interface number", interfaceNumber())
379 .add("CPU core index", cpuCoreIndex())
380 .add("Scope", scope())
381 .add("Traffic selector", selector())
382 .add("Traffic treatment", treatment())
383 .add("Priority", priority())
384 .add("Ethernet type", ethernetTypeValue())
385 .add("Ethernet address source", ethernetSrcAddress())
386 .add("Ethernet address destination", ethernetDstAddress())
387 .add("IP protocol", ipv4Protocol())
388 .add("IP address source", ipv4SrcAddress())
389 .add("IP mask source", ipv4SrcMask())
390 .add("IP address destination", ipv4DstAddress())
391 .add("IP mask destination", ipv4DstMask())
392 .add("Source port", sourcePort())
393 .add("Destination port", destinationPort())
394 .add("Actions", actions())
395 .toString();
396 }
397
398
399 public abstract static class Builder implements NicFlowRule.Builder {
400
401 protected FlowRule flowRule;
402
403 protected String trafficClassId;
404 protected String interfaceName;
405 protected long interfaceNumber;
406 protected long cpuCoreIndex;
407 protected NicRuleScope scope;
408
409 protected EthTypeCriterion ethTypeCriterion;
410 protected EthCriterion ethSrcAddrCriterion;
411 protected EthCriterion ethDstAddrCriterion;
412
413 protected IPProtocolCriterion ipv4ProtoCriterion;
414 protected IPCriterion ipv4SrcAddrCriterion;
415 protected IPCriterion ipv4SrcMaskCriterion;
416 protected IPCriterion ipv4DstAddrCriterion;
417 protected IPCriterion ipv4DstMaskCriterion;
418
419 protected UdpPortCriterion udpSrcPortCriterion;
420 protected UdpPortCriterion udpDstPortCriterion;
421 protected TcpPortCriterion tcpSrcPortCriterion;
422 protected TcpPortCriterion tcpDstPortCriterion;
423
424 protected Set<NicRuleAction> actions;
425
426 protected static final String DEFAULT_TRAFFIC_CLASS_ID = "tc:00001";
427 protected static final long DEFAULT_INTERFACE_NB = (long) 0;
428 protected static final long DEFAULT_CPU_CORE_INDEX = (long) 0;
429 protected static final NicRuleScope DEFAULT_RULE_SCOPE =
430 NicRuleScope.INGRESS;
431
432 protected Builder() {
433 this.flowRule = null;
434
435 this.trafficClassId = null;
436 this.interfaceName = "";
437 this.interfaceNumber = DEFAULT_INTERFACE_NB;
438 this.cpuCoreIndex = DEFAULT_CPU_CORE_INDEX;
439 this.scope = DEFAULT_RULE_SCOPE;
440
441 this.ethTypeCriterion = null;
442 this.ethSrcAddrCriterion = null;
443 this.ethDstAddrCriterion = null;
444 this.ipv4ProtoCriterion = null;
445 this.ipv4SrcAddrCriterion = null;
446 this.ipv4SrcMaskCriterion = null;
447 this.ipv4DstAddrCriterion = null;
448 this.ipv4DstMaskCriterion = null;
449 this.udpSrcPortCriterion = null;
450 this.udpDstPortCriterion = null;
451 this.tcpSrcPortCriterion = null;
452 this.tcpDstPortCriterion = null;
453
454 this.actions = new HashSet<NicRuleAction>();
455 }
456
457 @Override
458 public Builder fromFlowRule(FlowRule flowRule) {
459 this.flowRule = flowRule;
460 return this;
461 }
462
463 @Override
464 public Builder withTrafficClassId(String trafficClassId) {
465 this.trafficClassId = trafficClassId;
466 return this;
467 }
468
469 @Override
470 public Builder withInterfaceName(String interfaceName) {
471 this.interfaceName = interfaceName;
472 return this;
473 }
474
475 @Override
476 public Builder withInterfaceNumber(long interfaceNumber) {
477 this.interfaceNumber = interfaceNumber;
478 return this;
479 }
480
481 @Override
482 public Builder assignedToCpuCore(long cpuCoreIndex) {
483 this.cpuCoreIndex = cpuCoreIndex;
484 return this;
485 }
486
487 @Override
488 public Builder withScope(NicRuleScope scope) {
489 this.scope = scope;
490 return this;
491 }
492
493 @Override
494 public abstract NicFlowRule build();
495
496 }
497
498}