Initial implementation of security group for kubevirt tenant network

Change-Id: If49d03021408a134be01267cc4eee9e0091e3c3d
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java
index a2099e1..79e8351 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java
@@ -34,7 +34,7 @@
     public static final String TENANT_TO_TUNNEL_PREFIX = "i-to-t-";
     public static final String TUNNEL_TO_TENANT_PREFIX = "t-to-i-";
 
-    // flow table index
+    // provider and VLAN integration bridge flow table index
     public static final int STAT_INBOUND_TABLE = 0;
     public static final int VTAP_INBOUND_TABLE = 1;
     public static final int STAT_FLAT_OUTBOUND_TABLE = 10;
@@ -44,9 +44,9 @@
     public static final int FLAT_TABLE = 32;
     public static final int ARP_TABLE = 35;
     public static final int ACL_EGRESS_TABLE = 40;
-    public static final int ACL_INGRESS_TABLE = 44;
-    public static final int CT_TABLE = 45;
     public static final int ACL_RECIRC_TABLE = 43;
+    public static final int ACL_INGRESS_TABLE = 44;
+    public static final int ACL_CT_TABLE = 45;
     public static final int JUMP_TABLE = 50;
     public static final int ROUTING_TABLE = 60;
     public static final int STAT_OUTBOUND_TABLE = 70;
@@ -54,11 +54,15 @@
     public static final int FORWARDING_TABLE = 80;
     public static final int ERROR_TABLE = 100;
 
-    // tenant integration bridge flow table index
+    // tenant (VXLAN/GRE/GENEVE) integration bridge flow table index
     public static final int TENANT_INBOUND_TABLE = 0;
     public static final int TENANT_DHCP_TABLE = 5;
     public static final int TENANT_ARP_TABLE = 30;
     public static final int TENANT_ICMP_TABLE = 35;
+    public static final int TENANT_ACL_EGRESS_TABLE = 40;
+    public static final int TENANT_ACL_RECIRC_TABLE = 43;
+    public static final int TENANT_ACL_INGRESS_TABLE = 44;
+    public static final int TENANT_ACL_CT_TABLE = 45;
     public static final int TENANT_FORWARDING_TABLE = 80;
 
     // tunnel bridge flow table index
@@ -69,8 +73,17 @@
     public static final int PRIORITY_FORWARDING_RULE = 30000;
     public static final int PRIORITY_DHCP_RULE = 42000;
     public static final int PRIORITY_ARP_GATEWAY_RULE = 41000;
+    public static final int PRIORITY_ARP_DEFAULT_RULE = 40000;
     public static final int PRIORITY_TUNNEL_RULE = 31000;
 
+    public static final int PRIORITY_IP_INGRESS_RULE = 19000;
+    public static final int PRIORITY_IP_EGRESS_RULE = 18000;
+    public static final int PRIORITY_ACL_RULE = 31000;
+    public static final int PRIORITY_ACL_INGRESS_RULE = 30000;
+    public static final int PRIORITY_CT_HOOK_RULE = 30500;
+    public static final int PRIORITY_CT_RULE = 32000;
+    public static final int PRIORITY_CT_DROP_RULE = 32500;
+
     // CLI item length
     public static final int CLI_ID_LENGTH = 30;
     public static final int CLI_NAME_LENGTH = 30;
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetwork.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetwork.java
index 35d367f..73c96f0 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetwork.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetwork.java
@@ -30,6 +30,7 @@
 import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_TO_TUNNEL_PREFIX;
 import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
 import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
 import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.GENEVE;
@@ -157,9 +158,7 @@
     public DeviceId tenantDeviceId(String hostname) {
         if (type == VXLAN || type == GRE || type == GENEVE) {
             String dpid = genDpidFromName(tenantBridgeName() + "-" + hostname);
-            if (dpid != null) {
-                return DeviceId.deviceId(dpid);
-            }
+            return DeviceId.deviceId(dpid);
         }
         return null;
     }
@@ -176,6 +175,17 @@
     }
 
     @Override
