diff --git a/apps/proxyarp/src/main/java/org/onosproject/proxyarp/ProxyArp.java b/apps/proxyarp/src/main/java/org/onosproject/proxyarp/ProxyArp.java
deleted file mode 100644
index d441aee..0000000
--- a/apps/proxyarp/src/main/java/org/onosproject/proxyarp/ProxyArp.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 2014-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.proxyarp;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Modified;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv6;
-import org.onlab.util.Tools;
-import org.onosproject.cfg.ComponentConfigService;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.proxyarp.ProxyArpService;
-import org.osgi.service.component.ComponentContext;
-import org.slf4j.Logger;
-
-import java.util.Dictionary;
-
-import static org.onlab.packet.Ethernet.TYPE_ARP;
-import static org.onlab.packet.Ethernet.TYPE_IPV6;
-import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
-import static org.onlab.packet.ICMP6.NEIGHBOR_SOLICITATION;
-import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
-import static org.onosproject.net.packet.PacketPriority.CONTROL;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Sample reactive proxy arp application.
- *
- * @deprecated in Hummingbird release
- */
-@Deprecated
-@Component(enabled = false)
-public class ProxyArp {
-
-    private final Logger log = getLogger(getClass());
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected PacketService packetService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ProxyArpService proxyArpService;
-
-    private ProxyArpProcessor processor = new ProxyArpProcessor();
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected CoreService coreService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ComponentConfigService cfgService;
-
-    private ApplicationId appId;
-
-    @Property(name = "ipv6NeighborDiscovery", boolValue = false,
-            label = "Enable IPv6 Neighbor Discovery; default is false")
-    protected boolean ipv6NeighborDiscovery = false;
-
-    @Activate
-    public void activate(ComponentContext context) {
-        cfgService.registerProperties(getClass());
-        appId = coreService.registerApplication("org.onosproject.proxyarp");
-
-        packetService.addProcessor(processor, PacketProcessor.director(1));
-        readComponentConfiguration(context);
-        requestPackets();
-
-        log.info("Started with Application ID {}", appId.id());
-    }
-
-    @Deactivate
-    public void deactivate() {
-        cfgService.unregisterProperties(getClass(), false);
-        withdrawIntercepts();
-        packetService.removeProcessor(processor);
-        processor = null;
-        log.info("Stopped");
-    }
-
-    @Modified
-    public void modified(ComponentContext context) {
-        readComponentConfiguration(context);
-        requestPackets();
-    }
-
-    /**
-     * Request packet in via PacketService.
-     */
-    private void requestPackets() {
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(TYPE_ARP);
-        packetService.requestPackets(selectorBuilder.build(),
-                                     CONTROL, appId);
-
-        selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(TYPE_IPV6);
-        selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
-        selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
-        if (ipv6NeighborDiscovery) {
-            // IPv6 Neighbor Solicitation packet.
-            packetService.requestPackets(selectorBuilder.build(),
-                                         CONTROL, appId);
-        } else {
-            packetService.cancelPackets(selectorBuilder.build(),
-                                        CONTROL, appId);
-        }
-
-        // IPv6 Neighbor Advertisement packet.
-        selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(TYPE_IPV6);
-        selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
-        selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
-        if (ipv6NeighborDiscovery) {
-            packetService.requestPackets(selectorBuilder.build(),
-                                         CONTROL, appId);
-        } else {
-            packetService.cancelPackets(selectorBuilder.build(),
-                                        CONTROL, appId);
-        }
-
-
-    }
-
-    /**
-     * Cancel requested packet in via packet service.
-     */
-    private void withdrawIntercepts() {
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(TYPE_ARP);
-        packetService.cancelPackets(selectorBuilder.build(), CONTROL, appId);
-        selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(TYPE_IPV6);
-        selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
-        selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
-        packetService.cancelPackets(selectorBuilder.build(), CONTROL, appId);
-        selectorBuilder = DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(TYPE_IPV6);
-        selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
-        selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
-        packetService.cancelPackets(selectorBuilder.build(), CONTROL, appId);
-
-    }
-
-    /**
-     * Extracts properties from the component configuration context.
-     *
-     * @param context the component context
-     */
-    private void readComponentConfiguration(ComponentContext context) {
-        Dictionary<?, ?> properties = context.getProperties();
-        Boolean flag;
-
-        flag = Tools.isPropertyEnabled(properties, "ipv6NeighborDiscovery");
-        if (flag == null) {
-            log.info("IPv6 Neighbor Discovery is not configured, " +
-                             "using current value of {}", ipv6NeighborDiscovery);
-        } else {
-            ipv6NeighborDiscovery = flag;
-            log.info("Configured. IPv6 Neighbor Discovery is {}",
-                     ipv6NeighborDiscovery ? "enabled" : "disabled");
-        }
-    }
-
-    /**
-     * Packet processor responsible for forwarding packets along their paths.
-     */
-    private class ProxyArpProcessor implements PacketProcessor {
-
-        @Override
-        public void process(PacketContext context) {
-            // Stop processing if the packet has been handled, since we
-            // can't do any more to it.
-            if (context.isHandled()) {
-                return;
-            }
-
-            InboundPacket pkt = context.inPacket();
-            Ethernet ethPkt = pkt.parsed();
-            if (ethPkt == null) {
-                return;
-            }
-
-            if (ethPkt.getEtherType() == TYPE_ARP) {
-                //handle the arp packet.
-                proxyArpService.handlePacket(context);
-            } else if (ipv6NeighborDiscovery && ethPkt.getEtherType() == TYPE_IPV6) {
-                IPv6 ipv6Pkt = (IPv6) ethPkt.getPayload();
-                if (ipv6Pkt.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
-                    ICMP6 icmp6Pkt = (ICMP6) ipv6Pkt.getPayload();
-                    if (icmp6Pkt.getIcmpType() == NEIGHBOR_SOLICITATION ||
-                        icmp6Pkt.getIcmpType() == NEIGHBOR_ADVERTISEMENT) {
-                        // handle ICMPv6 solicitations and advertisements
-                        proxyArpService.handlePacket(context);
-                    }
-                }
-            }
-
-            // FIXME why were we listening to IPv4 frames at all?
-            // Do not ARP for multicast packets.  Let mfwd handle them.
-            if (ethPkt.getEtherType() == Ethernet.TYPE_IPV4) {
-                if (ethPkt.getDestinationMAC().isMulticast()) {
-                    return;
-                }
-            }
-        }
-    }
-}
diff --git a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java b/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java
deleted file mode 100644
index 015a263..0000000
--- a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpService.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2014-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.net.proxyarp;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpAddress;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.packet.PacketContext;
-
-/**
- * Service for processing ARP or NDP requests on behalf of applications.
- *
- * @deprecated in Hummingbird release. Use NeighbourResolutionService instead.
- */
-// TODO: move to the peer host package
-@Deprecated
-public interface ProxyArpService {
-
-    /**
-     * Returns whether this particular IP address is known to the system.
-     *
-     * @param addr an IP address
-     * @return true if know, false otherwise
-     */
-    boolean isKnown(IpAddress addr);
-
-    /**
-     * Sends a reply for a given request. If the host is not known then the
-     * arp or neighbor solicitation will be flooded at all edge ports.
-     *
-     * @param eth an arp or neighbor solicitation request
-     * @param inPort the port the request was received on
-     */
-    void reply(Ethernet eth, ConnectPoint inPort);
-
-    /**
-     * Forwards an ARP or neighbor solicitation request to its destination.
-     * Floods at the edg the request if the destination is not known.
-     *
-     * @param eth an ethernet frame containing an ARP or neighbor solicitation
-     * request.
-     * @param inPort the port the request was received on
-     */
-    void forward(Ethernet eth, ConnectPoint inPort);
-
-    /**
-     * Handles a arp or neighbor solicitation packet.
-     * Replies to arp or neighbor solicitation requests and forwards request
-     * to the right place.
-     * @param context the packet context to handle
-     * @return true if handled, false otherwise.
-     */
-    boolean handlePacket(PacketContext context);
-}
diff --git a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java b/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java
deleted file mode 100644
index 708f92f..0000000
--- a/core/api/src/main/java/org/onosproject/net/proxyarp/ProxyArpStore.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2015-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.net.proxyarp;
-
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-
-import java.nio.ByteBuffer;
-
-/**
- * State distribution mechanism for the proxy ARP service.
- *
- * @deprecated in Hummingbird release. This is no longer necessary as there are
- * other solutions for the problem this was solving.
- */
-@Deprecated
-public interface ProxyArpStore {
-
-    /**
-     * Forwards an ARP or neighbor solicitation request to its destination.
-     * Floods at the edg the request if the destination is not known.
-     *
-     * @param outPort the port the request was received on
-     * @param subject subject host
-     * @param packet  an ethernet frame containing an ARP or neighbor
-     *                solicitation request
-     */
-    void forward(ConnectPoint outPort, Host subject, ByteBuffer packet);
-
-    /**
-     * Associates the specified delegate with the store.
-     *
-     * @param delegate store delegate
-     */
-    void setDelegate(ProxyArpStoreDelegate delegate);
-}
diff --git a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
deleted file mode 100644
index a4fd544..0000000
--- a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * Copyright 2014-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.net.proxyarp.impl;
-
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.packet.ARP;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ndp.NeighborAdvertisement;
-import org.onlab.packet.ndp.NeighborDiscoveryOptions;
-import org.onlab.packet.ndp.NeighborSolicitation;
-import org.onosproject.incubator.net.intf.Interface;
-import org.onosproject.incubator.net.intf.InterfaceService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.edge.EdgePortService;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.proxyarp.ProxyArpService;
-import org.onosproject.net.proxyarp.ProxyArpStore;
-import org.slf4j.Logger;
-
-import java.nio.ByteBuffer;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onlab.packet.VlanId.vlanId;
-import static org.onosproject.net.HostId.hostId;
-import static org.onosproject.security.AppGuard.checkPermission;
-import static org.slf4j.LoggerFactory.getLogger;
-import static org.onosproject.security.AppPermission.Type.*;
-
-/**
- * Implementation of the proxy ARP service.
- *
- * @deprecated in Hummingbird release
- */
-@Deprecated
-@Component(immediate = true)
-@Service
-public class ProxyArpManager implements ProxyArpService {
-
-    private final Logger log = getLogger(getClass());
-
-    private static final String MAC_ADDR_NULL = "MAC address cannot be null.";
-    private static final String REQUEST_NULL = "ARP or NDP request cannot be null.";
-    private static final String MSG_NOT_REQUEST = "Message is not an ARP or NDP request";
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected EdgePortService edgeService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected HostService hostService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected PacketService packetService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected LinkService linkService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ProxyArpStore store;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected InterfaceService interfaceService;
-
-    private enum Protocol {
-        ARP, NDP
-    }
-
-    private enum MessageType {
-        REQUEST, REPLY
-    }
-
-    @Activate
-    public void activate() {
-        store.setDelegate(this::sendTo);
-        log.info("Started");
-    }
-
-    @Deactivate
-    public void deactivate() {
-        store.setDelegate(null);
-        log.info("Stopped");
-    }
-
-    @Override
-    public boolean isKnown(IpAddress addr) {
-        checkPermission(PACKET_READ);
-
-        checkNotNull(addr, MAC_ADDR_NULL);
-        Set<Host> hosts = hostService.getHostsByIp(addr);
-        return !hosts.isEmpty();
-    }
-
-    @Override
-    public void reply(Ethernet eth, ConnectPoint inPort) {
-        checkPermission(PACKET_WRITE);
-
-        checkNotNull(eth, REQUEST_NULL);
-
-        MessageContext context = createContext(eth, inPort);
-        if (context != null) {
-            replyInternal(context);
-        }
-    }
-
-    /**
-     * Handles a request message.
-     *
-     * If the MAC address of the target is known, we can reply directly to the
-     * requestor. Otherwise, we forward the request out other ports in an
-     * attempt to find the correct host.
-     *
-     * @param context request message context to process
-     */
-    private void replyInternal(MessageContext context) {
-        checkNotNull(context);
-        checkArgument(context.type() == MessageType.REQUEST, MSG_NOT_REQUEST);
-
-        if (hasIpAddress(context.inPort())) {
-            // If the request came from outside the network, only reply if it was
-            // for one of our external addresses.
-
-            interfaceService.getInterfacesByPort(context.inPort())
-                    .stream()
-                    .filter(intf -> intf.ipAddressesList()
-                            .stream()
-                            .anyMatch(ia -> ia.ipAddress().equals(context.target())))
-                    .forEach(intf -> buildAndSendReply(context, intf.mac()));
-
-            // Stop here and don't proxy ARPs if the port has an IP address
-            return;
-        }
-
-        // See if we have the target host in the host store
-        Set<Host> hosts = hostService.getHostsByIp(context.target());
-
-        Host dst = null;
-        Host src = hostService.getHost(hostId(context.srcMac(), context.vlan()));
-
-        for (Host host : hosts) {
-            if (host.vlan().equals(context.vlan())) {
-                dst = host;
-                break;
-            }
-        }
-
-        if (src != null && dst != null) {
-            // We know the target host so we can respond
-            buildAndSendReply(context, dst.mac());
-            return;
-        }
-
-        // If the source address matches one of our external addresses
-        // it could be a request from an internal host to an external
-        // address. Forward it over to the correct port.
-        boolean matched = false;
-        Set<Interface> interfaces = interfaceService.getInterfacesByIp(context.sender());
-        for (Interface intf : interfaces) {
-            if (intf.vlan().equals(context.vlan())) {
-                matched = true;
-                sendTo(context.packet(), intf.connectPoint());
-                break;
-            }
-        }
-
-        if (matched) {
-            return;
-        }
-
-        // If the packets has a vlanId look if there are some other
-        // interfaces in the configuration on the same vlan and broadcast
-        // the packet out just of through those interfaces.
-        VlanId vlanId = context.vlan();
-
-        Set<Interface> filteredVlanInterfaces =
-                filterVlanInterfacesNoIp(interfaceService.getInterfacesByVlan(vlanId));
-
-        if (vlanId != null
-        && !vlanId.equals(VlanId.NONE)
-        && confContainsVlans(vlanId, context.inPort())) {
-            vlanFlood(context.packet(), filteredVlanInterfaces, context.inPort);
-            return;
-        }
-
-        // The request couldn't be resolved.
-        // Flood the request on all ports except the incoming port.
-        flood(context.packet(), context.inPort());
-    }
-
-    private Set<Interface> filterVlanInterfacesNoIp(Set<Interface> vlanInterfaces) {
-        return vlanInterfaces
-                .stream()
-                .filter(intf -> intf.ipAddressesList().isEmpty())
-                .collect(Collectors.toSet());
-    }
-
-    /**
-     * States if the interface configuration contains more than one interface configured
-     * on a specific vlan, including the interface passed as argument.
-     *
-     * @param vlanId the vlanid to look for in the interface configuration
-     * @param connectPoint the connect point to exclude from the search
-     * @return true if interfaces are found. False otherwise
-     */
-    private boolean confContainsVlans(VlanId vlanId, ConnectPoint connectPoint) {
-        Set<Interface> vlanInterfaces = interfaceService.getInterfacesByVlan(vlanId);
-        return interfaceService.getInterfacesByVlan(vlanId)
-                .stream()
-                .anyMatch(intf -> intf.connectPoint().equals(connectPoint) && intf.ipAddressesList().isEmpty())
-                && vlanInterfaces.size() > 1;
-    }
-
-    /**
-     * Builds and sends a reply message given a request context and the resolved
-     * MAC address to answer with.
-     *
-     * @param context message context of request
-     * @param targetMac MAC address to be given in the response
-     */
-    private void buildAndSendReply(MessageContext context, MacAddress targetMac) {
-        switch (context.protocol()) {
-        case ARP:
-            sendTo(ARP.buildArpReply((Ip4Address) context.target(),
-                    targetMac, context.packet()), context.inPort());
-            break;
-        case NDP:
-            sendTo(buildNdpReply((Ip6Address) context.target(), targetMac,
-                    context.packet()), context.inPort());
-            break;
-        default:
-            break;
-        }
-    }
-
-    /**
-     * Outputs a packet out a specific port.
-     *
-     * @param packet  the packet to send
-     * @param outPort the port to send it out
-     */
-    private void sendTo(Ethernet packet, ConnectPoint outPort) {
-        sendTo(outPort, ByteBuffer.wrap(packet.serialize()));
-    }
-
-    /**
-     * Outputs a packet out a specific port.
-     *
-     * @param outPort port to send it out
-     * @param packet packet to send
-     */
-    private void sendTo(ConnectPoint outPort, ByteBuffer packet) {
-        if (!edgeService.isEdgePoint(outPort)) {
-            // Sanity check to make sure we don't send the packet out an
-            // internal port and create a loop (could happen due to
-            // misconfiguration).
-            return;
-        }
-
-        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
-        builder.setOutput(outPort.port());
-        packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
-                builder.build(), packet));
-    }
-
-    /**
-     * Returns whether the given port has any IP addresses configured or not.
-     *
-     * @param connectPoint the port to check
-     * @return true if the port has at least one IP address configured,
-     * false otherwise
-     */
-    private boolean hasIpAddress(ConnectPoint connectPoint) {
-        return interfaceService.getInterfacesByPort(connectPoint)
-                .stream()
-                .flatMap(intf -> intf.ipAddressesList().stream())
-                .findAny()
-                .isPresent();
-    }
-
-    /**
-     * Returns whether the given port has any VLAN configured or not.
-     *
-     * @param connectPoint the port to check
-     * @return true if the port has at least one VLAN configured,
-     * false otherwise
-     */
-    private boolean hasVlan(ConnectPoint connectPoint) {
-        return interfaceService.getInterfacesByPort(connectPoint)
-                .stream()
-                .filter(intf -> !intf.vlan().equals(VlanId.NONE))
-                .findAny()
-                .isPresent();
-    }
-
-    @Override
-    public void forward(Ethernet eth, ConnectPoint inPort) {
-        checkPermission(PACKET_WRITE);
-
-        checkNotNull(eth, REQUEST_NULL);
-
-        Host h = hostService.getHost(hostId(eth.getDestinationMAC(),
-                vlanId(eth.getVlanID())));
-
-        if (h == null) {
-            flood(eth, inPort);
-        } else {
-            Host subject = hostService.getHost(hostId(eth.getSourceMAC(),
-                                                      vlanId(eth.getVlanID())));
-            store.forward(h.location(), subject, ByteBuffer.wrap(eth.serialize()));
-        }
-    }
-
-    @Override
-    public boolean handlePacket(PacketContext context) {
-        checkPermission(PACKET_WRITE);
-
-        InboundPacket pkt = context.inPacket();
-        Ethernet ethPkt = pkt.parsed();
-
-        if (ethPkt == null) {
-            return false;
-        }
-
-        MessageContext msgContext = createContext(ethPkt, pkt.receivedFrom());
-
-        if (msgContext == null) {
-            return false;
-        }
-
-        switch (msgContext.type()) {
-        case REPLY:
-            forward(msgContext.packet(), msgContext.inPort());
-            break;
-        case REQUEST:
-            replyInternal(msgContext);
-            break;
-        default:
-            return false;
-        }
-
-        context.block();
-        return true;
-    }
-
-    /**
-     * Flood the arp request at all edges on a specifc VLAN.
-     *
-     * @param request the arp request
-     * @param dsts the destination interfaces
-     * @param inPort the connect point the arp request was received on
-     */
-    private void vlanFlood(Ethernet request, Set<Interface> dsts, ConnectPoint inPort) {
-        TrafficTreatment.Builder builder = null;
-        ByteBuffer buf = ByteBuffer.wrap(request.serialize());
-
-        for (Interface intf : dsts) {
-            ConnectPoint cPoint = intf.connectPoint();
-            if (cPoint.equals(inPort)) {
-                continue;
-            }
-
-            builder = DefaultTrafficTreatment.builder();
-            builder.setOutput(cPoint.port());
-            packetService.emit(new DefaultOutboundPacket(cPoint.deviceId(),
-                    builder.build(), buf));
-        }
-    }
-
-    /**
-     * Flood the arp request at all edges in the network.
-     *
-     * @param request the arp request
-     * @param inPort  the connect point the arp request was received on
-     */
-    private void flood(Ethernet request, ConnectPoint inPort) {
-        TrafficTreatment.Builder builder = null;
-        ByteBuffer buf = ByteBuffer.wrap(request.serialize());
-
-        for (ConnectPoint connectPoint : edgeService.getEdgePoints()) {
-            if (hasIpAddress(connectPoint)
-             || hasVlan(connectPoint)
-             || connectPoint.equals(inPort)) {
-                continue;
-            }
-
-            builder = DefaultTrafficTreatment.builder();
-            builder.setOutput(connectPoint.port());
-            packetService.emit(new DefaultOutboundPacket(connectPoint.deviceId(),
-                                                         builder.build(), buf));
-        }
-    }
-
-    /**
-     * Builds an Neighbor Discovery reply based on a request.
-     *
-     * @param srcIp   the IP address to use as the reply source
-     * @param srcMac  the MAC address to use as the reply source
-     * @param request the Neighbor Solicitation request we got
-     * @return an Ethernet frame containing the Neighbor Advertisement reply
-     */
-    private Ethernet buildNdpReply(Ip6Address srcIp, MacAddress srcMac,
-                                   Ethernet request) {
-        Ethernet eth = new Ethernet();
-        eth.setDestinationMACAddress(request.getSourceMAC());
-        eth.setSourceMACAddress(srcMac);
-        eth.setEtherType(Ethernet.TYPE_IPV6);
-        eth.setVlanID(request.getVlanID());
-
-        IPv6 requestIp = (IPv6) request.getPayload();
-        IPv6 ipv6 = new IPv6();
-        ipv6.setSourceAddress(srcIp.toOctets());
-        ipv6.setDestinationAddress(requestIp.getSourceAddress());
-        ipv6.setHopLimit((byte) 255);
-
-        ICMP6 icmp6 = new ICMP6();
-        icmp6.setIcmpType(ICMP6.NEIGHBOR_ADVERTISEMENT);
-        icmp6.setIcmpCode((byte) 0);
-
-        NeighborAdvertisement nadv = new NeighborAdvertisement();
-        nadv.setTargetAddress(srcIp.toOctets());
-        nadv.setSolicitedFlag((byte) 1);
-        nadv.setOverrideFlag((byte) 1);
-        nadv.addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
-                       srcMac.toBytes());
-
-        icmp6.setPayload(nadv);
-        ipv6.setPayload(icmp6);
-        eth.setPayload(ipv6);
-        return eth;
-    }
-
-    /**
-     * Attempts to create a MessageContext for the given Ethernet frame. If the
-     * frame is a valid ARP or NDP request or response, a context will be
-     * created.
-     *
-     * @param eth input Ethernet frame
-     * @param inPort in port
-     * @return MessageContext if the packet was ARP or NDP, otherwise null
-     */
-    private MessageContext createContext(Ethernet eth, ConnectPoint inPort) {
-        if (eth.getEtherType() == Ethernet.TYPE_ARP) {
-            return createArpContext(eth, inPort);
-        } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
-            return createNdpContext(eth, inPort);
-        }
-
-        return null;
-    }
-
-    /**
-     * Extracts context information from ARP packets.
-     *
-     * @param eth input Ethernet frame that is thought to be ARP
-     * @param inPort in port
-     * @return MessageContext object if the packet was a valid ARP packet,
-     * otherwise null
-     */
-    private MessageContext createArpContext(Ethernet eth, ConnectPoint inPort) {
-        if (eth.getEtherType() != Ethernet.TYPE_ARP) {
-            return null;
-        }
-
-        ARP arp = (ARP) eth.getPayload();
-
-        IpAddress target = Ip4Address.valueOf(arp.getTargetProtocolAddress());
-        IpAddress sender = Ip4Address.valueOf(arp.getSenderProtocolAddress());
-
-        MessageType type;
-        if (arp.getOpCode() == ARP.OP_REQUEST) {
-            type = MessageType.REQUEST;
-        } else if (arp.getOpCode() == ARP.OP_REPLY) {
-            type = MessageType.REPLY;
-        } else {
-            return null;
-        }
-
-        return new MessageContext(eth, inPort, Protocol.ARP, type, target, sender);
-    }
-
-    /**
-     * Extracts context information from NDP packets.
-     *
-     * @param eth input Ethernet frame that is thought to be NDP
-     * @param inPort in port
-     * @return MessageContext object if the packet was a valid NDP packet,
-     * otherwise null
-     */
-    private MessageContext createNdpContext(Ethernet eth, ConnectPoint inPort) {
-        if (eth.getEtherType() != Ethernet.TYPE_IPV6) {
-            return null;
-        }
-        IPv6 ipv6 = (IPv6) eth.getPayload();
-
-        if (ipv6.getNextHeader() != IPv6.PROTOCOL_ICMP6) {
-            return null;
-        }
-        ICMP6 icmpv6 = (ICMP6) ipv6.getPayload();
-
-        IpAddress sender = Ip6Address.valueOf(ipv6.getSourceAddress());
-        IpAddress target = null;
-
-        MessageType type;
-        if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_SOLICITATION) {
-            type = MessageType.REQUEST;
-            NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload();
-            target = Ip6Address.valueOf(nsol.getTargetAddress());
-        } else if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT) {
-            type = MessageType.REPLY;
-        } else {
-            return null;
-        }
-
-        return new MessageContext(eth, inPort, Protocol.NDP, type, target, sender);
-    }
-
-    /**
-     * Provides context information for a particular ARP or NDP message, with
-     * a unified interface to access data regardless of protocol.
-     */
-    private class MessageContext {
-        private Protocol protocol;
-        private MessageType type;
-
-        private IpAddress target;
-        private IpAddress sender;
-
-        private Ethernet eth;
-        private ConnectPoint inPort;
-
-
-        public MessageContext(Ethernet eth, ConnectPoint inPort,
-                              Protocol protocol, MessageType type,
-                              IpAddress target, IpAddress sender) {
-            this.eth = eth;
-            this.inPort = inPort;
-            this.protocol = protocol;
-            this.type = type;
-            this.target = target;
-            this.sender = sender;
-        }
-
-        public ConnectPoint inPort() {
-            return inPort;
-        }
-
-        public Ethernet packet() {
-            return eth;
-        }
-
-        public Protocol protocol() {
-            return protocol;
-        }
-
-        public MessageType type() {
-            return type;
-        }
-
-        public VlanId vlan() {
-            return VlanId.vlanId(eth.getVlanID());
-        }
-
-        public MacAddress srcMac() {
-            return MacAddress.valueOf(eth.getSourceMACAddress());
-        }
-
-        public IpAddress target() {
-            return target;
-        }
-
-        public IpAddress sender() {
-            return sender;
-        }
-    }
-}
diff --git a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/package-info.java b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/package-info.java
deleted file mode 100644
index 13849d2..0000000
--- a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2014-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.
- */
-
-/**
- * Core subsystem for responding to arp requests.
- */
-package org.onosproject.net.proxyarp.impl;
diff --git a/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java b/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
deleted file mode 100644
index 6e91ab0..0000000
--- a/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
+++ /dev/null
@@ -1,1186 +0,0 @@
-/*
- * Copyright 2014-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.net.proxyarp.impl;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Before;
-import org.junit.Test;
-import org.onlab.packet.ARP;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.ICMP6;
-import org.onlab.packet.IPacket;
-import org.onlab.packet.IPv6;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.Ip6Address;
-import org.onlab.packet.Ip6Prefix;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
-import org.onlab.packet.ndp.NeighborAdvertisement;
-import org.onlab.packet.ndp.NeighborDiscoveryOptions;
-import org.onlab.packet.ndp.NeighborSolicitation;
-import org.onosproject.incubator.net.intf.Interface;
-import org.onosproject.incubator.net.intf.InterfaceService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DefaultHost;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.HostLocation;
-import org.onosproject.net.Link;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.edge.EdgePortService;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flow.instructions.Instruction;
-import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.link.LinkListener;
-import org.onosproject.net.link.LinkService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.net.packet.PacketServiceAdapter;
-import org.onosproject.net.provider.ProviderId;
-import org.onosproject.net.proxyarp.ProxyArpStore;
-import org.onosproject.net.proxyarp.ProxyArpStoreDelegate;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.Matchers.anyOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests for the {@link ProxyArpManager} class.
- */
-public class ProxyArpManagerTest {
-
-    private static final int NUM_DEVICES = 10;
-    private static final int NUM_PORTS_PER_DEVICE = 3;
-    private static final int LAST_CONF_DEVICE_INTF_VLAN_IP = 3;
-    private static final int LAST_CONF_DEVICE_INTF_VLAN = 6;
-
-    private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
-    private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
-    private static final Ip6Address IP3 = Ip6Address.valueOf("1000:ffff::1");
-    private static final Ip6Address IP4 = Ip6Address.valueOf("1000:ffff::2");
-
-    private static final ProviderId PID = new ProviderId("of", "foo");
-
-    private static final VlanId VLAN1 = VlanId.vlanId((short) 1);
-    private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
-    private static final VlanId VLAN10 = VlanId.vlanId((short) 10);
-
-    private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01");
-    private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02");
-    private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03");
-    private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04");
-    private static final MacAddress MAC10 = MacAddress.valueOf("00:00:00:00:00:0A");
-
-    private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01");
-
-    private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
-    private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
-    private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
-    private static final HostId HID4 = HostId.hostId(MAC4, VLAN1);
-    private static final HostId HID10 = HostId.hostId(MAC10, VLAN10);
-
-    private static final HostId SOLICITED_HID3 = HostId.hostId(SOLICITED_MAC3, VLAN1);
-
-    private static final DeviceId DID1 = getDeviceId(1);
-    private static final DeviceId DID2 = getDeviceId(2);
-
-    private static final PortNumber P1 = PortNumber.portNumber(1);
-
-    private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
-    private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L);
-
-    private final byte[] zeroMacAddress = MacAddress.ZERO.toBytes();
-
-    // The first three devices in the topology have interfaces configured
-    // with VLANs and IPs
-    private final List<ConnectPoint> configIpCPoints = new ArrayList<>();
-
-    // Other three devices in the topology (from 4 to 6) have interfaces
-    // configured only with VLANs
-    private final List<ConnectPoint> configVlanCPoints = new ArrayList<>();
-
-    // Remaining devices in the network (id > 6) don't have any interface
-    // configured.
-    private final List<ConnectPoint> noConfigCPoints = new ArrayList<>();
-
-    private ProxyArpManager proxyArp;
-
-    private TestPacketService packetService;
-    private DeviceService deviceService;
-    private EdgePortService edgePortService;
-    private LinkService linkService;
-    private HostService hostService;
-    private InterfaceService interfaceService;
-
-    @Before
-    public void setUp() throws Exception {
-        proxyArp = new ProxyArpManager();
-        packetService = new TestPacketService();
-        proxyArp.packetService = packetService;
-        proxyArp.store = new TestProxyArpStoreAdapter();
-
-        // Create a host service mock here.
-        hostService = createMock(HostService.class);
-        proxyArp.hostService = hostService;
-
-        // Create an edge port service.
-        edgePortService = createMock(EdgePortService.class);
-        proxyArp.edgeService = edgePortService;
-
-        // Create interface service
-        interfaceService = createMock(InterfaceService.class);
-        proxyArp.interfaceService = interfaceService;
-
-        // Create the topology
-        createTopology();
-        proxyArp.deviceService = deviceService;
-        proxyArp.linkService = linkService;
-
-        setupNoConfigCPoints();
-        setupconfigIpCPoints();
-        setupconfigVlanCPoints();
-
-        proxyArp.activate();
-    }
-
-    /**
-     * Creates a fake topology to feed into the ARP module.
-     * <p>
-     * The default topology is a unidirectional ring topology. Each switch has
-     * 3 ports. Ports 2 and 3 have the links to neighbor switches, and port 1
-     * is free (edge port).
-     * The first half of the switches have IP addresses configured on their
-     * free ports (port 1). The second half of the switches have no IP
-     * addresses configured.
-     */
-    private void createTopology() {
-        deviceService = createMock(DeviceService.class);
-        linkService = createMock(LinkService.class);
-
-        deviceService.addListener(anyObject(DeviceListener.class));
-        linkService.addListener(anyObject(LinkListener.class));
-
-        createDevices(NUM_DEVICES, NUM_PORTS_PER_DEVICE);
-        createLinks(NUM_DEVICES);
-        addIntfConfig();
-        popluateEdgePortService();
-    }
-
-    /**
-     * Creates the devices for the fake topology.
-     */
-    private void createDevices(int numDevices, int numPorts) {
-        List<Device> devices = new ArrayList<>();
-
-        for (int i = 1; i <= numDevices; i++) {
-            DeviceId devId = getDeviceId(i);
-            Device device = createMock(Device.class);
-            expect(device.id()).andReturn(devId).anyTimes();
-            replay(device);
-
-            devices.add(device);
-
-            List<Port> ports = new ArrayList<>();
-            for (int j = 1; j <= numPorts; j++) {
-                Port port = createMock(Port.class);
-                expect(port.number()).andReturn(PortNumber.portNumber(j)).anyTimes();
-                replay(port);
-                ports.add(port);
-            }
-
-            expect(deviceService.getPorts(devId)).andReturn(ports).anyTimes();
-            expect(deviceService.getDevice(devId)).andReturn(device).anyTimes();
-        }
-
-        expect(deviceService.getDevices()).andReturn(devices).anyTimes();
-        replay(deviceService);
-    }
-
-    /**
-     * Creates the links for the fake topology.
-     * NB: Only unidirectional links are created, as for this purpose all we
-     * need is to occupy the ports with some link.
-     */
-    private void createLinks(int numDevices) {
-        List<Link> links = new ArrayList<>();
-
-        for (int i = 1; i <= numDevices; i++) {
-            ConnectPoint src = new ConnectPoint(
-                    getDeviceId(i),
-                    PortNumber.portNumber(2));
-            ConnectPoint dst = new ConnectPoint(
-                    getDeviceId((i + 1 > numDevices) ? 1 : i + 1),
-                    PortNumber.portNumber(3));
-
-            Link link = createMock(Link.class);
-            expect(link.src()).andReturn(src).anyTimes();
-            expect(link.dst()).andReturn(dst).anyTimes();
-            replay(link);
-
-            links.add(link);
-        }
-
-        expect(linkService.getLinks()).andReturn(links).anyTimes();
-        replay(linkService);
-    }
-
-    /**
-     * On the first three devices two config interfaces are binded on port 1.
-     * The first one with VLAN1, the second one with VLAN equals to none.
-     * Both interfaces have an IP.
-     * On devices 4, 5 and 6 it's binded a config interface on port 1.
-     * The interface is configured with VLAN 1 and no IP.
-     */
-    private void addIntfConfig() {
-        Set<Interface> interfaces = Sets.newHashSet();
-
-        Set<Interface> vlanOneSet = new HashSet<>();
-
-        for (int i = 1; i <= LAST_CONF_DEVICE_INTF_VLAN_IP; i++) {
-            ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
-
-            // Interface addresses for IPv4
-            Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
-            Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
-            Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24");
-            Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1");
-            InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1);
-            InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
-
-            // Interface addresses for IPv6
-            Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64");
-            Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1");
-            Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64");
-            Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::2");
-            InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3);
-            InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4);
-
-            // Setting up interfaces
-            Interface intf1 = new Interface(Interface.NO_INTERFACE_NAME, cp,
-                    Lists.newArrayList(ia1, ia3), MacAddress.valueOf(2 * i - 1), VlanId.vlanId((short) 1));
-            Interface intf2 = new Interface(Interface.NO_INTERFACE_NAME, cp,
-                    Lists.newArrayList(ia2, ia4), MacAddress.valueOf(2 * i), VlanId.NONE);
-
-            interfaces.add(intf1);
-            interfaces.add(intf2);
-
-            vlanOneSet.add(intf1);
-
-            expect(interfaceService.getInterfacesByPort(cp))
-                    .andReturn(Sets.newHashSet(intf1, intf2)).anyTimes();
-        }
-        for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) {
-            ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
-            Interface intf1 = new Interface(Interface.NO_INTERFACE_NAME, cp, Collections.emptyList(),
-                    MacAddress.NONE,
-                    VlanId.vlanId((short) 1));
-
-            interfaces.add(intf1);
-            vlanOneSet.add(intf1);
-
-            expect(interfaceService.getInterfacesByPort(cp))
-                    .andReturn(Sets.newHashSet(intf1)).anyTimes();
-        }
-        expect(interfaceService.getInterfacesByVlan(VLAN1))
-                .andReturn(vlanOneSet).anyTimes();
-        expect(interfaceService.getInterfacesByVlan(VLAN10))
-                .andReturn(Collections.emptySet()).anyTimes();
-        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
-
-        for (int i = LAST_CONF_DEVICE_INTF_VLAN + 1; i <= NUM_DEVICES; i++) {
-            ConnectPoint cp = new ConnectPoint(getDeviceId(i),
-                    P1);
-            expect(interfaceService.getInterfacesByPort(cp))
-                    .andReturn(Collections.emptySet()).anyTimes();
-        }
-    }
-
-    /**
-     * Populates edge ports in the EdgePortService to return all port 1
-     * as edge ports.
-     */
-    private void popluateEdgePortService() {
-        Set<ConnectPoint> edgeConnectPoints = new HashSet<>();
-
-        for (int i = 1; i <= NUM_DEVICES; i++) {
-            for (int j = 1; j <= NUM_PORTS_PER_DEVICE; j++) {
-                ConnectPoint edgeConnectPoint = new ConnectPoint(
-                        getDeviceId(i),
-                        PortNumber.portNumber(1));
-                ConnectPoint noEdgeConnectPointOne = new ConnectPoint(
-                        getDeviceId(i),
-                        PortNumber.portNumber(2));
-                ConnectPoint noEdgeConnectPointTwo = new ConnectPoint(
-                        getDeviceId(i),
-                        PortNumber.portNumber(3));
-
-                edgeConnectPoints.add(edgeConnectPoint);
-
-                expect(edgePortService.isEdgePoint(edgeConnectPoint))
-                        .andReturn(true).anyTimes();
-                expect(edgePortService.isEdgePoint(noEdgeConnectPointOne))
-                        .andReturn(false).anyTimes();
-                expect(edgePortService.isEdgePoint(noEdgeConnectPointTwo))
-                        .andReturn(false).anyTimes();
-            }
-        }
-        expect(edgePortService.getEdgePoints())
-                .andReturn(edgeConnectPoints).anyTimes();
-
-        replay(edgePortService);
-    }
-
-    /**
-     * Creates a list of connect points used to verify floodling on ports
-     * with no interfaces configured (all ports without interface config).
-     */
-    private void setupNoConfigCPoints() {
-        for (int i = NUM_DEVICES / 2 + 2; i <= NUM_DEVICES; i++) {
-            ConnectPoint connectPoint = new ConnectPoint(
-                    getDeviceId(i),
-                    PortNumber.portNumber(1));
-            noConfigCPoints.add(connectPoint);
-        }
-    }
-
-    /**
-     * Creates a list of connect points used to verify floodling on ports
-     * with interfaces configured (both VLAN and IP).
-     */
-    private void setupconfigIpCPoints() {
-        for (int i = 1; i <= 3; i++) {
-            ConnectPoint connectPoint = new ConnectPoint(
-                    getDeviceId(i),
-                    PortNumber.portNumber(1));
-            configIpCPoints.add(connectPoint);
-        }
-    }
-
-    /**
-     * Creates a list of connect points used to verify floodling on ports
-     * with interfaces configured (both VLAN and IP).
-     */
-    private void setupconfigVlanCPoints() {
-        for (int i = LAST_CONF_DEVICE_INTF_VLAN_IP + 1; i <= LAST_CONF_DEVICE_INTF_VLAN; i++) {
-            ConnectPoint connectPoint = new ConnectPoint(
-                    getDeviceId(i),
-                    PortNumber.portNumber(1));
-            configVlanCPoints.add(connectPoint);
-        }
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the
-     * case where the IP address is not known.
-     * Verifies the method returns false.
-     */
-    @Test
-    public void testNotKnown() {
-        expect(hostService.getHostsByIp(IP1)).andReturn(Collections.emptySet());
-        replay(hostService);
-        replay(interfaceService);
-
-        assertFalse(proxyArp.isKnown(IP1));
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the
-     * case where the IP address is known.
-     * Verifies the method returns true.
-     */
-    @Test
-    public void testKnown() {
-        Host host1 = createMock(Host.class);
-        Host host2 = createMock(Host.class);
-
-        expect(hostService.getHostsByIp(IP1))
-                .andReturn(Sets.newHashSet(host1, host2));
-        replay(hostService);
-        replay(interfaceService);
-
-        assertTrue(proxyArp.isKnown(IP1));
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * destination host is known.
-     * Two host using the same VLAN are registered on the host service on devices 5 and 6.
-     * Host on port 6 asks for the MAC of the device on port 5.
-     * Since the destination mac address is known, the request is not flooded to anywhere
-     * and ONOS directly builds an ARP reply, sended back to the requester on device 6.
-     * It's verified that a proper ARP reply is received on port 1 of device 6.
-     */
-    @Test
-    public void testReplyKnown() {
-        Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES),
-                Collections.singleton(IP1));
-
-        Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(NUM_DEVICES - 1),
-                Collections.singleton(IP2));
-
-        expect(hostService.getHostsByIp(IP2))
-                .andReturn(Collections.singleton(replyer));
-        expect(hostService.getHost(HID1)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
-
-        proxyArp.reply(arpRequest, getLocation(NUM_DEVICES));
-
-        assertEquals(1, packetService.packets.size());
-        Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1);
-        verifyPacketOut(arpReply, getLocation(NUM_DEVICES), packetService.packets.get(0));
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * destination host is known.
-     * Verifies the correct NDP reply is sent out the correct port.
-     */
-    @Test
-    public void testReplyKnownIpv6() {
-        Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4),
-                                       Collections.singleton(IP3));
-
-        Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
-                                         Collections.singleton(IP4));
-
-        expect(hostService.getHostsByIp(IP3))
-                .andReturn(Collections.singleton(replyer));
-        expect(hostService.getHost(HID4)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC4, SOLICITED_MAC3,
-                IP4, IP3);
-
-        proxyArp.reply(ndpRequest, getLocation(5));
-
-        assertEquals(1, packetService.packets.size());
-        Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
-                MAC3, MAC4, IP3, IP4);
-        verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0));
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * destination host is not known.
-     * Only a requestor is present (on device 6, port 1). The device has a VLAN configured
-     * which is not configured anywhere in the system.
-     * Since the destination is not known, and since the ARP request can't be sent out of
-     * interfaces configured, the ARP request is flooded out of ports 4 and 5.
-     * Verifies the ARP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testReplyUnknown() {
-        Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES),
-                Collections.singleton(IP1));
-
-        expect(hostService.getHostsByIp(IP2))
-                .andReturn(Collections.emptySet());
-        expect(interfaceService.getInterfacesByIp(IP1))
-                .andReturn(Collections.emptySet());
-        expect(hostService.getHost(HID10)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2);
-
-        proxyArp.reply(arpRequest, getLocation(NUM_DEVICES));
-
-        verifyFlood(arpRequest, noConfigCPoints);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * destination host is not known.
-     * Verifies the NDP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testReplyUnknownIpv6() {
-        Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES),
-                                         Collections.singleton(IP4));
-
-        expect(hostService.getHostsByIp(IP3))
-                .andReturn(Collections.emptySet());
-        expect(interfaceService.getInterfacesByIp(IP4))
-                .andReturn(Collections.emptySet());
-        expect(hostService.getHost(HID4)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC4, SOLICITED_MAC3,
-                IP4, IP3);
-
-        proxyArp.reply(ndpRequest, getLocation(NUM_DEVICES));
-
-        verifyFlood(ndpRequest, noConfigCPoints);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * destination host is known for that IP address, but is not on the same
-     * VLAN as the source host.
-     * An host is connected on device 6, port 1 where no interfaces are defined. It sends
-     * ARP requests from VLAN10, not configured anywhere in the network. Another host with
-     * the IP address requested lives on device 5, port 1 in the network. Anyway, since the
-     * host uses another VLAN it's not found and the ARP packet is flooded out of port
-     * 4 and 5.
-     *
-     * Verifies the ARP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testReplyDifferentVlan() {
-        Host requestor = new DefaultHost(PID, HID10, MAC10, VLAN10, getLocation(NUM_DEVICES),
-                Collections.singleton(IP1));
-
-        Host replyer = new DefaultHost(PID, HID2, MAC2, VLAN2, getLocation(NUM_DEVICES - 1),
-                Collections.singleton(IP2));
-
-        expect(hostService.getHostsByIp(IP2))
-                .andReturn(Collections.singleton(replyer));
-        expect(interfaceService.getInterfacesByIp(IP1))
-                .andReturn(Collections.emptySet());
-        expect(hostService.getHost(HID10)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN10, MAC10, null, IP1, IP2);
-
-        proxyArp.reply(arpRequest, getLocation(NUM_DEVICES));
-
-        verifyFlood(arpRequest, noConfigCPoints);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * a vlan packet comes in from a port without interfaces configured. The destination
-     * host is unknown for that IP address and there are some interfaces configured on
-     * the same vlan.
-     * It's expected to see the ARP request going out through ports with no interfaces
-     * configured, devices 4 and 5, port 1.
-     *
-     * Verifies the ARP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testConfiguredVlan() {
-        Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(NUM_DEVICES),
-                Collections.singleton(IP1));
-
-        expect(hostService.getHostsByIp(IP2))
-                .andReturn(Collections.emptySet());
-        expect(interfaceService.getInterfacesByIp(IP1))
-                .andReturn(Collections.emptySet());
-        expect(hostService.getHost(HID1)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
-
-        proxyArp.reply(arpRequest, getLocation(NUM_DEVICES));
-
-        verifyFlood(arpRequest, noConfigCPoints);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * a vlan packet comes in from a port without interfaces configured. The destination
-     * host is not known for that IP address and there are some interfaces configured on
-     * the same vlan.
-     * It's expected to see the ARP request going out through ports with no interfaces
-     * configured, devices 4 and 5, port 1.
-     *
-     * Verifies the ARP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testConfiguredVlanOnInterfaces() {
-        Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(6),
-                Collections.singleton(IP1));
-
-        expect(hostService.getHostsByIp(IP2))
-                .andReturn(Collections.emptySet());
-        expect(interfaceService.getInterfacesByIp(IP1))
-                .andReturn(Collections.emptySet());
-        expect(hostService.getHost(HID1)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, IP1, IP2);
-
-        proxyArp.reply(arpRequest, getLocation(6));
-
-        verifyFlood(arpRequest, configVlanCPoints);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
-     * destination host is known for that IP address, but is not on the same
-     * VLAN as the source host.
-     * Verifies the NDP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testReplyDifferentVlanIpv6() {
-        Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(NUM_DEVICES),
-                                         Collections.singleton(IP4));
-
-        Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(NUM_DEVICES - 1),
-                Collections.singleton(IP3));
-
-        expect(hostService.getHostsByIp(IP3))
-                .andReturn(Collections.singleton(replyer));
-        expect(interfaceService.getInterfacesByIp(IP4))
-                .andReturn(Collections.emptySet());
-        expect(hostService.getHost(HID4)).andReturn(requestor);
-
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC4, SOLICITED_MAC3,
-                IP4, IP3);
-
-        proxyArp.reply(ndpRequest, getLocation(NUM_DEVICES));
-
-        verifyFlood(ndpRequest, noConfigCPoints);
-    }
-
-    /**
-     * Test ARP request from external network to an internal host.
-     */
-    @Test
-    public void testReplyToRequestForUs() {
-        Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
-        Ip4Address ourFirstIp = Ip4Address.valueOf("10.0.1.1");
-        Ip4Address ourSecondIp = Ip4Address.valueOf("10.0.2.1");
-        MacAddress firstMac = MacAddress.valueOf(1L);
-        MacAddress secondMac = MacAddress.valueOf(2L);
-
-        Host requestor = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1,
-                Collections.singleton(theirIp));
-
-        expect(hostService.getHost(HID1)).andReturn(requestor);
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourFirstIp);
-
-        proxyArp.reply(arpRequest, LOC1);
-
-        assertEquals(1, packetService.packets.size());
-        Ethernet arpReply = buildArp(ARP.OP_REPLY, VLAN1, firstMac, MAC1, ourFirstIp, theirIp);
-        verifyPacketOut(arpReply, LOC1, packetService.packets.get(0));
-
-        // Test a request for the second address on that port
-        packetService.packets.clear();
-        arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, ourSecondIp);
-
-        proxyArp.reply(arpRequest, LOC1);
-
-        assertEquals(1, packetService.packets.size());
-        arpReply = buildArp(ARP.OP_REPLY, VLAN1, secondMac, MAC1, ourSecondIp, theirIp);
-        verifyPacketOut(arpReply, LOC1, packetService.packets.get(0));
-    }
-
-    /**
-     * Test NDP request from external network to an internal host.
-     */
-    @Test
-    public void testReplyToRequestForUsIpv6() {
-        Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
-        Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1");
-        Ip6Address ourSecondIp = Ip6Address.valueOf("2000::2");
-        MacAddress firstMac = MacAddress.valueOf(1L);
-        MacAddress secondMac = MacAddress.valueOf(2L);
-
-        Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1,
-                                         Collections.singleton(theirIp));
-
-        expect(hostService.getHost(HID2)).andReturn(requestor);
-        expect(hostService.getHostsByIp(ourFirstIp))
-                .andReturn(Collections.singleton(requestor));
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC2,
-                MacAddress.valueOf("33:33:ff:00:00:01"),
-                theirIp,
-                ourFirstIp);
-
-        proxyArp.reply(ndpRequest, LOC1);
-        assertEquals(1, packetService.packets.size());
-
-        Ethernet ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
-                firstMac,
-                MAC2,
-                ourFirstIp,
-                theirIp);
-        verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
-
-        // Test a request for the second address on that port
-        packetService.packets.clear();
-        ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC2,
-                MacAddress.valueOf("33:33:ff:00:00:01"),
-                theirIp,
-                ourSecondIp);
-        proxyArp.reply(ndpRequest, LOC1);
-        assertEquals(1, packetService.packets.size());
-
-        ndpReply = buildNdp(ICMP6.NEIGHBOR_ADVERTISEMENT,
-                secondMac,
-                MAC2,
-                ourSecondIp,
-                theirIp);
-        verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
-    }
-
-    /**
-     * Request for a valid external IPv4 address but coming in the wrong port.
-     */
-    @Test
-    public void testReplyExternalPortBadRequest() {
-        replay(hostService); // no further host service expectations
-        replay(interfaceService);
-
-        Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
-
-        // Request for a valid external IP address but coming in the wrong port
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp,
-                Ip4Address.valueOf("10.0.3.1"));
-        proxyArp.reply(arpRequest, LOC1);
-        assertEquals(0, packetService.packets.size());
-
-        // Request for a valid internal IP address but coming in an external port
-        packetService.packets.clear();
-        arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, MAC1, null, theirIp, IP1);
-        proxyArp.reply(arpRequest, LOC1);
-        assertEquals(0, packetService.packets.size());
-    }
-
-    /**
-     * Request for a valid external IPv6 address but coming in the wrong port.
-     */
-    @Test
-    public void testReplyExternalPortBadRequestIpv6() {
-        replay(hostService); // no further host service expectations
-        replay(interfaceService);
-
-        Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
-
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC1,
-                MacAddress.valueOf("33:33:ff:00:00:01"),
-                theirIp,
-                Ip6Address.valueOf("3000::1"));
-        proxyArp.reply(ndpRequest, LOC1);
-        assertEquals(0, packetService.packets.size());
-
-        // Request for a valid internal IP address but coming in an external port
-        packetService.packets.clear();
-        ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC1,
-                MacAddress.valueOf("33:33:ff:00:00:01"),
-                theirIp,
-                IP3);
-        proxyArp.reply(ndpRequest, LOC1);
-        assertEquals(0, packetService.packets.size());
-    }
-
-    /**
-     * Test ARP request from internal network to an external host.
-     */
-    @Test
-    public void testReplyToRequestFromUs() {
-        Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
-        MacAddress ourMac = MacAddress.valueOf(1L);
-        Ip4Address theirIp = Ip4Address.valueOf("10.0.1.100");
-
-        expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
-        expect(interfaceService.getInterfacesByIp(ourIp))
-                .andReturn(Collections.singleton(new Interface(Interface.NO_INTERFACE_NAME, getLocation(1),
-                        Collections.singletonList(new InterfaceIpAddress(ourIp, IpPrefix.valueOf("10.0.1.1/24"))),
-                        ourMac, VLAN1)));
-        expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
-        replay(hostService);
-        replay(interfaceService);
-
-        // This is a request from something inside our network (like a BGP
-        // daemon) to an external host.
-        Ethernet arpRequest = buildArp(ARP.OP_REQUEST, VLAN1, ourMac, null, ourIp, theirIp);
-        //Ensure the packet is allowed through (it is not to an internal port)
-
-        proxyArp.reply(arpRequest, getLocation(5));
-        assertEquals(1, packetService.packets.size());
-        verifyPacketOut(arpRequest, getLocation(1), packetService.packets.get(0));
-
-        // The same request from a random external port should fail
-        packetService.packets.clear();
-        proxyArp.reply(arpRequest, getLocation(2));
-        assertEquals(0, packetService.packets.size());
-    }
-
-    /**
-     * Test NDP request from internal network to an external host.
-     */
-    @Test
-    public void testReplyToRequestFromUsIpv6() {
-        Ip6Address ourIp = Ip6Address.valueOf("1000::1");
-        MacAddress ourMac = MacAddress.valueOf(1L);
-        Ip6Address theirIp = Ip6Address.valueOf("1000::100");
-
-        expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
-        expect(interfaceService.getInterfacesByIp(ourIp))
-                .andReturn(Collections.singleton(new Interface(Interface.NO_INTERFACE_NAME, getLocation(1),
-                        Collections.singletonList(new InterfaceIpAddress(
-                                ourIp,
-                                IpPrefix.valueOf("1000::1/64"))),
-                                ourMac,
-                                VLAN1)));
-        expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
-        replay(hostService);
-        replay(interfaceService);
-
-        // This is a request from something inside our network (like a BGP
-        // daemon) to an external host.
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                ourMac,
-                MacAddress.valueOf("33:33:ff:00:00:01"),
-                ourIp,
-                theirIp);
-
-        proxyArp.reply(ndpRequest, getLocation(5));
-        assertEquals(1, packetService.packets.size());
-        verifyPacketOut(ndpRequest, getLocation(1), packetService.packets.get(0));
-
-        // The same request from a random external port should fail
-        packetService.packets.clear();
-        proxyArp.reply(ndpRequest, getLocation(2));
-        assertEquals(0, packetService.packets.size());
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
-     * destination host is known.
-     * Verifies the correct ARP request is sent out the correct port.
-     */
-    @Test
-    public void testForwardToHost() {
-        Host host1 = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC1,
-                Collections.singleton(IP1));
-        Host host2 = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC2,
-                                     Collections.singleton(IP2));
-
-        expect(hostService.getHost(HID1)).andReturn(host1);
-        expect(hostService.getHost(HID2)).andReturn(host2);
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REPLY, VLAN1, MAC2, MAC1, IP2, IP1);
-
-        proxyArp.forward(arpRequest, LOC2);
-
-        assertEquals(1, packetService.packets.size());
-        OutboundPacket packet = packetService.packets.get(0);
-
-        verifyPacketOut(arpRequest, LOC1, packet);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
-     * destination host is known.
-     * Verifies the correct ARP request is sent out the correct port.
-     */
-    @Test
-    public void testForwardToHostIpv6() {
-        Host host1 = new DefaultHost(PID, HID3, MAC3, VLAN1, LOC1,
-                                     Collections.singleton(IP3));
-        Host host2 = new DefaultHost(PID, HID4, MAC4, VLAN1, LOC2,
-                                     Collections.singleton(IP4));
-
-        expect(hostService.getHost(SOLICITED_HID3)).andReturn(host1);
-        expect(hostService.getHost(HID4)).andReturn(host2);
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC4, SOLICITED_MAC3,
-                IP4, IP3);
-
-        proxyArp.forward(ndpRequest, LOC2);
-
-        assertEquals(1, packetService.packets.size());
-        OutboundPacket packet = packetService.packets.get(0);
-
-        verifyPacketOut(ndpRequest, LOC1, packet);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
-     * destination host is not known.
-     * Verifies the correct ARP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testForwardFlood() {
-        expect(hostService.getHost(HID2)).andReturn(null);
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet arpRequest = buildArp(ARP.OP_REPLY, VLAN1, MAC1, MAC2, IP1, IP2);
-
-        proxyArp.forward(arpRequest, getLocation(NUM_DEVICES));
-
-        verifyFlood(arpRequest, noConfigCPoints);
-    }
-
-    /**
-     * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
-     * destination host is not known.
-     * Verifies the correct NDP request is flooded out the correct edge ports.
-     */
-    @Test
-    public void testForwardFloodIpv6() {
-        expect(hostService.getHost(SOLICITED_HID3)).andReturn(null);
-        replay(hostService);
-        replay(interfaceService);
-
-        Ethernet ndpRequest = buildNdp(ICMP6.NEIGHBOR_SOLICITATION,
-                MAC4, SOLICITED_MAC3,
-                IP4, IP3);
-
-        proxyArp.forward(ndpRequest, getLocation(NUM_DEVICES));
-
-        verifyFlood(ndpRequest, noConfigCPoints);
-    }
-
-    /**
-     * Verifies that the given packet was flooded out all available edge ports,
-     * except for the input port.
-     *
-     * @param packet the packet that was expected to be flooded
-     * @param connectPoints the connectPoints where the outpacket should be
-     *                      observed
-     */
-    private void verifyFlood(Ethernet packet, List<ConnectPoint> connectPoints) {
-
-        // There should be 1 less than NUM_FLOOD_PORTS; the inPort should be excluded.
-        assertEquals(connectPoints.size() - 1, packetService.packets.size());
-
-        Collections.sort(packetService.packets,
-                (o1, o2) -> o1.sendThrough().uri().compareTo(o2.sendThrough().uri()));
-
-        for (int i = 0; i < connectPoints.size() - 1; i++) {
-            OutboundPacket outboundPacket = packetService.packets.get(i);
-            verifyPacketOut(packet, connectPoints.get(i), outboundPacket);
-        }
-    }
-
-    /**
-     * Verifies the given packet was sent out the given port.
-     *
-     * @param expected the packet that was expected to be sent
-     * @param outPort  the port the packet was expected to be sent out
-     * @param actual   the actual OutboundPacket to verify
-     */
-    private void verifyPacketOut(Ethernet expected, ConnectPoint outPort,
-                                 OutboundPacket actual) {
-        assertArrayEquals(expected.serialize(), actual.data().array());
-        assertEquals(1, actual.treatment().immediate().size());
-        assertEquals(outPort.deviceId(), actual.sendThrough());
-        Instruction instruction = actual.treatment().immediate().get(0);
-        assertTrue(instruction instanceof OutputInstruction);
-        assertEquals(outPort.port(), ((OutputInstruction) instruction).port());
-    }
-
-    /**
-     * Returns the device ID of the ith device.
-     *
-     * @param i device to get the ID of
-     * @return the device ID
-     */
-    private static DeviceId getDeviceId(int i) {
-        return DeviceId.deviceId("" + i);
-    }
-
-    private static HostLocation getLocation(int i) {
-        return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
-    }
-
-    /**
-     * Builds an ARP packet with the given parameters.
-     *
-     * @param opcode opcode of the ARP packet
-     * @param srcMac source MAC address
-     * @param dstMac destination MAC address, or null if this is a request
-     * @param srcIp  source IP address
-     * @param dstIp  destination IP address
-     * @return the ARP packet
-     */
-    private Ethernet buildArp(short opcode, VlanId vlanId, MacAddress srcMac,
-                              MacAddress dstMac, Ip4Address srcIp, Ip4Address dstIp) {
-        Ethernet eth = new Ethernet();
-
-        if (dstMac == null) {
-            eth.setDestinationMACAddress(MacAddress.BROADCAST);
-        } else {
-            eth.setDestinationMACAddress(dstMac);
-        }
-
-        eth.setSourceMACAddress(srcMac);
-        eth.setEtherType(Ethernet.TYPE_ARP);
-        eth.setVlanID(vlanId.toShort());
-
-        ARP arp = new ARP();
-        arp.setOpCode(opcode);
-        arp.setProtocolType(ARP.PROTO_TYPE_IP);
-        arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
-
-        arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
-        arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
-        arp.setSenderHardwareAddress(srcMac.toBytes());
-
-        if (dstMac == null) {
-            arp.setTargetHardwareAddress(zeroMacAddress);
-        } else {
-            arp.setTargetHardwareAddress(dstMac.toBytes());
-        }
-
-        arp.setSenderProtocolAddress(srcIp.toOctets());
-        arp.setTargetProtocolAddress(dstIp.toOctets());
-
-        eth.setPayload(arp);
-        return eth;
-    }
-
-    /**
-     * Builds an NDP packet with the given parameters.
-     *
-     * @param type NeighborSolicitation or NeighborAdvertisement
-     * @param srcMac source MAC address
-     * @param dstMac destination MAC address, or null if this is a request
-     * @param srcIp  source IP address
-     * @param dstIp  destination IP address
-     * @return the NDP packet
-     */
-    private Ethernet buildNdp(byte type, MacAddress srcMac, MacAddress dstMac,
-                              Ip6Address srcIp, Ip6Address dstIp) {
-        assertThat(type, anyOf(
-                is(ICMP6.NEIGHBOR_SOLICITATION),
-                is(ICMP6.NEIGHBOR_ADVERTISEMENT)
-        ));
-        assertNotNull(srcMac);
-        assertNotNull(dstMac);
-        assertNotNull(srcIp);
-        assertNotNull(dstIp);
-
-        IPacket ndp;
-        if (type == ICMP6.NEIGHBOR_SOLICITATION) {
-            ndp = new NeighborSolicitation().setTargetAddress(dstIp.toOctets());
-        } else {
-            ndp = new NeighborAdvertisement()
-                    .setSolicitedFlag((byte) 1)
-                    .setOverrideFlag((byte) 1)
-                    .setTargetAddress(srcIp.toOctets())
-                    .addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
-                       srcMac.toBytes());
-        }
-
-        ICMP6 icmp6 = new ICMP6();
-        icmp6.setIcmpType(type);
-        icmp6.setIcmpCode((byte) 0);
-        icmp6.setPayload(ndp);
-
-        IPv6 ipv6 = new IPv6();
-        ipv6.setDestinationAddress(dstIp.toOctets());
-        ipv6.setSourceAddress(srcIp.toOctets());
-        ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6);
-        ipv6.setHopLimit((byte) 255);
-        ipv6.setPayload(icmp6);
-
-        Ethernet eth = new Ethernet();
-        eth.setDestinationMACAddress(dstMac);
-        eth.setSourceMACAddress(srcMac);
-        eth.setEtherType(Ethernet.TYPE_IPV6);
-        eth.setVlanID(VLAN1.toShort());
-        eth.setPayload(ipv6);
-
-        return eth;
-    }
-
-    /**
-     * Test PacketService implementation that simply stores OutboundPackets
-     * passed to {@link #emit(OutboundPacket)} for later verification.
-     */
-    class TestPacketService extends PacketServiceAdapter {
-
-        List<OutboundPacket> packets = new ArrayList<>();
-
-        @Override
-        public void emit(OutboundPacket packet) {
-            packets.add(packet);
-        }
-
-    }
-
-    private class TestProxyArpStoreAdapter implements ProxyArpStore {
-        @Override
-        public void forward(ConnectPoint outPort, Host subject, ByteBuffer packet) {
-            TrafficTreatment tt = DefaultTrafficTreatment.builder().setOutput(outPort.port()).build();
-            packetService.emit(new DefaultOutboundPacket(outPort.deviceId(), tt, packet));
-        }
-
-        @Override
-        public void setDelegate(ProxyArpStoreDelegate delegate) {
-        }
-    }
-}
diff --git a/core/security/src/main/java/org/onosproject/security/impl/DefaultPolicyBuilder.java b/core/security/src/main/java/org/onosproject/security/impl/DefaultPolicyBuilder.java
index 92b4eec..8327b56 100644
--- a/core/security/src/main/java/org/onosproject/security/impl/DefaultPolicyBuilder.java
+++ b/core/security/src/main/java/org/onosproject/security/impl/DefaultPolicyBuilder.java
@@ -63,7 +63,6 @@
 import org.onosproject.net.link.LinkAdminService;
 import org.onosproject.net.link.LinkService;
 import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.proxyarp.ProxyArpService;
 import org.onosproject.net.statistic.StatisticService;
 import org.onosproject.net.topology.PathService;
 import org.onosproject.net.topology.TopologyService;
