OSPF protocol manual merge from 1.6, due to cherry pick merge conflict

Change-Id: I93653e745468722ce95533537a79e897b4292f5d
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfConfigUtil.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfConfigUtil.java
new file mode 100644
index 0000000..06af9bf
--- /dev/null
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfConfigUtil.java
@@ -0,0 +1,332 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * 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.ospf.controller.impl;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.ospf.controller.OspfArea;
+import org.onosproject.ospf.controller.OspfInterface;
+import org.onosproject.ospf.controller.OspfProcess;
+import org.onosproject.ospf.controller.area.OspfAreaImpl;
+import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
+import org.onosproject.ospf.controller.area.OspfProcessImpl;
+import org.onosproject.ospf.protocol.util.OspfUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * Representation of OSPF network configuration parsing util.
+ */
+public final class OspfConfigUtil {
+    public static final String PROCESSID = "processId";
+    public static final String AREAS = "areas";
+    public static final String INTERFACEINDEX = "interfaceIndex";
+    public static final String AREAID = "areaId";
+    public static final String ROUTERID = "routerId";
+    public static final String INTERFACE = "interface";
+    public static final String HELLOINTERVAL = "helloIntervalTime";
+    public static final String ROUTERDEADINTERVAL = "routerDeadIntervalTime";
+    public static final String INTERFACETYPE = "interfaceType";
+    public static final String EXTERNALROUTINGCAPABILITY = "externalRoutingCapability";
+    protected static final Logger log = LoggerFactory.getLogger(OspfConfigUtil.class);
+    private static final String ISOPAQUE = "isOpaqueEnable";
+
+    /**
+     * Creates an instance of this.
+     */
+    private OspfConfigUtil() {
+
+    }
+
+    /**
+     * Returns list of OSPF process from the json nodes.
+     *
+     * @param jsonNodes represents one or more OSPF process configuration
+     * @return list of OSPF processes.
+     */
+    public static List<OspfProcess> processes(JsonNode jsonNodes) {
+        List<OspfProcess> ospfProcesses = new ArrayList<>();
+        if (jsonNodes == null) {
+            return ospfProcesses;
+        }
+        //From each Process nodes, get area and related interface details.
+        jsonNodes.forEach(jsonNode -> {
+            List<OspfArea> areas = new ArrayList<>();
+            //Get configured areas for the process.
+            for (JsonNode areaNode : jsonNode.path(AREAS)) {
+                List<OspfInterface> interfaceList = new ArrayList<>();
+                for (JsonNode interfaceNode : areaNode.path(INTERFACE)) {
+                    OspfInterface ospfInterface = interfaceDetails(interfaceNode);
+                    if (ospfInterface != null) {
+                        interfaceList.add(ospfInterface);
+                    }
+                }
+                //Get the area details
+                OspfArea area = areaDetails(areaNode);
+                if (area != null) {
+                    area.setOspfInterfaceList(interfaceList);
+                    areas.add(area);
+                }
+            }
+            OspfProcess process = new OspfProcessImpl();
+            process.setProcessId(jsonNode.path(PROCESSID).asText());
+            process.setAreas(areas);
+            ospfProcesses.add(process);
+        });
+
+        return ospfProcesses;
+    }
+
+    /**
+     * Returns interface IP by index.
+     *
+     * @param interfaceIndex interface index
+     * @return interface IP by index
+     */
+    private static Ip4Address getInterfaceIp(int interfaceIndex) {
+        Ip4Address ipAddress = null;
+        try {
+            NetworkInterface networkInterface = NetworkInterface.getByIndex(interfaceIndex);
+            Enumeration ipAddresses = networkInterface.getInetAddresses();
+            while (ipAddresses.hasMoreElements()) {
+                InetAddress address = (InetAddress) ipAddresses.nextElement();
+                if (!address.isLinkLocalAddress()) {
+                    ipAddress = Ip4Address.valueOf(address.getAddress());
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            log.debug("Error while getting Interface IP by index");
+            return OspfUtil.DEFAULTIP;
+        }
+        return ipAddress;
+    }
+
+    /**
+     * Returns interface MAC by index.
+     *
+     * @param interfaceIndex interface index
+     * @return interface IP by index
+     */
+    private static String getInterfaceMask(int interfaceIndex) {
+        String subnetMask = null;
+        try {
+            Ip4Address ipAddress = getInterfaceIp(interfaceIndex);
+            NetworkInterface networkInterface = NetworkInterface.getByInetAddress(
+                    InetAddress.getByName(ipAddress.toString()));
+            Enumeration ipAddresses = networkInterface.getInetAddresses();
+            int index = 0;
+            while (ipAddresses.hasMoreElements()) {
+                InetAddress address = (InetAddress) ipAddresses.nextElement();
+                if (!address.isLinkLocalAddress()) {
+                    break;
+                }
+                index++;
+            }
+            int prfLen = networkInterface.getInterfaceAddresses().get(index).getNetworkPrefixLength();
+            int shft = 0xffffffff << (32 - prfLen);
+            int oct1 = ((byte) ((shft & 0xff000000) >> 24)) & 0xff;
+            int oct2 = ((byte) ((shft & 0x00ff0000) >> 16)) & 0xff;
+            int oct3 = ((byte) ((shft & 0x0000ff00) >> 8)) & 0xff;
+            int oct4 = ((byte) (shft & 0x000000ff)) & 0xff;
+            subnetMask = oct1 + "." + oct2 + "." + oct3 + "." + oct4;
+        } catch (Exception e) {
+            log.debug("Error while getting Interface network mask by index");
+            return subnetMask;
+        }
+        return subnetMask;
+    }
+
+    /**
+     * Checks if valid digit or not.
+     *
+     * @param strInput input value
+     * @return true if valid else false
+     */
+    private static boolean isValidDigit(String strInput) {
+        boolean isValid = true;
+        if (isPrimitive(strInput)) {
+            int input = Integer.parseInt(strInput);
+            if (input < 1 || input > 255) {
+                log.debug("Wrong config input value: {}", strInput);
+                isValid = false;
+            } else {
+                isValid = true;
+            }
+
+        } else {
+            isValid = false;
+        }
+
+        return isValid;
+    }
+
+    /**
+     * Checks if primitive or not.
+     *
+     * @param value input value
+     * @return true if number else false
+     */
+    private static boolean isPrimitive(String value) {
+        boolean status = true;
+        value = value.trim();
+        if (value.length() < 1) {
+            return false;
+        }
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            if (!Character.isDigit(c)) {
+                status = false;
+                break;
+            }
+        }
+
+        return status;
+    }
+
+    /**
+     * Checks if boolean or not.
+     *
+     * @param value input value
+     * @return true if boolean else false
+     */
+    private static boolean isBoolean(String value) {
+        boolean status = false;
+        value = value.trim();
+        if (value.equals("true") || value.equals("false")) {
+            return true;
+        }
+
+        return status;
+    }
+
+    /**
+     * Checks if given id is valid or not.
+     *
+     * @param value input value
+     * @return true if valid else false
+     */
+    private static boolean isValidIpAddress(String value) {
+        boolean status = true;
+        try {
+            Ip4Address ipAddress = Ip4Address.valueOf(value);
+        } catch (Exception e) {
+            log.debug("Invalid IP address string: {}", value);
+            return false;
+        }
+
+        return status;
+    }
+
+    /**
+     * Returns OSPF area instance from configuration.
+     *
+     * @param areaNode area configuration
+     * @return OSPF area instance
+     */
+    private static OspfArea areaDetails(JsonNode areaNode) {
+        OspfArea area = new OspfAreaImpl();
+        String areaId = areaNode.path(AREAID).asText();
+        if (isValidIpAddress(areaId)) {
+            area.setAreaId(Ip4Address.valueOf(areaId));
+        } else {
+            log.debug("Wrong areaId: {}", areaId);
+            return null;
+        }
+        String routerId = areaNode.path(ROUTERID).asText();
+        if (isValidIpAddress(routerId)) {
+            area.setRouterId(Ip4Address.valueOf(routerId));
+        } else {
+            log.debug("Wrong routerId: {}", routerId);
+            return null;
+        }
+        String routingCapability = areaNode.path(EXTERNALROUTINGCAPABILITY).asText();
+        if (isBoolean(routingCapability)) {
+            area.setExternalRoutingCapability(Boolean.valueOf(routingCapability));
+        } else {
+            log.debug("Wrong routingCapability: {}", routingCapability);
+            return null;
+        }
+        String isOpaqueEnabled = areaNode.path(ISOPAQUE).asText();
+        if (isBoolean(isOpaqueEnabled)) {
+            area.setIsOpaqueEnabled(Boolean.valueOf(isOpaqueEnabled));
+        } else {
+            log.debug("Wrong isOpaqueEnabled: {}", isOpaqueEnabled);
+            return null;
+        }
+        area.setOptions(OspfUtil.HELLO_PACKET_OPTIONS);
+
+        return area;
+    }
+
+    /**
+     * Returns OSPF interface instance from configuration.
+     *
+     * @param interfaceNode interface configuration
+     * @return OSPF interface instance
+     */
+    private static OspfInterface interfaceDetails(JsonNode interfaceNode) {
+        OspfInterface ospfInterface = new OspfInterfaceImpl();
+        String index = interfaceNode.path(INTERFACEINDEX).asText();
+        if (isValidDigit(index)) {
+            ospfInterface.setInterfaceIndex(Integer.parseInt(index));
+        } else {
+            log.debug("Wrong interface index: {}", index);
+            return null;
+        }
+        Ip4Address interfaceIp = getInterfaceIp(ospfInterface.interfaceIndex());
+        if (interfaceIp.equals(OspfUtil.DEFAULTIP)) {
+            return null;
+        }
+        ospfInterface.setIpAddress(interfaceIp);
+        ospfInterface.setIpNetworkMask(Ip4Address.valueOf(getInterfaceMask(
+                ospfInterface.interfaceIndex())));
+        ospfInterface.setBdr(OspfUtil.DEFAULTIP);
+        ospfInterface.setDr(OspfUtil.DEFAULTIP);
+        String helloInterval = interfaceNode.path(HELLOINTERVAL).asText();
+        if (isValidDigit(helloInterval)) {
+            ospfInterface.setHelloIntervalTime(Integer.parseInt(helloInterval));
+        } else {
+            log.debug("Wrong hello interval: {}", helloInterval);
+            return null;
+        }
+        String routerDeadInterval = interfaceNode.path(ROUTERDEADINTERVAL).asText();
+        if (isValidDigit(routerDeadInterval)) {
+            ospfInterface.setRouterDeadIntervalTime(Integer.parseInt(routerDeadInterval));
+        } else {
+            log.debug("Wrong routerDeadInterval: {}", routerDeadInterval);
+            return null;
+        }
+        String interfaceType = interfaceNode.path(INTERFACETYPE).asText();
+        if (isValidDigit(interfaceType)) {
+            ospfInterface.setInterfaceType(Integer.parseInt(interfaceType));
+        } else {
+            log.debug("Wrong interfaceType: {}", interfaceType);
+            return null;
+        }
+        ospfInterface.setReTransmitInterval(OspfUtil.RETRANSMITINTERVAL);
+        ospfInterface.setMtu(OspfUtil.MTU);
+        ospfInterface.setRouterPriority(OspfUtil.ROUTER_PRIORITY);
+
+        return ospfInterface;
+    }
+}