Implement host probing retry with major refactoring

- Implement probe retry
- Switch to typical core/provider design pattern for HostProbingService
  and as a result decoupling the dependency between SR and HostLocationProvider

Change-Id: I33a15af580677ea376b421ac3e26f9821dcca844
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostLocationProbingService.java b/core/api/src/main/java/org/onosproject/net/host/HostLocationProbingService.java
index 56d056c..66f1266 100644
--- a/core/api/src/main/java/org/onosproject/net/host/HostLocationProbingService.java
+++ b/core/api/src/main/java/org/onosproject/net/host/HostLocationProbingService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-present Open Networking Foundation
+ * 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.
@@ -18,31 +18,21 @@
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Host;
 
+/**
+ * Service for interacting with the host probing entities.
+ *
+ * @deprecated in ONOS 1.12, replaced by {@link HostProbingService}
+ */
+@Deprecated
 public interface HostLocationProbingService {
     /**
-     * Mode of host location probing.
-     */
-    enum ProbeMode {
-        /**
-         * Append probed host location if reply is received before timeout. Otherwise, do nothing.
-         * Typically used to discover secondary locations.
-         */
-        DISCOVER,
-
-        /**
-         * Remove probed host location if reply is received after timeout. Otherwise, do nothing.
-         * Typically used to verify previous locations.
-         */
-        VERIFY
-    }
-
-    /**
      * Probes given host on given location.
      *
      * @param host the host to be probed
      * @param connectPoint the location of host to be probed
      * @param probeMode probe mode
+     * @deprecated in ONOS 1.12, replaced by {@link HostProbingService#probeHost(Host, ConnectPoint, ProbeMode)}
      */
-    void probeHostLocation(Host host, ConnectPoint connectPoint, ProbeMode probeMode);
-
+    @Deprecated
+    void probeHost(Host host, ConnectPoint connectPoint, ProbeMode probeMode);
 }
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbe.java b/core/api/src/main/java/org/onosproject/net/host/HostProbe.java
new file mode 100644
index 0000000..7303a3d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbe.java
@@ -0,0 +1,58 @@
+/*
+ * 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.net.host;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+
+/**
+ * Information related to the host being probed.
+ */
+public interface HostProbe extends Host {
+    /**
+     * Gets connect point of this entry.
+     *
+     * @return connect point
+     */
+    ConnectPoint connectPoint();
+
+    /**
+     * Gets retry counter of this entry.
+     *
+     * @return retry
+     */
+    int retry();
+
+    /**
+     * Decrease retry counter of this entry by one.
+     */
+    void decreaseRetry();
+
+    /**
+     * Gets mode of this entry.
+     *
+     * @return mode
+     */
+    ProbeMode mode();
+
+    /**
+     * Gets probe MAC of this entry.
+     *
+     * @return probe mac
+     */
+    MacAddress probeMac();
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbeStore.java b/core/api/src/main/java/org/onosproject/net/host/HostProbeStore.java
new file mode 100644
index 0000000..ba1217d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbeStore.java
@@ -0,0 +1,49 @@
+/*
+ * 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.net.host;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+import org.onosproject.store.Store;
+
+/**
+ * Manages inventory of pending host probes.
+ */
+public interface HostProbeStore extends Store<HostProbingEvent, HostProbingStoreDelegate> {
+
+    /**
+     * Notifies HostProbeStore the beginning of pending host location verification and
+     * retrieves the unique MAC address for the probe.
+     *
+     * @param host host to be probed
+     * @param connectPoint the connect point that is under verification
+     * @param probeMode probe mode
+     * @param probeMac probeMac if this is a retry.
+     *                 Null if this is the very first probe and the probeMac is to-be-generated
+     * @param retry max retry times
+     * @return probeMac, the source MAC address ONOS uses to probe the host
+     */
+    MacAddress addProbingHost(Host host, ConnectPoint connectPoint, ProbeMode probeMode,
+                                      MacAddress probeMac, int retry);
+
+    /**
+     * Notifies HostProbeStore the end of pending host location verification.
+     *
+     * @param probeMac the source MAC address ONOS uses to probe the host
+     */
+    void removeProbingHost(MacAddress probeMac);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbingEvent.java b/core/api/src/main/java/org/onosproject/net/host/HostProbingEvent.java
new file mode 100644
index 0000000..b77334a
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbingEvent.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2014-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.net.host;
+
+import org.onlab.util.Tools;
+import org.onosproject.event.AbstractEvent;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Describes host probing event.
+ */
+public class HostProbingEvent extends AbstractEvent<HostProbingEvent.Type, HostProbe> {
+
+    /**
+     * Type of host probing events.
+     */
+    public enum Type {
+        /**
+         * Probe has been requested.
+         */
+        PROBE_REQUESTED,
+
+        /**
+         * Probe timed out but still have not reach max retry.
+         */
+        PROBE_TIMEOUT,
+
+        /**
+         * Probe timed out and reach max retry.
+         */
+        PROBE_FAIL,
+
+        /**
+         * Probe has been complete normally.
+         */
+        PROBE_COMPLETED
+    }
+
+    private HostProbe prevSubject;
+
+    /**
+     * Creates an event of a given type and for the specified host probe and the
+     * current time.
+     *
+     * @param type probing host event type
+     * @param subject event subject
+     */
+    public HostProbingEvent(Type type, HostProbe subject) {
+        super(type, subject);
+    }
+
+    /**
+     * Creates an event of a given type and for the specified host probe and time.
+     *
+     * @param type probing host event type
+     * @param subject event subject
+     * @param time occurrence time
+     */
+    public HostProbingEvent(Type type, HostProbe subject, long time) {
+        super(type, subject, time);
+    }
+
+    /**
+     * Creates an event with previous subject.
+     * The previous subject is ignored if the type is not PROBE_TIMEOUT
+     *
+     * @param type host event type
+     * @param subject event subject
+     * @param prevSubject previous host subject
+     */
+    public HostProbingEvent(Type type, HostProbe subject, HostProbe prevSubject) {
+        super(type, subject);
+        this.prevSubject = prevSubject;
+    }
+
+    /**
+     * Creates an event with previous subject and specified time.
+     * The previous subject is ignored if the type is not PROBE_TIMEOUT
+     *
+     * @param type host event type
+     * @param subject event subject
+     * @param prevSubject previous host subject
+     * @param time occurrence time
+     */
+    public HostProbingEvent(Type type, HostProbe subject, HostProbe prevSubject, long time) {
+        super(type, subject, time);
+        this.prevSubject = prevSubject;
+    }
+
+    /**
+     * Gets the previous subject in this host probe event.
+     *
+     * @return the previous subject, or null if previous subject is not
+     *         specified.
+     */
+    public HostProbe prevSubject() {
+        return this.prevSubject;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("time", Tools.defaultOffsetDataTime(time()))
+                .add("type", type())
+                .add("subject", subject())
+                .add("prevSubject", prevSubject())
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbingListener.java b/core/api/src/main/java/org/onosproject/net/host/HostProbingListener.java
new file mode 100644
index 0000000..25fd1ea
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbingListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.net.host;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving host probing related events.
+ */
+public interface HostProbingListener extends EventListener<HostProbingEvent> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbingProvider.java b/core/api/src/main/java/org/onosproject/net/host/HostProbingProvider.java
new file mode 100644
index 0000000..f126013
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbingProvider.java
@@ -0,0 +1,42 @@
+/*
+ * 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.net.host;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+import org.onosproject.net.provider.Provider;
+
+/**
+ * Provider of host probing.
+ */
+public interface HostProbingProvider extends Provider {
+
+    /**
+     * Probe given host on the given connectPoint with given probeMode.
+     *
+     * @param host host to be probed
+     * @param connectPoint connect point on which the probe is sent
+     * @param probeMode probe mode
+     */
+    void probeHost(Host host, ConnectPoint connectPoint, ProbeMode probeMode);
+
+    /**
+     * Process host probing events.
+     *
+     * @param event host probing event
+     */
+    void processEvent(HostProbingEvent event);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbingProviderRegistry.java b/core/api/src/main/java/org/onosproject/net/host/HostProbingProviderRegistry.java
new file mode 100644
index 0000000..915df6c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbingProviderRegistry.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014-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.net.host;
+
+import org.onosproject.net.provider.ProviderRegistry;
+
+/**
+ * Abstraction of a host probing provider registry.
+ */
+public interface HostProbingProviderRegistry
+        extends ProviderRegistry<HostProbingProvider, HostProbingProviderService> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbingProviderService.java b/core/api/src/main/java/org/onosproject/net/host/HostProbingProviderService.java
new file mode 100644
index 0000000..d9c7c16
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbingProviderService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014-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.net.host;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+import org.onosproject.net.provider.ProviderService;
+
+/**
+ * Means of conveying host probing information to the core.
+ */
+public interface HostProbingProviderService extends ProviderService<HostProbingProvider> {
+
+    /**
+     * Notifies HostProbeStore the beginning of pending host location verification and
+     * retrieves the unique MAC address for the probe.
+     *
+     * @param host host to be probed
+     * @param connectPoint the connect point that is under verification
+     * @param probeMode probe mode
+     * @param probeMac probeMac if this is a retry.
+     *                 Null if this is the very first probe and the probeMac is to-be-generated
+     * @param retry max retry times
+     * @return probeMac, the source MAC address ONOS uses to probe the host
+     */
+     MacAddress addProbingHost(Host host, ConnectPoint connectPoint, ProbeMode probeMode,
+                                      MacAddress probeMac, int retry);
+
+    /**
+     * Notifies HostProbeStore the end of pending host location verification.
+     *
+     * @param probeMac the source MAC address ONOS uses to probe the host
+     */
+     void removeProbingHost(MacAddress probeMac);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbingService.java b/core/api/src/main/java/org/onosproject/net/host/HostProbingService.java
new file mode 100644
index 0000000..6113dd4
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbingService.java
@@ -0,0 +1,33 @@
+/*
+ * 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.net.host;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+
+/**
+ * Service for interacting with the host probing entities.
+ */
+public interface HostProbingService {
+    /**
+     * Probes given host on given location.
+     *
+     * @param host the host to be probed
+     * @param connectPoint the location of host to be probed
+     * @param probeMode probe mode
+     */
+    void probeHost(Host host, ConnectPoint connectPoint, ProbeMode probeMode);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProbingStoreDelegate.java b/core/api/src/main/java/org/onosproject/net/host/HostProbingStoreDelegate.java
new file mode 100644
index 0000000..5221951
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProbingStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * 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.net.host;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Host probing store delegate abstraction.
+ */
+public interface HostProbingStoreDelegate extends StoreDelegate<HostProbingEvent> {
+}
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java b/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java
index d9aeff5..f3dc7ab 100644
--- a/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java
+++ b/core/api/src/main/java/org/onosproject/net/host/HostProviderService.java
@@ -15,12 +15,12 @@
  */
 package org.onosproject.net.host;
 
+import org.apache.commons.lang3.NotImplementedException;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.HostId;
 import org.onosproject.net.HostLocation;
-import org.onosproject.net.host.HostLocationProbingService.ProbeMode;
 import org.onosproject.net.provider.ProviderService;
 
 /**
@@ -54,6 +54,16 @@
     void removeIpFromHost(HostId hostId, IpAddress ipAddress);
 
     /**
+     * Notifies the core when a location is associated with a host.
+     *
+     * @param hostId id of the host
+     * @param location location of host that gets discovered
+     */
+    default void addLocationToHost(HostId hostId, HostLocation location) {
+        throw new NotImplementedException("addLocationToHost is not implemented");
+    }
+
+    /**
      * Notifies the core when a location is no longer associated with a host.
      *
      * @param hostId id of the host
@@ -69,7 +79,9 @@
      * @param connectPoint the connect point that is under verification
      * @param probeMode probe mode
      * @return probeMac, the source MAC address ONOS uses to probe the host
+     * @deprecated in ONOS 1.12, replaced by {@link HostProbingProviderService}
      */
+    @Deprecated
     default MacAddress addPendingHostLocation(HostId hostId, ConnectPoint connectPoint, ProbeMode probeMode) {
         return MacAddress.NONE;
     }
@@ -78,6 +90,8 @@
      * Notifies HostProviderService the end of pending host location verification.
      *
      * @param probeMac the source MAC address ONOS uses to probe the host
+     * @deprecated in ONOS 1.12, replaced by {@link HostProbingProviderService}
      */
+    @Deprecated
     default void removePendingHostLocation(MacAddress probeMac) {}
 }
diff --git a/core/api/src/main/java/org/onosproject/net/host/HostStore.java b/core/api/src/main/java/org/onosproject/net/host/HostStore.java
index 96d3c31..0b6238b 100644
--- a/core/api/src/main/java/org/onosproject/net/host/HostStore.java
+++ b/core/api/src/main/java/org/onosproject/net/host/HostStore.java
@@ -23,7 +23,6 @@
 import org.onosproject.net.Host;
 import org.onosproject.net.HostId;
 import org.onosproject.net.HostLocation;
-import org.onosproject.net.host.HostLocationProbingService.ProbeMode;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.store.Store;
 
diff --git a/core/api/src/main/java/org/onosproject/net/host/ProbeMode.java b/core/api/src/main/java/org/onosproject/net/host/ProbeMode.java
new file mode 100644
index 0000000..bc3efbf
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/host/ProbeMode.java
@@ -0,0 +1,33 @@
+/*
+ * 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.net.host;
+
+/**
+ * Mode of host location probing.
+ */
+public enum ProbeMode {
+    /**
+     * Append probed host location if reply is received before timeout. Otherwise, do nothing.
+     * Typically used to discover secondary locations.
+     */
+    DISCOVER,
+
+    /**
+     * Remove probed host location if reply is received after timeout. Otherwise, do nothing.
+     * Typically used to verify previous locations.
+     */
+    VERIFY
+}