Allow to query mapping value when receives MapRequest

Change-Id: Ic7893a397c2c16e219135a31516565d2f1323f50
diff --git a/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProvider.java b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProvider.java
index b4fd841..a7ba95f 100644
--- a/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProvider.java
+++ b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProvider.java
@@ -15,6 +15,7 @@
  */
 package org.onosproject.provider.lisp.mapping.impl;
 
+import com.google.common.collect.Lists;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -24,12 +25,14 @@
 import org.onosproject.lisp.ctl.LispMessageListener;
 import org.onosproject.lisp.ctl.LispRouterId;
 import org.onosproject.lisp.ctl.LispRouterListener;
-import org.onosproject.lisp.msg.protocols.LispMapNotify;
+import org.onosproject.lisp.msg.protocols.LispEidRecord;
 import org.onosproject.lisp.msg.protocols.LispMapRecord;
 import org.onosproject.lisp.msg.protocols.LispMapRegister;
 import org.onosproject.lisp.msg.protocols.LispMapReply;
+import org.onosproject.lisp.msg.protocols.LispMapRequest;
 import org.onosproject.lisp.msg.protocols.LispMessage;
 import org.onosproject.mapping.MappingEntry;
+import org.onosproject.mapping.MappingKey;
 import org.onosproject.mapping.MappingProvider;
 import org.onosproject.mapping.MappingProviderRegistry;
 import org.onosproject.mapping.MappingProviderService;
@@ -39,6 +42,7 @@
 import org.onosproject.net.provider.AbstractProvider;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.provider.lisp.mapping.util.MappingEntryBuilder;
