Support distributed virtual router (DVR) at kubernetes

Change-Id: I6dfa1ad0d2161443e37fa80901d5ababbec6f74e
diff --git a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sApiConfigCodec.java b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sApiConfigCodec.java
index 5b8c05e..9b90c94 100644
--- a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sApiConfigCodec.java
+++ b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sApiConfigCodec.java
@@ -57,6 +57,7 @@
     private static final String CLIENT_CERT_DATA = "clientCertData";
     private static final String CLIENT_KEY_DATA = "clientKeyData";
     private static final String HOST_NODES_INFO = "hostNodesInfo";
+    private static final String DVR = "dvr";
 
     private static final String MISSING_MESSAGE = " is required in K8sApiConfig";
 
@@ -69,7 +70,8 @@
                 .put(SCHEME, entity.scheme().name())
                 .put(IP_ADDRESS, entity.ipAddress().toString())
                 .put(PORT, entity.port())
-                .put(STATE, entity.state().name());
+                .put(STATE, entity.state().name())
+                .put(DVR, entity.dvr());
 
         if (entity.scheme() == HTTPS) {
             node.put(CA_CERT_DATA, entity.caCertData())
@@ -159,6 +161,11 @@
                 .port(port)
                 .state(DISCONNECTED);
 
+        JsonNode dvrJson = json.get(DVR);
+        if (dvrJson != null) {
+            builder.dvr(dvrJson.asBoolean());
+        }
+
         JsonNode tokenJson = json.get(TOKEN);
         JsonNode caCertDataJson = json.get(CA_CERT_DATA);
         JsonNode clientCertDataJson = json.get(CLIENT_CERT_DATA);
diff --git a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java
index 8793c46..4cc6609 100644
--- a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java
+++ b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/codec/K8sNodeCodec.java
@@ -19,6 +19,7 @@
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.commons.lang.StringUtils;
 import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.codec.JsonCodec;
 import org.onosproject.k8snode.api.DefaultK8sNode;
@@ -54,6 +55,7 @@
     private static final String EXTERNAL_INTF = "externalInterface";
     private static final String EXTERNAL_BRIDGE_IP = "externalBridgeIp";
     private static final String EXTERNAL_GATEWAY_IP = "externalGatewayIp";
+    private static final String EXTERNAL_GATEWAY_MAC = "externalGatewayMac";
 
     private static final String MISSING_MESSAGE = " is required in K8sNode";
 
@@ -101,6 +103,10 @@
             result.put(EXTERNAL_GATEWAY_IP, node.extGatewayIp().toString());
         }
 
+        if (node.extGatewayMac() != null) {
+            result.put(EXTERNAL_GATEWAY_MAC, node.extGatewayMac().toString());
+        }
+
         return result;
     }
 
@@ -176,6 +182,11 @@
             nodeBuilder.extGatewayIp(IpAddress.valueOf(extGatewayIpJson.asText()));
         }
 
+        JsonNode extGatewayMacJson = json.get(EXTERNAL_GATEWAY_MAC);
+        if (extGatewayMacJson != null) {
+            nodeBuilder.extGatewayMac(MacAddress.valueOf(extGatewayMacJson.asText()));
+        }
+
         log.trace("node is {}", nodeBuilder.build().toString());
 
         return nodeBuilder.build();
diff --git a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java
index c188871..342787c 100644
--- a/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java
+++ b/apps/k8s-node/app/src/main/java/org/onosproject/k8snode/impl/DefaultK8sApiConfigHandler.java
@@ -20,6 +20,7 @@
 import io.fabric8.kubernetes.api.model.NodeAddress;
 import io.fabric8.kubernetes.client.KubernetesClient;
 import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.LeadershipService;
 import org.onosproject.cluster.NodeId;
@@ -54,6 +55,7 @@
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.k8snode.api.Constants.DEFAULT_CLUSTER_NAME;
+import static org.onosproject.k8snode.api.Constants.DEFAULT_EXTERNAL_GATEWAY_MAC;
 import static org.onosproject.k8snode.api.Constants.EXTERNAL_TO_ROUTER;
 import static org.onosproject.k8snode.api.K8sApiConfig.Mode.PASSTHROUGH;
 import static org.onosproject.k8snode.api.K8sNode.Type.MASTER;
@@ -243,7 +245,7 @@
             extBridgeIpStr = annots.get(EXT_BRIDGE_IP);
         }
 
-        return DefaultK8sNode.builder()
+        K8sNode.Builder builder = DefaultK8sNode.builder()
                 .clusterName(DEFAULT_CLUSTER_NAME)
                 .hostname(hostname)
                 .managementIp(managementIp)
@@ -255,8 +257,13 @@
                 .mode(config.mode())
                 .extBridgeIp(IpAddress.valueOf(extBridgeIpStr))
                 .extGatewayIp(IpAddress.valueOf(extGatewayIpStr))
-                .podCidr(node.getSpec().getPodCIDR())
-                .build();
+                .podCidr(node.getSpec().getPodCIDR());
+
+        if (config.dvr()) {
+            builder.extGatewayMac(MacAddress.valueOf(DEFAULT_EXTERNAL_GATEWAY_MAC));
+        }
+
+        return builder.build();
     }
 
     /**