@@ -234,7 +233,6 @@
 //        permSet.add(new ServicePermission(MeterService.class.getName(), ServicePermission.GET));
         permSet.add(new ServicePermission(ResourceService.class.getName(), ServicePermission.GET));
         permSet.add(new ServicePermission(PacketService.class.getName(), ServicePermission.GET));
-        permSet.add(new ServicePermission(ProxyArpService.class.getName(), ServicePermission.GET));
         permSet.add(new ServicePermission(RegionService.class.getName(), ServicePermission.GET));
 //      permSet.add(new ServicePermission(LinkResourceService.class.getName(), ServicePermission.GET));
         permSet.add(new ServicePermission(FlowStatisticService.class.getName(), ServicePermission.GET));
@@ -328,11 +326,6 @@
 //        serviceDirectory.put(LINK_EVENT, ImmutableSet.of(
 //                LinkService.class.getName(), LinkResourceService.class.getName(),
 //                LabelResourceService.class.getName()));
-        serviceDirectory.put(PACKET_READ, ImmutableSet.of(
-                PacketService.class.getName(), ProxyArpService.class.getName()));
-        serviceDirectory.put(PACKET_WRITE, ImmutableSet.of(
-                PacketService.class.getName(), ProxyArpService.class.getName(),
-                EdgePortService.class.getName()));
         serviceDirectory.put(PACKET_EVENT, ImmutableSet.of(
                 PacketService.class.getName()));
         serviceDirectory.put(STATISTIC_READ, ImmutableSet.of(
diff --git a/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java b/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java
deleted file mode 100644
index 00768dc..0000000
--- a/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/DistributedProxyArpStore.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2015-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.store.proxyarp.impl;
-
-import com.google.common.collect.Maps;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.ClusterService;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.net.proxyarp.ProxyArpStore;
-import org.onosproject.net.proxyarp.ProxyArpStoreDelegate;
-import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
-import org.onosproject.store.cluster.messaging.MessageSubject;
-import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.serializers.StoreSerializer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-
-import static org.onlab.util.BoundedThreadPool.newFixedThreadPool;
-import static org.onlab.util.Tools.groupedThreads;
-
-/**
- * Implementation of proxy ARP distribution mechanism.
- *
- * @deprecated in Hummingbird release. This is no longer necessary as there are
- * other solutions for the problem this was solving.
- */
-@Deprecated
-@Component(immediate = true)
-@Service
-public class DistributedProxyArpStore implements ProxyArpStore {
-
-    private Logger log = LoggerFactory.getLogger(getClass());
-
-    private static final MessageSubject ARP_RESPONSE_MESSAGE =
-            new MessageSubject("onos-arp-response");
-
-    protected final StoreSerializer serializer = StoreSerializer.using(
-            KryoNamespace.newBuilder()
-                    .register(KryoNamespaces.API)
-                    .nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
-                    .register(ArpResponseMessage.class)
-                    .register(ByteBuffer.class)
-                    .build("ProxyArpStore"));
-
-    private ProxyArpStoreDelegate delegate;
-
-    private Map<HostId, ArpResponseMessage> pendingMessages = Maps.newConcurrentMap();
-
-    private ExecutorService executor =
-            newFixedThreadPool(4, groupedThreads("onos/arp", "sender-%d", log));
-
-    private NodeId localNodeId;
-
-    private HostListener hostListener = new InternalHostListener();
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected MastershipService mastershipService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ClusterService clusterService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ClusterCommunicationService commService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected HostService hostService;
-
-
-    @Activate
-    protected void activate() {
-        localNodeId = clusterService.getLocalNode().id();
-        hostService.addListener(hostListener);
-        commService.addSubscriber(ARP_RESPONSE_MESSAGE, serializer::decode,
-                                  this::processArpResponse, executor);
-        log.info("Started");
-    }
-
-    @Deactivate
-    protected void deactivate() {
-        commService.removeSubscriber(ARP_RESPONSE_MESSAGE);
-        hostService.removeListener(hostListener);
-        log.info("Stopped");
-    }
-
-    @Override
-    public void forward(ConnectPoint outPort, Host subject, ByteBuffer packet) {
-        /*NodeId nodeId = mastershipService.getMasterFor(outPort.deviceId());
-        if (nodeId.equals(localNodeId)) {
-            if (delegate != null) {
-                delegate.emitResponse(outPort, packet);
-            }
-        } else {
-            log.info("Forwarding ARP response from {} to {}", subject.id(), outPort);
-            commService.unicast(new ArpResponseMessage(outPort, subject, packet.array()),
-                                ARP_RESPONSE_MESSAGE, serializer::encode, nodeId);
-        }*/
-        //FIXME: Code above may be unnecessary and therefore cluster messaging
-        // and pendingMessages could be pruned as well.
-        delegate.emitResponse(outPort, packet);
-    }
-
-    @Override
-    public void setDelegate(ProxyArpStoreDelegate delegate) {
-        this.delegate = delegate;
-    }
-
-    // Processes the incoming ARP response message.
-    private void processArpResponse(ArpResponseMessage msg) {
-        pendingMessages.put(msg.subject.id(), msg);
-        if (hostService.getHost(msg.subject.id()) != null) {
-            checkPendingArps(msg.subject.id());
-        }
-        // FIXME: figure out pruning so stuff does not build up
-    }
-
-    // Checks for pending ARP response message for the specified host.
-    // If one exists, emit response via delegate.
-    private void checkPendingArps(HostId id) {
-        ArpResponseMessage msg = pendingMessages.remove(id);
-        if (msg != null && delegate != null) {
-            log.info("Emitting ARP response from {} to {}", id, msg.outPort);
-            delegate.emitResponse(msg.outPort, ByteBuffer.wrap(msg.packet));
-        }
-    }
-
-    // Message carrying an ARP response.
-    private static class ArpResponseMessage {
-        private ConnectPoint outPort;
-        private Host subject;
-        private byte[] packet;
-
-        public ArpResponseMessage(ConnectPoint outPort, Host subject, byte[] packet) {
-            this.outPort = outPort;
-            this.subject = subject;
-            this.packet = packet;
-        }
-
-        private ArpResponseMessage() {
-        }
-    }
-
-    private class InternalHostListener implements HostListener {
-        @Override
-        public void event(HostEvent event) {
-            checkPendingArps(event.subject().id());
-        }
-    }
-}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/package-info.java b/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/package-info.java
deleted file mode 100644
index a08c67b..0000000
--- a/core/store/dist/src/main/java/org/onosproject/store/proxyarp/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2015-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.
- */
-
-/**
- * Implementation of proxy ARP distribution mechanism.
- */
-package org.onosproject.store.proxyarp.impl;