+    public PortNumber tenantToTunnelPort(DeviceId deviceId) {
+        String portName = TENANT_TO_TUNNEL_PREFIX + segmentIdHex(segmentId);
+        Port port = port(deviceId, portName);
+        if (port == null) {
+            return null;
+        } else {
+            return port.number();
+        }
+    }
+
+    @Override
     public boolean equals(Object o) {
         if (this == o) {
             return true;
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
index 992eb90..2a7385f 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
@@ -16,12 +16,17 @@
 package org.onosproject.kubevirtnetworking.api;
 
 import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import org.onlab.osgi.DefaultServiceDirectory;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
+import org.onosproject.kubevirtnode.api.KubevirtNode;
+import org.onosproject.kubevirtnode.api.KubevirtNodeService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 
 import java.util.Objects;
+import java.util.Set;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
@@ -37,6 +42,7 @@
     private final IpAddress ipAddress;
     private final DeviceId deviceId;
     private final PortNumber portNumber;
+    private final Set<String> securityGroups;
 
     /**
      * Default constructor.
@@ -46,14 +52,16 @@
      * @param ipAddress         IP address
      * @param deviceId          device identifier
      * @param portNumber        port number
+     * @param securityGroups    security groups
      */
     public DefaultKubevirtPort(String networkId, MacAddress macAddress, IpAddress ipAddress,
-                               DeviceId deviceId, PortNumber portNumber) {
+                               DeviceId deviceId, PortNumber portNumber, Set<String> securityGroups) {
         this.networkId = networkId;
         this.macAddress = macAddress;
         this.ipAddress = ipAddress;
         this.deviceId = deviceId;
         this.portNumber = portNumber;
+        this.securityGroups = securityGroups;
     }
 
     @Override
@@ -77,6 +85,27 @@
     }
 
     @Override
+    public DeviceId tenantDeviceId() {
+        KubevirtNetworkService networkService =
+                DefaultServiceDirectory.getService(KubevirtNetworkService.class);
+        KubevirtNodeService nodeService =
+                DefaultServiceDirectory.getService(KubevirtNodeService.class);
+        KubevirtNetwork network = networkService.network(networkId);
+        KubevirtNode node = nodeService.node(deviceId);
+        return network.tenantDeviceId(node.hostname());
+    }
+
+    @Override
+    public boolean isTenant() {
+        KubevirtNetworkService networkService =
+                DefaultServiceDirectory.getService(KubevirtNetworkService.class);
+        KubevirtNetwork network = networkService.network(networkId);
+        return network.type() == KubevirtNetwork.Type.VXLAN ||
+                network.type() == KubevirtNetwork.Type.GRE ||
+                network.type() == KubevirtNetwork.Type.GENEVE;
+    }
+
+    @Override
     public PortNumber portNumber() {
         return portNumber;
     }
@@ -89,6 +118,7 @@
                 .ipAddress(updateIpAddress)
                 .deviceId(deviceId)
                 .portNumber(portNumber)
+                .securityGroups(securityGroups)
                 .build();
     }
 
@@ -100,6 +130,7 @@
                 .ipAddress(ipAddress)
                 .deviceId(deviceId)
                 .portNumber(updatedPortNumber)
+                .securityGroups(securityGroups)
                 .build();
     }
 
@@ -111,6 +142,28 @@
                 .ipAddress(ipAddress)
                 .deviceId(updatedDeviceId)
                 .portNumber(portNumber)
+                .securityGroups(securityGroups)
+                .build();
+    }
+
+    @Override
+    public Set<String> securityGroups() {
+        if (securityGroups != null) {
+            return ImmutableSet.copyOf(securityGroups);
+        } else {
+            return ImmutableSet.of();
+        }
+    }
+
+    @Override
+    public KubevirtPort updateSecurityGroups(Set<String> sgs) {
+        return new Builder()
+                .networkId(networkId)
+                .macAddress(macAddress)
+                .ipAddress(ipAddress)
+                .deviceId(deviceId)
+                .portNumber(portNumber)
+                .securityGroups(sgs)
                 .build();
     }
 
@@ -125,12 +178,12 @@
         DefaultKubevirtPort that = (DefaultKubevirtPort) o;
         return networkId.equals(that.networkId) && macAddress.equals(that.macAddress) &&
                 ipAddress.equals(that.ipAddress) && deviceId.equals(that.deviceId) &&
