Server driver implements FlowRuleProgrammable

This patch extends the server device driver with the
ability to manage FlowRule objects on the network interface
cards (NICs) of commodity servers.
With a minimal modification in an existing ONOS class (i.e.,
DefaultFlowRule.java), the server device driver re-uses the
FlowRule and FlowEntry concepts to implement a sub-class
translator that converts FlowRule objects into NicFlowRule
objects.
Currently this new feature supports a handful of possible
NIC rule actions but it can be easily extended in the future.

Addressed comment made by ONOS reviewers and fixed two bugs.
One bug was related to rule installation (ability to send
an array of rules at the same time), while the other bug was
related to the hash code of a NicFlowRule.

Refactoring of this driver according to ONOS reviewers's
comments.

Change-Id: Ie76947df120d6e0df86acf9e5917e237653a8cea
Signed-off-by: Georgios Katsikas <katsikas.gp@gmail.com>
diff --git a/drivers/server/src/main/java/org/onosproject/drivers/server/devices/nic/DefaultDpdkNicFlowRule.java b/drivers/server/src/main/java/org/onosproject/drivers/server/devices/nic/DefaultDpdkNicFlowRule.java
new file mode 100644
index 0000000..5831b79
--- /dev/null
+++ b/drivers/server/src/main/java/org/onosproject/drivers/server/devices/nic/DefaultDpdkNicFlowRule.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.server.devices.nic;
+
+import org.onosproject.net.flow.FlowRule;
+
+import org.onlab.packet.MacAddress;
+
+/**
+ * Implementation of a DPDK-based network interface card (NIC) flow rule.
+ */
+public class DefaultDpdkNicFlowRule extends DefaultNicFlowRule {
+
+    public DefaultDpdkNicFlowRule(
+            FlowRule         flowRule,
+            String           trafficClassId,
+            String           interfaceName,
+            long             interfaceNumber,
+            long             cpuCoreIndex,
+            NicRuleScope     scope) {
+        super(flowRule, trafficClassId, interfaceName, interfaceNumber,
+            cpuCoreIndex, scope);
+    }
+
+    @Override
+    public String createRule() {
+        String rule = "flow create " + Long.toString(this.interfaceNumber) + " ";
+        return rule + ruleBody();
+    }
+
+    @Override
+    public String removeRule() {
+        String rule = "flow remove " + Long.toString(this.interfaceNumber) + " ";
+        return rule + ruleBody();
+    }
+
+    @Override
+    public String ruleBody() {
+        String rule = "";
+
+        rule += this.scope() + " pattern ";
+
+        if (this.hasEthernet()) {
+            rule += "eth ";
+
+            if (this.ethernetType() != null) {
+                rule += "type is " + Integer.toString(this.ethernetTypeValue()) + " ";
+            }
+
+            if (this.ethernetSrcAddress() != null) {
+                rule += "src spec " + this.ethernetSrcAddress().toString() + " ";
+                rule += "src mask " + MacAddress.BROADCAST.toString() + " ";
+            }
+
+            if (this.ethernetDstAddress() != null) {
+                rule += "dst spec " + this.ethernetDstAddress().toString() + " ";
+                rule += "dst mask " + MacAddress.BROADCAST.toString() + " ";
+            }
+
+            rule += "/ ";
+        }
+
+        if (this.hasIpv4()) {
+            rule += "ipv4 ";
+
+            if (this.ipv4Protocol() > 0) {
+                rule += "proto spec " + Integer.toString(this.ipv4Protocol()) + " ";
+                rule += "proto mask 0x0 ";
+            }
+
+            if (this.ipv4SrcAddress() != null) {
+                rule += "src is " + this.ipv4SrcAddress().toString() + " ";
+            }
+
+            if (this.ipv4SrcMask() != null) {
+                rule += "src mask " + this.ipv4SrcMask().toString() + " ";
+            }
+
+            if (this.ipv4DstAddress() != null) {
+                rule += "dst is " + this.ipv4DstAddress().toString() + " ";
+            }
+
+            if (this.ipv4DstMask() != null) {
+                rule += "dst mask " + this.ipv4DstMask().toString() + " ";
+            }
+
+            rule += "/ ";
+        }
+
+        if (this.hasTransport()) {
+
+            if (this.hasUdp()) {
+                rule += "udp ";
+            } else if (this.hasTcp()) {
+                rule += "tcp ";
+            }
+
+            if (this.sourcePort() > 0) {
+                rule += "src is " + Integer.toString(this.sourcePort()) + " ";
+            }
+
+            if (this.destinationPort() > 0) {
+                rule += "dst is " + Integer.toString(this.destinationPort()) + " ";
+            }
+
+            rule += "/ ";
+        }
+
+        rule += "end ";
+
+        if (this.actions() != null) {
+            rule += "actions ";
+
+            for (NicRuleAction action : this.actions()) {
+                rule += action.actionType().toString() + " ";
+
+                // No subsequent field
+                if (action.actionField().isEmpty()) {
+                    continue;
+                }
+
+                // A subsequent field is associated with a value
+                rule += action.actionField() + " ";
+                rule += Long.toString(action.actionValue()) + " ";
+            }
+
+            rule += "/ end";
+        }
+
+        return rule;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return super.equals(obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+
+    /**
+     * Returns a DPDK NIC rule builder.
+     *
+     * @return builder
+     */
+    public static Builder nicRulebuilder() {
+        return new Builder();
+    }
+
+    /**
+     * Default DPDK NIC rule builder.
+     */
+    public static final class Builder extends DefaultNicFlowRule.Builder {
+
+        public Builder() {
+            super();
+        }
+
+        @Override
+        public NicFlowRule build() {
+            return new DefaultDpdkNicFlowRule(
+                flowRule, trafficClassId, interfaceName, interfaceNumber,
+                cpuCoreIndex, scope);
+        }
+
+    }
+
+}