+import org.onosproject.provider.lisp.mapping.util.MappingKeyBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -143,8 +147,12 @@
             switch (msg.getType()) {
 
                 case LISP_MAP_REQUEST:
-                    log.warn("LISP mapping query feature will be added when " +
-                             "provider service supports it.");
+                    LispMapRequest request = (LispMapRequest) msg;
+                    List<LispEidRecord> records = request.getEids();
+                    List<MappingKey> keys = Lists.newArrayList();
+                    records.forEach(r -> keys.add(new MappingKeyBuilder(deviceService,
+                            deviceId, r.getPrefix()).build()));
+                    keys.forEach(key -> providerService.mappingQueried(key));
                     break;
 
                 case LISP_MAP_REGISTER:
@@ -173,8 +181,8 @@
                     break;
 
                 case LISP_MAP_NOTIFY:
-                    LispMapNotify notify = (LispMapNotify) msg;
-                    processMappings(deviceId, notify.getMapRecords(), MAP_DATABASE);
+                    // not take any action for map notify, and we've already
+                    // store the mapping when receives map register message
                     break;
 
                 default:
diff --git a/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingAddressBuilder.java b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingAddressBuilder.java
new file mode 100644
index 0000000..11492d6
--- /dev/null
+++ b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingAddressBuilder.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2017-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.provider.lisp.mapping.util;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.lisp.ctl.ExtensionMappingAddressInterpreter;
+import org.onosproject.lisp.msg.types.LispAfiAddress;
+import org.onosproject.lisp.msg.types.LispAsAddress;
+import org.onosproject.lisp.msg.types.LispDistinguishedNameAddress;
+import org.onosproject.lisp.msg.types.LispIpv4Address;
+import org.onosproject.lisp.msg.types.LispIpv6Address;
+import org.onosproject.lisp.msg.types.LispMacAddress;
+import org.onosproject.lisp.msg.types.lcaf.LispLcafAddress;
+import org.onosproject.mapping.addresses.ExtensionMappingAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddresses;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onosproject.mapping.addresses.ExtensionMappingAddressType.ExtensionMappingAddressTypes.*;
+
+/**
+ * Mapping address builder class.
+ */
+public final class MappingAddressBuilder {
+
+    private static final Logger log =
+            LoggerFactory.getLogger(MappingAddressBuilder.class);
+
+    private static final int IPV4_PREFIX_LENGTH = 32;
+    private static final int IPV6_PREFIX_LENGTH = 128;
+
+    // prevent from instantiation
+    private MappingAddressBuilder() {
+    }
+
+    /**
+     * Converts LispAfiAddress into abstracted mapping address.
+     *
+     * @param deviceService device service
+     * @param deviceId      device identifier
+     * @param address       LispAfiAddress
+     * @return abstracted mapping address
+     */
+    protected static MappingAddress getAddress(DeviceService deviceService,
+                                               DeviceId deviceId,
+                                               LispAfiAddress address) {
+
+        if (address == null) {
+            log.warn("Address is not specified.");
+            return null;
+        }
+
+        switch (address.getAfi()) {
+            case IP4:
+                return afi2mapping(address);
+            case IP6:
+                return afi2mapping(address);
+            case AS:
+                int asNum = ((LispAsAddress) address).getASNum();
+                return MappingAddresses.asMappingAddress(String.valueOf(asNum));
+            case DISTINGUISHED_NAME:
+                String dn = ((LispDistinguishedNameAddress)
+                        address).getDistinguishedName();
+                return MappingAddresses.dnMappingAddress(dn);
+            case MAC:
+                MacAddress macAddress = ((LispMacAddress) address).getAddress();
+                return MappingAddresses.ethMappingAddress(macAddress);
+            case LCAF:
+                return deviceService == null ? null :
+                        lcaf2extension(deviceService, deviceId, (LispLcafAddress) address);
+            default:
+                log.warn("Unsupported address type {}", address.getAfi());
+                break;
+        }
+
+        return null;
+    }
+
+    /**
+     * Converts AFI address to generalized mapping address.
+     *
+     * @param afiAddress IP typed AFI address
+     * @return generalized mapping address
+     */
+    private static MappingAddress afi2mapping(LispAfiAddress afiAddress) {
+        switch (afiAddress.getAfi()) {
+            case IP4:
+                IpAddress ipv4Address = ((LispIpv4Address) afiAddress).getAddress();
+                IpPrefix ipv4Prefix = IpPrefix.valueOf(ipv4Address, IPV4_PREFIX_LENGTH);
+                return MappingAddresses.ipv4MappingAddress(ipv4Prefix);
+            case IP6:
+                IpAddress ipv6Address = ((LispIpv6Address) afiAddress).getAddress();
+                IpPrefix ipv6Prefix = IpPrefix.valueOf(ipv6Address, IPV6_PREFIX_LENGTH);
+                return MappingAddresses.ipv6MappingAddress(ipv6Prefix);
+            default:
+                log.warn("Only support to convert IP address type");
+                break;
+        }
+        return null;
+    }
+
+    /**
+     * Converts LCAF address to extension mapping address.
+     *
+     * @param deviceService device service
+     * @param deviceId      device identifier
+     * @param lcaf          LCAF address
+     * @return extension mapping address
+     */
+    private static MappingAddress lcaf2extension(DeviceService deviceService,
+                                                 DeviceId deviceId,
+                                                 LispLcafAddress lcaf) {
+
+        Device device = deviceService.getDevice(deviceId);
+
+        ExtensionMappingAddressInterpreter addressInterpreter;
+        ExtensionMappingAddress mappingAddress = null;
+        if (device.is(ExtensionMappingAddressInterpreter.class)) {
+            addressInterpreter = device.as(ExtensionMappingAddressInterpreter.class);
+        } else {
+            addressInterpreter = null;
+        }
+
+        switch (lcaf.getType()) {
+            case LIST:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(LIST_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case SEGMENT:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(SEGMENT_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case AS:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(AS_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case APPLICATION_DATA:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(APPLICATION_DATA_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case GEO_COORDINATE:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(GEO_COORDINATE_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case NAT:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(NAT_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case NONCE:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(NONCE_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case MULTICAST:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(MULTICAST_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case TRAFFIC_ENGINEERING:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(TRAFFIC_ENGINEERING_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            case SOURCE_DEST:
+                if (addressInterpreter != null &&
+                        addressInterpreter.supported(SOURCE_DEST_ADDRESS.type())) {
+                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
+                }
+                break;
+            default:
+                log.warn("Unsupported extension mapping address type {}", lcaf.getType());
+                break;
+        }
+
+        return mappingAddress != null ?
+                MappingAddresses.extensionMappingAddressWrapper(mappingAddress, deviceId) : null;
+    }
+}
diff --git a/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingEntryBuilder.java b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingEntryBuilder.java
index 10162cd..7e1ab3d 100644
--- a/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingEntryBuilder.java
+++ b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingEntryBuilder.java
@@ -16,19 +16,9 @@
 package org.onosproject.provider.lisp.mapping.util;
 
 import com.google.common.collect.Lists;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onosproject.lisp.ctl.ExtensionMappingAddressInterpreter;
 import org.onosproject.lisp.msg.protocols.LispLocator;
 import org.onosproject.lisp.msg.protocols.LispMapRecord;
 import org.onosproject.lisp.msg.types.LispAfiAddress;
-import org.onosproject.lisp.msg.types.LispAsAddress;
-import org.onosproject.lisp.msg.types.LispDistinguishedNameAddress;
-import org.onosproject.lisp.msg.types.LispIpv4Address;
-import org.onosproject.lisp.msg.types.LispIpv6Address;
-import org.onosproject.lisp.msg.types.LispMacAddress;
-import org.onosproject.lisp.msg.types.lcaf.LispLcafAddress;
 import org.onosproject.mapping.DefaultMapping;
 import org.onosproject.mapping.DefaultMappingEntry;
 import org.onosproject.mapping.DefaultMappingKey;
@@ -42,10 +32,7 @@
 import org.onosproject.mapping.MappingValue;
 import org.onosproject.mapping.actions.MappingAction;
 import org.onosproject.mapping.actions.MappingActions;
-import org.onosproject.mapping.addresses.ExtensionMappingAddress;
 import org.onosproject.mapping.addresses.MappingAddress;
-import org.onosproject.mapping.addresses.MappingAddresses;
-import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.device.DeviceService;
 import org.slf4j.Logger;
@@ -53,7 +40,7 @@
 
 import java.util.List;
 
-import static org.onosproject.mapping.addresses.ExtensionMappingAddressType.ExtensionMappingAddressTypes.*;
+import static org.onosproject.provider.lisp.mapping.util.MappingAddressBuilder.getAddress;
 
 /**
  * Mapping entry builder class.
@@ -62,9 +49,6 @@
     private static final Logger log =
             LoggerFactory.getLogger(MappingEntryBuilder.class);
 
-    private static final int IPV4_PREFIX_LENGTH = 32;
-    private static final int IPV6_PREFIX_LENGTH = 128;
-
     private final DeviceId deviceId;
 
     private final MappingAddress address;
@@ -189,157 +173,8 @@
      */
     private MappingAddress buildAddress(LispMapRecord record) {
 
-        return record == null ? null : getAddress(record.getEidPrefixAfi());
-    }
-
-    /**
-     * Converts LispAfiAddress into abstracted mapping address.
-     *
-     * @param address LispAfiAddress
-     * @return abstracted mapping address
-     */
-    private MappingAddress getAddress(LispAfiAddress address) {
-
-        if (address == null) {
-            log.warn("Address is not specified.");
-            return null;
-        }
-
-        switch (address.getAfi()) {
-            case IP4:
-                return afi2mapping(address);
-            case IP6:
-                return afi2mapping(address);
-            case AS:
-                int asNum = ((LispAsAddress) address).getASNum();
-                return MappingAddresses.asMappingAddress(String.valueOf(asNum));
-            case DISTINGUISHED_NAME:
-                String dn = ((LispDistinguishedNameAddress)
-                        address).getDistinguishedName();
-                return MappingAddresses.dnMappingAddress(dn);
-            case MAC:
-                MacAddress macAddress = ((LispMacAddress) address).getAddress();
-                return MappingAddresses.ethMappingAddress(macAddress);
-            case LCAF:
-                return deviceService == null ? null :
-                                     lcaf2extension((LispLcafAddress) address);
-            default:
-                log.warn("Unsupported address type {}", address.getAfi());
-                break;
-        }
-
-        return null;
-    }
-
-    /**
-     * Converts LCAF address to extension mapping address.
-     *
-     * @param lcaf          LCAF address
-     * @return extension mapping address
-     */
-    private MappingAddress lcaf2extension(LispLcafAddress lcaf) {
-
-        Device device = deviceService.getDevice(deviceId);
-
-        ExtensionMappingAddressInterpreter addressInterpreter;
-        ExtensionMappingAddress mappingAddress = null;
-        if (device.is(ExtensionMappingAddressInterpreter.class)) {
-            addressInterpreter = device.as(ExtensionMappingAddressInterpreter.class);
-        } else {
-            addressInterpreter = null;
-        }
-
-        switch (lcaf.getType()) {
-            case LIST:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(LIST_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case SEGMENT:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(SEGMENT_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case AS:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(AS_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case APPLICATION_DATA:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(APPLICATION_DATA_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case GEO_COORDINATE:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(GEO_COORDINATE_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case NAT:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(NAT_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case NONCE:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(NONCE_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case MULTICAST:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(MULTICAST_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case TRAFFIC_ENGINEERING:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(TRAFFIC_ENGINEERING_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            case SOURCE_DEST:
-                if (addressInterpreter != null &&
-                        addressInterpreter.supported(SOURCE_DEST_ADDRESS.type())) {
-                    mappingAddress = addressInterpreter.mapLcafAddress(lcaf);
-                }
-                break;
-            default:
-                log.warn("Unsupported extension mapping address type {}", lcaf.getType());
-                break;
-        }
-
-        return mappingAddress != null ?
-                MappingAddresses.extensionMappingAddressWrapper(mappingAddress, deviceId) : null;
-    }
-
-    /**
-     * Converts AFI address to generalized mapping address.
-     *
-     * @param afiAddress IP typed AFI address
-     * @return generalized mapping address
-     */
-    private MappingAddress afi2mapping(LispAfiAddress afiAddress) {
-        switch (afiAddress.getAfi()) {
-            case IP4:
-                IpAddress ipv4Address = ((LispIpv4Address) afiAddress).getAddress();
-                IpPrefix ipv4Prefix = IpPrefix.valueOf(ipv4Address, IPV4_PREFIX_LENGTH);
-                return MappingAddresses.ipv4MappingAddress(ipv4Prefix);
-            case IP6:
-                IpAddress ipv6Address = ((LispIpv6Address) afiAddress).getAddress();
-                IpPrefix ipv6Prefix = IpPrefix.valueOf(ipv6Address, IPV6_PREFIX_LENGTH);
-                return MappingAddresses.ipv6MappingAddress(ipv6Prefix);
-            default:
-                log.warn("Only support to convert IP address type");
-                break;
-        }
-        return null;
+        return record == null ? null :
+                getAddress(deviceService, deviceId, record.getEidPrefixAfi());
     }
 
     /**
@@ -356,7 +191,8 @@
             MappingTreatment.Builder builder = DefaultMappingTreatment.builder();
             LispAfiAddress address = locator.getLocatorAfi();
 
-            final MappingAddress mappingAddress = getAddress(address);
+            final MappingAddress mappingAddress =
+                    getAddress(deviceService, deviceId, address);
             if (mappingAddress != null) {
                 builder.withAddress(mappingAddress);
             }
diff --git a/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingKeyBuilder.java b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingKeyBuilder.java
new file mode 100644
index 0000000..903a992
--- /dev/null
+++ b/providers/lisp/mapping/src/main/java/org/onosproject/provider/lisp/mapping/util/MappingKeyBuilder.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017-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.provider.lisp.mapping.util;
+
+import org.onosproject.lisp.msg.types.LispAfiAddress;
+import org.onosproject.mapping.DefaultMappingKey;
+import org.onosproject.mapping.MappingKey;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onosproject.provider.lisp.mapping.util.MappingAddressBuilder.getAddress;
+
+/**
+ * Mapping key builder class.
+ */
+public class MappingKeyBuilder {
+    private static final Logger log =
+            LoggerFactory.getLogger(MappingKeyBuilder.class);
+
+    private final LispAfiAddress address;
+
+    private final DeviceId deviceId;
+
+    private final DeviceService deviceService;
+
+
+    /**
+     * Default constructor for MappingKeyBuilder.
+     *
+     * @param deviceService device service
+     * @param deviceId      device identifier
+     * @param afiAddress    AFI address
+     */
+    public MappingKeyBuilder(DeviceService deviceService, DeviceId deviceId,
+                             LispAfiAddress afiAddress) {
+        this.deviceId = deviceId;
+        this.address = afiAddress;
+        this.deviceService = deviceService;
+    }
+
+    /**
+     * Builds mapping key from a AFI address.
+     *
+     * @return mapping key
+     */
+    public MappingKey build() {
+        MappingAddress mappingAddress = getAddress(deviceService, deviceId, address);
+        return DefaultMappingKey.builder().withAddress(mappingAddress).build();
+    }
+}