-                portNumber.equals(that.portNumber);
+                portNumber.equals(that.portNumber) && securityGroups.equals(that.securityGroups);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(networkId, macAddress, ipAddress, deviceId, portNumber);
+        return Objects.hash(networkId, macAddress, ipAddress, deviceId, portNumber, securityGroups);
     }
 
     @Override
@@ -141,6 +194,7 @@
                 .add("ipAddress", ipAddress)
                 .add("deviceId", deviceId)
                 .add("portNumber", portNumber)
+                .add("securityGroups", securityGroups)
                 .toString();
     }
 
@@ -163,6 +217,7 @@
         private IpAddress ipAddress;
         private DeviceId deviceId;
         private PortNumber portNumber;
+        private Set<String> securityGroups;
 
         // private constructor not intended to use from external
         private Builder() {
@@ -174,7 +229,7 @@
             checkArgument(macAddress != null, NOT_NULL_MSG, "macAddress");
 
             return new DefaultKubevirtPort(networkId, macAddress, ipAddress,
-                    deviceId, portNumber);
+                    deviceId, portNumber, securityGroups);
         }
 
         @Override
@@ -206,5 +261,11 @@
             this.portNumber = portNumber;
             return this;
         }
+
+        @Override
+        public Builder securityGroups(Set<String> securityGroups) {
+            this.securityGroups = securityGroups;
+            return this;
+        }
     }
 }
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtSecurityGroupRule.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtSecurityGroupRule.java
index 556d0bc..63d5f18 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtSecurityGroupRule.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtSecurityGroupRule.java
@@ -114,6 +114,21 @@
     }
 
     @Override
