blob: 019b875f169ebde604d6402cfa00891216aa662a [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 }
Georgios Katsikas43ec4702018-10-12 08:46:48 +0200170
171 // This action provides basic rule match counters
172 this.actions.add(new NicRuleAction(NicRuleAction.Action.COUNT));
Georgios Katsikas70671b32018-07-02 18:47:27 +0200173 }
174
175 @Override
176 public FlowRule flowRule() {
177 return this;
178 }
179
180 @Override
181 public String trafficClassId() {
182 return trafficClassId;
183 }
184
185 @Override
186 public String interfaceName() {
187 return interfaceName;
188 }
189
190 @Override
191 public long interfaceNumber() {
192 return interfaceNumber;
193 }
194
195 @Override
196 public long cpuCoreIndex() {
197 return cpuCoreIndex;
198 }
199
200 @Override
201 public NicRuleScope scope() {
202 return scope;
203 }
204
205 @Override
206 public EthType ethernetType() {
207 return (ethTypeCriterion != null) ?
208 ethTypeCriterion.ethType() : null;
209 }
210
211 @Override
212 public short ethernetTypeValue() {
213 return (ethTypeCriterion != null) ?
214 ethTypeCriterion.ethType().toShort() : -1;
215 }
216
217 @Override
218 public MacAddress ethernetSrcAddress() {
219 return (ethSrcAddrCriterion != null) ?
220 ethSrcAddrCriterion.mac() : null;
221 }
222
223 @Override
224 public MacAddress ethernetDstAddress() {
225 return (ethDstAddrCriterion != null) ?
226 ethDstAddrCriterion.mac() : null;
227 }
228
229 @Override
230 public boolean hasEthernet() {
231 return (ethernetType() != null) ||
232 (ethernetSrcAddress() != null) ||
233 (ethernetDstAddress() != null);
234 }
235
236 @Override
237 public short ipv4Protocol() {
238 return (ipv4ProtoCriterion != null) ?
239 ipv4ProtoCriterion.protocol() : -1;
240 }
241
242 @Override
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200243 public Ip4Address ipv4SrcAddress() {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200244 return (ipv4SrcAddrCriterion != null) ?
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200245 ipv4SrcAddrCriterion.ip().address().getIp4Address() : null;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200246 }
247
248 @Override
249 public Ip4Prefix ipv4SrcMask() {
250 return (ipv4SrcMaskCriterion != null) ?
251 ipv4SrcMaskCriterion.ip().getIp4Prefix() : null;
252 }
253
254 @Override
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200255 public Ip4Address ipv4DstAddress() {
Georgios Katsikas70671b32018-07-02 18:47:27 +0200256 return (ipv4DstAddrCriterion != null) ?
Georgios Katsikas3e6d0f02018-07-25 17:04:04 +0200257 ipv4DstAddrCriterion.ip().address().getIp4Address() : null;
Georgios Katsikas70671b32018-07-02 18:47:27 +0200258 }
259
260 @Override
261 public Ip4Prefix ipv4DstMask() {
262 return (ipv4DstMaskCriterion != null) ?
263 ipv4DstMaskCriterion.ip().getIp4Prefix() : null;
264 }
265
266 @Override
267 public boolean hasIpv4() {
268 return (ipv4Protocol() > 0) ||
269 (ipv4SrcAddress() != null) ||
270 (ipv4DstAddress() != null);
271 }
272
273 @Override
274 public boolean hasIpv6() {
275 return false;
276 }
277
278 @Override
279 public int sourcePort() {
280 return ((udpSrcPortCriterion != null) ?
281 udpSrcPortCriterion.udpPort().toInt() :
282 ((tcpSrcPortCriterion != null) ?
283 tcpSrcPortCriterion.tcpPort().toInt() : -1));
284 }
285
286 @Override
287 public int destinationPort() {
288 return ((udpDstPortCriterion != null) ?
289 udpDstPortCriterion.udpPort().toInt() :
290 ((tcpDstPortCriterion != null) ?
291 tcpDstPortCriterion.tcpPort().toInt() : -1));
292 }
293
294 @Override
295 public boolean hasUdp() {
296 return (udpSrcPortCriterion != null) || (udpDstPortCriterion != null);
297 }
298
299 @Override
300 public boolean hasTcp() {
301 return (tcpSrcPortCriterion != null) || (tcpDstPortCriterion != null);
302 }
303
304 @Override
305 public boolean hasTransport() {
306 return (sourcePort() > 0) || (destinationPort() > 0);
307 }
308
309 @Override
310 public Set<NicRuleAction> actions() {
311 return actions;
312 }
313
314 @Override
315 public void addAction(NicRuleAction action) {
316 checkNotNull(action, "Cannot add a NULL NIC rule action");
317 if (actions == null) {
318 actions = new HashSet<NicRuleAction>();
319 }
320 actions.add(action);
321 }
322
323 @Override
324 public long queueNumber() {
325 for (NicRuleAction action : actions) {
326 if (action.actionType() == NicRuleAction.Action.QUEUE) {
327 return action.actionValue();
328 }
329 }
330
331 return (long) -1;
332 }
333
334 @Override
335 public abstract String createRule();
336
337 @Override
338 public abstract String removeRule();
339
340 @Override
341 public abstract String ruleBody();
342
343 @Override
344 public boolean equals(Object obj) {
345 if (this == obj) {
346 return true;
347 }
348
349 if (obj instanceof DefaultNicFlowRule) {
350 DefaultNicFlowRule that = (DefaultNicFlowRule) obj;
351 return Objects.equals(trafficClassId, that.trafficClassId) &&
352 Objects.equals(interfaceName, that.interfaceName) &&
353 Objects.equals(interfaceNumber, that.interfaceNumber) &&
354 Objects.equals(cpuCoreIndex, that.cpuCoreIndex) &&
355 Objects.equals(scope, that.scope) &&
356 Objects.equals(actions, that.actions) &&
357 Objects.equals(deviceId(), that.deviceId()) &&
358 Objects.equals(id(), that.id()) &&
359 Objects.equals(selector(), that.selector());
360 }
361
362 return false;
363 }
364
365 @Override
366 public int hashCode() {
367 return Objects.hash(
368 trafficClassId, interfaceName, interfaceNumber,
369 cpuCoreIndex, scope, deviceId(), id(), selector()
370 );
371 }
372
373 @Override
374 public String toString() {
375 return toStringHelper(this)
376 .omitNullValues()
377 .add("Device ID", deviceId())
378 .add("Traffic class ID", trafficClassId())
379 .add("Flow ID", id())
380 .add("Interface name", interfaceName())
381 .add("Interface number", interfaceNumber())
382 .add("CPU core index", cpuCoreIndex())
383 .add("Scope", scope())
384 .add("Traffic selector", selector())
385 .add("Traffic treatment", treatment())
386 .add("Priority", priority())
387 .add("Ethernet type", ethernetTypeValue())
388 .add("Ethernet address source", ethernetSrcAddress())
389 .add("Ethernet address destination", ethernetDstAddress())
390 .add("IP protocol", ipv4Protocol())
391 .add("IP address source", ipv4SrcAddress())
392 .add("IP mask source", ipv4SrcMask())
393 .add("IP address destination", ipv4DstAddress())
394 .add("IP mask destination", ipv4DstMask())
395 .add("Source port", sourcePort())
396 .add("Destination port", destinationPort())
397 .add("Actions", actions())
398 .toString();
399 }
400
401
402 public abstract static class Builder implements NicFlowRule.Builder {
403
404 protected FlowRule flowRule;
405
406 protected String trafficClassId;
407 protected String interfaceName;
408 protected long interfaceNumber;
409 protected long cpuCoreIndex;
410 protected NicRuleScope scope;
411
412 protected EthTypeCriterion ethTypeCriterion;
413 protected EthCriterion ethSrcAddrCriterion;
414 protected EthCriterion ethDstAddrCriterion;
415
416 protected IPProtocolCriterion ipv4ProtoCriterion;
417 protected IPCriterion ipv4SrcAddrCriterion;
418 protected IPCriterion ipv4SrcMaskCriterion;
419 protected IPCriterion ipv4DstAddrCriterion;
420 protected IPCriterion ipv4DstMaskCriterion;
421
422 protected UdpPortCriterion udpSrcPortCriterion;
423 protected UdpPortCriterion udpDstPortCriterion;
424 protected TcpPortCriterion tcpSrcPortCriterion;
425 protected TcpPortCriterion tcpDstPortCriterion;
426
427 protected Set<NicRuleAction> actions;
428
429 protected static final String DEFAULT_TRAFFIC_CLASS_ID = "tc:00001";
430 protected static final long DEFAULT_INTERFACE_NB = (long) 0;
431 protected static final long DEFAULT_CPU_CORE_INDEX = (long) 0;
432 protected static final NicRuleScope DEFAULT_RULE_SCOPE =
433 NicRuleScope.INGRESS;
434
435 protected Builder() {
436 this.flowRule = null;
437
438 this.trafficClassId = null;
439 this.interfaceName = "";
440 this.interfaceNumber = DEFAULT_INTERFACE_NB;
441 this.cpuCoreIndex = DEFAULT_CPU_CORE_INDEX;
442 this.scope = DEFAULT_RULE_SCOPE;
443
444 this.ethTypeCriterion = null;
445 this.ethSrcAddrCriterion = null;
446 this.ethDstAddrCriterion = null;
447 this.ipv4ProtoCriterion = null;
448 this.ipv4SrcAddrCriterion = null;
449 this.ipv4SrcMaskCriterion = null;
450 this.ipv4DstAddrCriterion = null;
451 this.ipv4DstMaskCriterion = null;
452 this.udpSrcPortCriterion = null;
453 this.udpDstPortCriterion = null;
454 this.tcpSrcPortCriterion = null;
455 this.tcpDstPortCriterion = null;
456
457 this.actions = new HashSet<NicRuleAction>();
458 }
459
460 @Override
461 public Builder fromFlowRule(FlowRule flowRule) {
462 this.flowRule = flowRule;
463 return this;
464 }
465
466 @Override
467 public Builder withTrafficClassId(String trafficClassId) {
468 this.trafficClassId = trafficClassId;
469 return this;
470 }
471
472 @Override
473 public Builder withInterfaceName(String interfaceName) {
474 this.interfaceName = interfaceName;
475 return this;
476 }
477
478 @Override
479 public Builder withInterfaceNumber(long interfaceNumber) {
480 this.interfaceNumber = interfaceNumber;
481 return this;
482 }
483
484 @Override
485 public Builder assignedToCpuCore(long cpuCoreIndex) {
486 this.cpuCoreIndex = cpuCoreIndex;
487 return this;
488 }
489
490 @Override
491 public Builder withScope(NicRuleScope scope) {
492 this.scope = scope;
493 return this;
494 }
495
496 @Override
497 public abstract NicFlowRule build();
498
499 }
500
501}