+    public KubevirtSecurityGroupRule updateDirection(String updated) {
+        return DefaultKubevirtSecurityGroupRule.builder()
+                .remoteGroupId(remoteGroupId)
+                .etherType(etherType)
+                .protocol(protocol)
+                .portRangeMin(portRangeMin)
+                .portRangeMax(portRangeMax)
+                .securityGroupId(securityGroupId)
+                .remoteIpPrefix(remoteIpPrefix)
+                .id(id)
+                .direction(updated)
+                .build();
+    }
+
+    @Override
     public boolean equals(Object o) {
         if (this == o) {
             return true;
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetwork.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetwork.java
index b1bf336..94ed1de 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetwork.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetwork.java
@@ -144,7 +144,7 @@
     DeviceId tenantDeviceId(String hostname);
 
     /**
-     * Returns the tunnel to tenant port number.
+     * Returns the tunnel bridge to tenant bridge port number.
      *
      * @param deviceId device identifier
      * @return port number
@@ -152,6 +152,14 @@
     PortNumber tunnelToTenantPort(DeviceId deviceId);
 
     /**
+     * Returns the tenant bridge to tunnel bridge patch port number.
+     *
+     * @param deviceId device identifier
+     * @return port number
+     */
+    PortNumber tenantToTunnelPort(DeviceId deviceId);
+
+    /**
      * Builder of new network.
      */
     interface Builder {
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetworkService.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetworkService.java
index 574f365..e89a635 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetworkService.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtNetworkService.java
@@ -48,4 +48,11 @@
      * @return set of kubevirt networks
      */
     Set<KubevirtNetwork> networks(Type type);
+
+    /**
+     * Returns all kubevirt tenant networks.
+     *
+     * @return set of kubevirt tenant networks
+     */
+    Set<KubevirtNetwork> tenantNetworks();
 }
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
index 850ac6f..3f19640 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
@@ -20,6 +20,8 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 
+import java.util.Set;
+
 /**
  * Representation of virtual port.
  */
@@ -54,6 +56,20 @@
     DeviceId deviceId();
 
     /**
+     * Returns the tenant device ID of the port.
+     *
+     * @return device ID
+     */
+    DeviceId tenantDeviceId();
+
+    /**
+     * Returns the result whether the port is associated with the tenant network.
+     *
+     * @return true if the port is associated with tenant network, false otherwise
+     */
+    boolean isTenant();
+
+    /**
      * Returns the port number of the port.
      *
      * @return port number
@@ -85,6 +101,21 @@
     KubevirtPort updateDeviceId(DeviceId updatedDeviceId);
 
     /**
+     * Returns the security group IDs.
+     *
+     * @return security group identifiers.
+     */
+    Set<String> securityGroups();
+
+    /**
+     * Returns new port instance with the given security groups.
+     *
+     * @param sgs security groups
+     * @return updated port
+     */
+    KubevirtPort updateSecurityGroups(Set<String> sgs);
+
+    /**
      * Builder of new port.
      */
     interface Builder {
@@ -135,5 +166,13 @@
          * @return port builder
          */
         Builder portNumber(PortNumber portNumber);
+
+        /**
+         * Returns port builder with supplied security group identifiers.
+         *
+         * @param securityGroups security group identifiers
+         * @return port builder
+         */
+        Builder securityGroups(Set<String> securityGroups);
     }
 }
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java
index efc67d5..2c2012a 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java
@@ -15,13 +15,20 @@
  */
 package org.onosproject.kubevirtnetworking.api;
 
+import org.onlab.util.Tools;
 import org.onosproject.event.AbstractEvent;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 
 /**
  * Kubevirt port event class.
  */
 public class KubevirtPortEvent extends AbstractEvent<KubevirtPortEvent.Type, KubevirtPort> {
 
+    private final String securityGroupId;
+    private final DeviceId deviceId;
+
     /**
      * Creates an event of a given type for the specified port.
      *
@@ -30,6 +37,34 @@
      */
     public KubevirtPortEvent(Type type, KubevirtPort subject) {
         super(type, subject);
+        securityGroupId = null;
+        deviceId = null;
+    }
+
+    /**
+     * Creates an event of a given type for the specified port.
+     *
+     * @param type              kubevirt port event type
+     * @param subject           kubevirt port subject
+     * @param securityGroupId   kubevirt security group ID
+     */
+    public KubevirtPortEvent(Type type, KubevirtPort subject, String securityGroupId) {
+        super(type, subject);
+        this.securityGroupId = securityGroupId;
+        this.deviceId = null;
+    }
+
+    /**
+     * Creates an event of a given type for the specified port.
+     *
+     * @param type              kubevirt port event type
+     * @param subject           kubevirt port subject
+     * @param deviceId          kubevirt device ID
+     */
+    public KubevirtPortEvent(Type type, KubevirtPort subject, DeviceId deviceId) {
+        super(type, subject);
+        this.deviceId = deviceId;
+        this.securityGroupId = null;
     }
 
     /**
@@ -51,5 +86,39 @@
          * Signifies that the kubevirt port is removed.
          */
         KUBEVIRT_PORT_REMOVED,
+
+        /**
+         * Signifies that the kubevirt device is added.
+         */
+        KUBEVIRT_PORT_DEVICE_ADDED,
+
+        /**
+         * Signifies that the kubevirt security group rule is added to a specific port.
+         */
+        KUBEVIRT_PORT_SECURITY_GROUP_ADDED,
+
+        /**
+         * Signifies that the kubevirt security group rule is removed from a specific port.
+         */
+        KUBEVIRT_PORT_SECURITY_GROUP_REMOVED,
+    }
+
+    /**
+     * Returns the security group rule IDs updated.
+     *
+     * @return edgestack security group
+     */
+    public String securityGroupId() {
+        return securityGroupId;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("time", Tools.defaultOffsetDataTime(time()))
+                .add("type", type())
+                .add("port", subject())
+                .add("security group", securityGroupId())
+                .toString();
     }
 }
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtSecurityGroupRule.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtSecurityGroupRule.java
index 8010d97..5c99306 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtSecurityGroupRule.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtSecurityGroupRule.java
@@ -86,6 +86,14 @@
     String remoteGroupId();
 
     /**
+     * Returns the security group rule with updated direction.
+     *
+     * @param direction direction
+     * @return updated security group
+     */
+    KubevirtSecurityGroupRule updateDirection(String direction);
+
+    /**
      * A default builder interface.
      */
     interface Builder {