/*
 * Copyright 2015-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.segmentrouting;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.intf.Interface;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
import org.onosproject.segmentrouting.grouphandler.DestinationSet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ForwardingObjective.Builder;
import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
import org.onosproject.segmentrouting.storekey.DummyVlanIdStoreKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkNotNull;
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.ICMP6.ROUTER_ADVERTISEMENT;
import static org.onlab.packet.ICMP6.ROUTER_SOLICITATION;
import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
import static org.onosproject.segmentrouting.SegmentRoutingService.DEFAULT_PRIORITY;

/**
 * Populator of segment routing flow rules.
 */
public class RoutingRulePopulator {
    private static final Logger log = LoggerFactory.getLogger(RoutingRulePopulator.class);

    private static final int ARP_NDP_PRIORITY = 30000;

    private AtomicLong rulePopulationCounter;
    private SegmentRoutingManager srManager;
    private DeviceConfiguration config;
    private RouteSimplifierUtils routeSimplifierUtils;

    /**
     * Creates a RoutingRulePopulator object.
     *
     * @param srManager segment routing manager reference
     */
    RoutingRulePopulator(SegmentRoutingManager srManager) {
        this.srManager = srManager;
        this.config = checkNotNull(srManager.deviceConfiguration);
        this.rulePopulationCounter = new AtomicLong(0);
        this.routeSimplifierUtils = new RouteSimplifierUtils(srManager);
    }

    /**
     * Resets the population counter.
     */
    void resetCounter() {
        rulePopulationCounter.set(0);
    }

    /**
     * Returns the number of rules populated.
     *
     * @return number of rules
     */
    long getCounter() {
        return rulePopulationCounter.get();
    }

    /**
     * Populate a bridging rule on given deviceId that matches given mac, given vlan and
     * output to given port.
     *
     * @param deviceId device ID
     * @param port port
     * @param mac mac address
     * @param vlanId VLAN ID
     */
    void populateBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
        ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, false);
        if (fob == null) {
            log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
            return;
        }

        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("Brigding rule for {}/{} populated", mac, vlanId),
                (objective, error) -> log.warn("Failed to populate bridging rule for {}/{}: {}", mac, vlanId, error));
        srManager.flowObjectiveService.forward(deviceId, fob.add(context));
    }

    /**
     * Revoke a bridging rule on given deviceId that matches given mac, given vlan and
     * output to given port.
     *
     * @param deviceId device ID
     * @param port port
     * @param mac mac address
     * @param vlanId VLAN ID
     */
    void revokeBridging(DeviceId deviceId, PortNumber port, MacAddress mac, VlanId vlanId) {
        ForwardingObjective.Builder fob = bridgingFwdObjBuilder(deviceId, mac, vlanId, port, true);
        if (fob == null) {
            log.warn("Fail to build fwd obj for host {}/{}. Abort.", mac, vlanId);
            return;
        }

        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("Brigding rule for {}/{} revoked", mac, vlanId),
                (objective, error) -> log.warn("Failed to revoke bridging rule for {}/{}: {}", mac, vlanId, error));
        srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
    }

    /**
     * Generates a forwarding objective builder for bridging rules.
     * <p>
     * The forwarding objective bridges packets destined to a given MAC to
     * given port on given device.
     *
     * @param deviceId Device that host attaches to
     * @param mac MAC address of the host
     * @param hostVlanId VLAN ID of the host
     * @param outport Port that host attaches to
     * @param revoke true if forwarding objective is meant to revoke forwarding rule
     * @return Forwarding objective builder
     */
    private ForwardingObjective.Builder bridgingFwdObjBuilder(
            DeviceId deviceId, MacAddress mac, VlanId hostVlanId, PortNumber outport, boolean revoke) {
        ConnectPoint connectPoint = new ConnectPoint(deviceId, outport);
        VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
        Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
        VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);

        // Create host selector
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        sbuilder.matchEthDst(mac);

        // Create host treatment
        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
        tbuilder.immediate().setOutput(outport);

        // Create host meta
        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();

        // Adjust the selector, treatment and meta according to VLAN configuration
        if (taggedVlans.contains(hostVlanId)) {
            sbuilder.matchVlanId(hostVlanId);
            mbuilder.matchVlanId(hostVlanId);
        } else if (hostVlanId.equals(VlanId.NONE)) {
            if (untaggedVlan != null) {
                sbuilder.matchVlanId(untaggedVlan);
                mbuilder.matchVlanId(untaggedVlan);
                tbuilder.immediate().popVlan();
            } else if (nativeVlan != null) {
                sbuilder.matchVlanId(nativeVlan);
                mbuilder.matchVlanId(nativeVlan);
                tbuilder.immediate().popVlan();
            } else {
                log.warn("Untagged host {}/{} is not allowed on {} without untagged or native" +
                        "vlan config", mac, hostVlanId, connectPoint);
                return null;
            }
        } else {
            log.warn("Tagged host {}/{} is not allowed on {} without VLAN listed in tagged vlan",
                    mac, hostVlanId, connectPoint);
            return null;
        }

        // All forwarding is via Groups. Drivers can re-purpose to flow-actions if needed.
        // If the objective is to revoke an existing rule, and for some reason
        // the next-objective does not exist, then a new one should not be created
        int portNextObjId = srManager.getPortNextObjectiveId(deviceId, outport,
                tbuilder.build(), mbuilder.build(), !revoke);
        if (portNextObjId == -1) {
            // Warning log will come from getPortNextObjective method
            return null;
        }

        return DefaultForwardingObjective.builder()
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withSelector(sbuilder.build())
                .nextStep(portNextObjId)
                .withPriority(100)
                .fromApp(srManager.appId)
                .makePermanent();
    }

    /**
     * Populate or revoke a bridging rule on given deviceId that matches given vlanId,
     * and hostMAC connected to given port, and output to given port only when
     * vlan information is valid.
     *
     * @param deviceId device ID that host attaches to
     * @param portNum port number that host attaches to
     * @param hostMac mac address of the host connected to the switch port
     * @param vlanId Vlan ID configured on the switch port
     * @param popVlan true to pop Vlan tag at TrafficTreatment, false otherwise
     * @param install true to populate the objective, false to revoke
     */
    // TODO Refactor. There are a lot of duplications between this method, populateBridging,
    //      revokeBridging and bridgingFwdObjBuilder.
    void updateBridging(DeviceId deviceId, PortNumber portNum, MacAddress hostMac,
                        VlanId vlanId, boolean popVlan, boolean install) {
        // Create host selector
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        sbuilder.matchEthDst(hostMac);

        // Create host meta
        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();

        sbuilder.matchVlanId(vlanId);
        mbuilder.matchVlanId(vlanId);

        // Create host treatment
        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
        tbuilder.immediate().setOutput(portNum);

        if (popVlan) {
            tbuilder.immediate().popVlan();
        }

        int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNum,
                tbuilder.build(), mbuilder.build(), install);
        if (portNextObjId != -1) {
            ForwardingObjective.Builder fob = DefaultForwardingObjective.builder()
                    .withFlag(ForwardingObjective.Flag.SPECIFIC)
                    .withSelector(sbuilder.build())
                    .nextStep(portNextObjId)
                    .withPriority(100)
                    .fromApp(srManager.appId)
                    .makePermanent();

            ObjectiveContext context = new DefaultObjectiveContext(
                    (objective) -> log.debug("Brigding rule for {}/{} {}", hostMac, vlanId,
                            install ? "populated" : "revoked"),
                    (objective, error) -> log.warn("Failed to {} bridging rule for {}/{}: {}",
                            install ? "populate" : "revoke", hostMac, vlanId, error));
            srManager.flowObjectiveService.forward(deviceId, install ? fob.add(context) : fob.remove(context));
        } else {
            log.warn("Failed to retrieve next objective for {}/{}", hostMac, vlanId);
        }
    }

    /**
     * Populates IP rules for a route that has direct connection to the switch.
     * This method should not be invoked directly without going through DefaultRoutingHandler.
     *
     * @param deviceId device ID of the device that next hop attaches to
     * @param prefix IP prefix of the route
     * @param hostMac MAC address of the next hop
     * @param hostVlanId Vlan ID of the nexthop
     * @param outPort port where the next hop attaches to
     * @param directHost host is of type direct or indirect
     */
    void populateRoute(DeviceId deviceId, IpPrefix prefix,
                              MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
        log.debug("Populate direct routing entry for route {} at {}:{}",
                prefix, deviceId, outPort);
        ForwardingObjective.Builder fwdBuilder;
        try {
            fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac,
                                              hostVlanId, outPort, directHost, false);
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting direct populateRoute");
            return;
        }
        if (fwdBuilder == null) {
            log.warn("Aborting host routing table entry due "
                    + "to error for dev:{} route:{}", deviceId, prefix);
            return;
        }

        int nextId = fwdBuilder.add().nextId();
        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("Direct routing rule for route {} populated. nextId={}",
                                         prefix, nextId),
                (objective, error) ->
                        log.warn("Failed to populate direct routing rule for route {}: {}",
                                 prefix, error));
        srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
        rulePopulationCounter.incrementAndGet();
    }

    /**
     * Removes IP rules for a route when the next hop is gone.
     * This method should not be invoked directly without going through DefaultRoutingHandler.
     *
     * @param deviceId device ID of the device that next hop attaches to
     * @param prefix IP prefix of the route
     * @param hostMac MAC address of the next hop
     * @param hostVlanId Vlan ID of the nexthop
     * @param outPort port that next hop attaches to
     * @param directHost host is of type direct or indirect
     */
    void revokeRoute(DeviceId deviceId, IpPrefix prefix,
            MacAddress hostMac, VlanId hostVlanId, PortNumber outPort, boolean directHost) {
        log.debug("Revoke IP table entry for route {} at {}:{}",
                prefix, deviceId, outPort);
        ForwardingObjective.Builder fwdBuilder;
        try {
            fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac,
                                              hostVlanId, outPort, directHost, true);
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting revokeIpRuleForHost.");
            return;
        }
        if (fwdBuilder == null) {
            log.warn("Aborting host routing table entries due "
                    + "to error for dev:{} route:{}", deviceId, prefix);
            return;
        }
        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("IP rule for route {} revoked", prefix),
                (objective, error) ->
                        log.warn("Failed to revoke IP rule for route {}: {}", prefix, error));
        srManager.flowObjectiveService.forward(deviceId, fwdBuilder.remove(context));
    }

    /**
     * Returns a forwarding objective builder for routing rules.
     * <p>
     * The forwarding objective routes packets destined to a given prefix to
     * given port on given device with given destination MAC.
     *
     * @param deviceId device ID
     * @param prefix prefix that need to be routed
     * @param hostMac MAC address of the nexthop
     * @param hostVlanId Vlan ID of the nexthop
     * @param outPort port where the nexthop attaches to
     * @param revoke true if forwarding objective is meant to revoke forwarding rule
     * @param directHost host is direct or indirect
     * @return forwarding objective builder
     * @throws DeviceConfigNotFoundException if given device is not configured
     */

    private ForwardingObjective.Builder


    routingFwdObjBuilder(
            DeviceId deviceId, IpPrefix prefix,
            MacAddress hostMac, VlanId hostVlanId, PortNumber outPort,
            boolean directHost, boolean revoke)
            throws DeviceConfigNotFoundException {
        MacAddress deviceMac;
        deviceMac = config.getDeviceMac(deviceId);
        int nextObjId = -1;

        ConnectPoint connectPoint = new ConnectPoint(deviceId, outPort);
        VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
        Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
        VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);

        // Create route selector
        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(prefix);

        // Create route treatment
        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
        tbuilder.deferred()
                .setEthDst(hostMac)
                .setEthSrc(deviceMac)
                .setOutput(outPort);

        // Create route meta
        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();

        // Adjust the meta according to VLAN configuration
        if (taggedVlans.contains(hostVlanId)) {
            tbuilder.setVlanId(hostVlanId);
        } else if (hostVlanId.equals(VlanId.NONE)) {
            if (untaggedVlan != null) {
                mbuilder.matchVlanId(untaggedVlan);
            } else if (nativeVlan != null) {
                mbuilder.matchVlanId(nativeVlan);
            } else {
                log.warn("Untagged nexthop {}/{} is not allowed on {} without untagged or native vlan",
                        hostMac, hostVlanId, connectPoint);
                return null;
            }
        } else {
            // Internally-assigned dummy VLAN id will be given as hostVlanId
            // when destination is double-tagged.
            VlanId vlanId = srManager.dummyVlanIdStore().get(
                    new DummyVlanIdStoreKey(connectPoint, prefix.address()));
            if (vlanId != null && vlanId.equals(hostVlanId)) {
                tbuilder.setVlanId(hostVlanId);
                mbuilder.matchVlanId(VlanId.ANY);
            } else {
                log.warn("Tagged nexthop {}/{} is not allowed on {} without VLAN listed"
                                 + " in tagged vlan", hostMac, hostVlanId, connectPoint);
                return null;
            }
        }

        if (directHost) {
          // if the objective is to revoke an existing rule, and for some reason
          // the next-objective does not exist, then a new one should not be created
          nextObjId = srManager.getPortNextObjectiveId(deviceId, outPort,
                                          tbuilder.build(), mbuilder.build(), !revoke);
        } else {
          // if the objective is to revoke an existing rule, and for some reason
          // the next-objective does not exist, then a new one should not be created
          nextObjId = srManager.getMacVlanNextObjectiveId(deviceId, hostMac, hostVlanId,
                                          tbuilder.build(), mbuilder.build(), !revoke);
        }
        if (nextObjId == -1) {
            // Warning log will come from getMacVlanNextObjective method
            return null;
        }

        return DefaultForwardingObjective.builder()
                .withSelector(sbuilder.build())
                .nextStep(nextObjId)
                .fromApp(srManager.appId).makePermanent()
                .withPriority(getPriorityFromPrefix(prefix))
                .withFlag(ForwardingObjective.Flag.SPECIFIC);
    }

    /**
     * Populates IP flow rules for all the given prefixes reachable from the
     * destination switch(es).
     *
     * @param targetSw switch where rules are to be programmed
     * @param subnets subnets/prefixes being added
     * @param destSw1 destination switch where the prefixes are reachable
     * @param destSw2 paired destination switch if one exists for the subnets/prefixes.
     *                Should be null if there is no paired destination switch (by config)
     *                or if the given prefixes are reachable only via destSw1
     * @param nextHops a map containing a set of next-hops for each destination switch.
     *                 If destSw2 is not null, then this map must contain an
     *                 entry for destSw2 with its next-hops from the targetSw
     *                 (although the next-hop set may be empty in certain scenarios).
     *                 If destSw2 is null, there should not be an entry in this
     *                 map for destSw2.
     * @return true if all rules are set successfully, false otherwise
     */
    boolean populateIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets,
            DeviceId destSw1, DeviceId destSw2, Map<DeviceId, Set<DeviceId>> nextHops) {
        // Get pair device of the target switch
        Optional<DeviceId> pairDev = srManager.getPairDeviceId(targetSw);
        // Route simplification will be off in case of the nexthop location at target switch is down
        // (routing through spine case)
        boolean routeSimplOff = pairDev.isPresent() && pairDev.get().equals(destSw1) && destSw2 == null;
        // Iterates over the routes
        // If route simplification is enabled
        // If the target device is another leaf in the network
        if (srManager.routeSimplification && !routeSimplOff) {
            for (IpPrefix subnet : subnets) {
                // Skip route programming on the target device
                // If route simplification applies
                if (routeSimplifierUtils.hasLeafExclusionEnabledForPrefix(subnet)) {
                    // XXX route simplification assumes that source of the traffic
                    // towards the nexthops are co-located with the nexthops. In different
                    // scenarios will not work properly.
                    continue;
                }
                // populate the route in the remaning scenarios
                if (!populateIpRuleForRouter(targetSw, subnet, destSw1, destSw2, nextHops)) {
                    return false;
                }
            }
        } else {
            // Populate IP flow rules for all the subnets.
            for (IpPrefix subnet : subnets) {
                if (!populateIpRuleForRouter(targetSw, subnet, destSw1, destSw2, nextHops)) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Revokes IP flow rules for the subnets from given device.
     *
     * @param targetSw target switch from which the subnets need to be removed
     * @param subnets subnet being removed
     * @return true if all rules are removed successfully, false otherwise
     */
    boolean revokeIpRuleForSubnet(DeviceId targetSw, Set<IpPrefix> subnets) {
        for (IpPrefix subnet : subnets) {
            if (!revokeIpRuleForRouter(targetSw, subnet)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Populates IP flow rules for an IP prefix in the target device. The prefix
     * is reachable via destination device(s).
     *
     * @param targetSw target device ID to set the rules
     * @param ipPrefix the IP prefix
     * @param destSw1 destination switch where the prefixes are reachable
     * @param destSw2 paired destination switch if one exists for the subnets/prefixes.
     *                Should be null if there is no paired destination switch (by config)
     *                or if the given prefixes are reachable only via destSw1
     * @param nextHops map of destination switches and their next-hops.
     *                  Should only contain destination switches that are
     *                  actually meant to be routed to. If destSw2 is null, there
     *                  should not be an entry for destSw2 in this map.
     * @return true if all rules are set successfully, false otherwise
     */
    private boolean populateIpRuleForRouter(DeviceId targetSw,
                                           IpPrefix ipPrefix, DeviceId destSw1,
                                           DeviceId destSw2,
                                           Map<DeviceId, Set<DeviceId>> nextHops) {
        int segmentId1, segmentId2 = -1;
        try {
            if (ipPrefix.isIp4()) {
                segmentId1 = config.getIPv4SegmentId(destSw1);
                if (destSw2 != null) {
                    segmentId2 = config.getIPv4SegmentId(destSw2);
                }
            } else {
                segmentId1 = config.getIPv6SegmentId(destSw1);
                if (destSw2 != null) {
                    segmentId2 = config.getIPv6SegmentId(destSw2);
                }
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting populateIpRuleForRouter.");
            return false;
        }

        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(ipPrefix);
        TrafficSelector selector = sbuilder.build();

        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
        DestinationSet ds;
        TrafficTreatment treatment;
        DestinationSet.DestinationSetType dsType;

        if (destSw2 == null) {
            // single dst - create destination set based on next-hop
            // If the next hop is the same as the final destination, then MPLS
            // label is not set.
            Set<DeviceId> nhd1 = nextHops.get(destSw1);
            if (nhd1.size() == 1 && nhd1.iterator().next().equals(destSw1)) {
                tbuilder.immediate().decNwTtl();
                ds = DestinationSet.createTypePushNone(destSw1);
                treatment = tbuilder.build();
            } else {
                ds = DestinationSet.createTypePushBos(segmentId1, destSw1);
                treatment = null;
            }
        } else {
            // dst pair - IP rules for dst-pairs are always from other edge nodes
            // the destination set needs to have both destinations, even if there
            // are no next hops to one of them
            ds = DestinationSet.createTypePushBos(segmentId1, destSw1, segmentId2, destSw2);
            treatment = null;
        }

        // setup metadata to pass to nextObjective - indicate the vlan on egress
        // if needed by the switch pipeline. Since neighbor sets are always to
        // other neighboring routers, there is no subnet assigned on those ports.
        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
        metabuilder.matchVlanId(srManager.getDefaultInternalVlan());
        DefaultGroupHandler grpHandler = srManager.getGroupHandler(targetSw);
        if (grpHandler == null) {
            log.warn("populateIPRuleForRouter: groupHandler for device {} "
                    + "not found", targetSw);
            return false;
        }

        int nextId = grpHandler.getNextObjectiveId(ds, nextHops,
                                                   metabuilder.build(), false);
        if (nextId <= 0) {
            log.warn("No next objective in {} for ds: {}", targetSw, ds);
            return false;
        }

        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
                .builder()
                .fromApp(srManager.appId)
                .makePermanent()
                .nextStep(nextId)
                .withSelector(selector)
                .withPriority(getPriorityFromPrefix(ipPrefix))
                .withFlag(ForwardingObjective.Flag.SPECIFIC);
        if (treatment != null) {
            fwdBuilder.withTreatment(treatment);
        }
        log.debug("Installing IPv4 forwarding objective for router IP/subnet {} "
                + "in switch {} with nextId: {}", ipPrefix, targetSw, nextId);
        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("IP rule for router {} populated in dev:{}",
                                         ipPrefix, targetSw),
                (objective, error) ->
                        log.warn("Failed to populate IP rule for router {}: {} in dev:{}",
                                 ipPrefix, error, targetSw));
        srManager.flowObjectiveService.forward(targetSw, fwdBuilder.add(context));
        rulePopulationCounter.incrementAndGet();

        return true;
    }

    /**
     * Revokes IP flow rules for the router IP address from given device.
     *
     * @param targetSw target switch from which the ipPrefix need to be removed
     * @param ipPrefix the IP address of the destination router
     * @return true if all rules are removed successfully, false otherwise
     */
    private boolean revokeIpRuleForRouter(DeviceId targetSw, IpPrefix ipPrefix) {
        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(ipPrefix);
        TrafficSelector selector = sbuilder.build();
        TrafficTreatment dummyTreatment = DefaultTrafficTreatment.builder().build();

        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
                .builder()
                .fromApp(srManager.appId)
                .makePermanent()
                .withSelector(selector)
                .withTreatment(dummyTreatment)
                .withPriority(getPriorityFromPrefix(ipPrefix))
                .withFlag(ForwardingObjective.Flag.SPECIFIC);

        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("IP rule for router {} revoked from {}", ipPrefix, targetSw),
                (objective, error) -> log.warn("Failed to revoke IP rule for router {} from {}: {}",
                        ipPrefix, targetSw, error));
        srManager.flowObjectiveService.forward(targetSw, fwdBuilder.remove(context));

        return true;
    }

    /**
     * Populates MPLS flow rules in the target device to point towards the
     * destination device.
     *
     * @param targetSwId target device ID of the switch to set the rules
     * @param destSwId destination switch device ID
     * @param nextHops next hops switch ID list
     * @param routerIp the router ip of the destination switch
     * @return true if all rules are set successfully, false otherwise
     */
    boolean populateMplsRule(DeviceId targetSwId, DeviceId destSwId,
                             Set<DeviceId> nextHops, IpAddress routerIp) {
        int segmentId;
        try {
            if (routerIp.isIp4()) {
                segmentId = config.getIPv4SegmentId(destSwId);
            } else {
                segmentId = config.getIPv6SegmentId(destSwId);
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting populateMplsRule.");
            return false;
        }

        List<ForwardingObjective> fwdObjs = new ArrayList<>();
        Collection<ForwardingObjective> fwdObjsMpls;
        // Generates the transit rules used by the standard "routing".
        fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, segmentId,
                                 routerIp, true);
        if (fwdObjsMpls.isEmpty()) {
            return false;
        }
        fwdObjs.addAll(fwdObjsMpls);

        // Generates the transit rules used by the MPLS Pwaas.
        int pwSrLabel;
        try {
            pwSrLabel = config.getPWRoutingLabel(destSwId);
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage()
                    + " Aborting populateMplsRule. No label for PseudoWire traffic.");
            return false;
        }
        fwdObjsMpls = handleMpls(targetSwId, destSwId, nextHops, pwSrLabel,
                                 routerIp, false);
        if (fwdObjsMpls.isEmpty()) {
            return false;
        }
        fwdObjs.addAll(fwdObjsMpls);

        for (ForwardingObjective fwdObj : fwdObjs) {
            log.debug("Sending MPLS fwd obj {} for SID {}-> next {} in sw: {}",
                      fwdObj.id(), segmentId, fwdObj.nextId(), targetSwId);
            srManager.flowObjectiveService.forward(targetSwId, fwdObj);
            rulePopulationCounter.incrementAndGet();
        }

        return true;
    }

    /**
     * Differentiates between popping and swapping labels when building an MPLS
     * forwarding objective.
     *
     * @param targetSwId the target sw
     * @param destSwId the destination sw
     * @param nextHops the set of next hops
     * @param segmentId the segmentId to match representing the destination
     *            switch
     * @param routerIp the router ip representing the destination switch
     * @return a collection of fwdobjective
     */
    private Collection<ForwardingObjective> handleMpls(
                                        DeviceId targetSwId,
                                        DeviceId destSwId,
                                        Set<DeviceId> nextHops,
                                        int segmentId,
                                        IpAddress routerIp,
                                        boolean isMplsBos) {

        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        List<ForwardingObjective.Builder> fwdObjBuilders = Lists.newArrayList();
        // For the transport of Pwaas we can use two or three MPLS label
        sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
        sbuilder.matchMplsLabel(MplsLabel.mplsLabel(segmentId));
        sbuilder.matchMplsBos(isMplsBos);
        TrafficSelector selector = sbuilder.build();

        // setup metadata to pass to nextObjective - indicate the vlan on egress
        // if needed by the switch pipeline. Since mpls next-hops are always to
        // other neighboring routers, there is no subnet assigned on those ports.
        TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
        metabuilder.matchVlanId(srManager.getDefaultInternalVlan());

        if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
            // If the next hop is the destination router for the segment, do pop
            log.debug("populateMplsRule: Installing MPLS forwarding objective for "
                    + "label {} in switch {} with pop to next-hops {}",
                    segmentId, targetSwId, nextHops);
            ForwardingObjective.Builder fwdObjNoBosBuilder =
                    getMplsForwardingObjective(targetSwId,
                                               nextHops,
                                               true,
                                               isMplsBos,
                                               metabuilder.build(),
                                               routerIp,
                                               segmentId,
                                               destSwId);
            // Error case, we cannot handle, exit.
            if (fwdObjNoBosBuilder == null) {
                return Collections.emptyList();
            }
            fwdObjBuilders.add(fwdObjNoBosBuilder);

        } else {
            // next hop is not destination, irrespective of the number of next
            // hops (1 or more) -- SR CONTINUE case (swap with self)
            log.debug("Installing MPLS forwarding objective for "
                    + "label {} in switch {} without pop to next-hops {}",
                    segmentId, targetSwId, nextHops);
            ForwardingObjective.Builder fwdObjNoBosBuilder =
                    getMplsForwardingObjective(targetSwId,
                                               nextHops,
                                               false,
                                               isMplsBos,
                                               metabuilder.build(),
                                               routerIp,
                                               segmentId,
                                               destSwId);
            // Error case, we cannot handle, exit.
            if (fwdObjNoBosBuilder == null) {
                return Collections.emptyList();
            }
            fwdObjBuilders.add(fwdObjNoBosBuilder);

        }

        List<ForwardingObjective> fwdObjs = Lists.newArrayList();
        // We add the final property to the fwdObjs.
        for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
            ((Builder) ((Builder) fwdObjBuilder
                    .fromApp(srManager.appId)
                    .makePermanent())
                    .withSelector(selector)
                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY))
                    .withFlag(ForwardingObjective.Flag.SPECIFIC);

            ObjectiveContext context = new DefaultObjectiveContext(
                    (objective) ->
                            log.debug("MPLS rule {} for SID {} populated in dev:{} ",
                                      objective.id(), segmentId, targetSwId),
                    (objective, error) ->
                            log.warn("Failed to populate MPLS rule {} for SID {}: {} in dev:{}",
                                     objective.id(), segmentId, error, targetSwId));

            ForwardingObjective fob = fwdObjBuilder.add(context);
            fwdObjs.add(fob);
        }

        return fwdObjs;
    }

    /**
     * Returns a Forwarding Objective builder for the MPLS rule that references
     * the desired Next Objective. Creates a DestinationSet that allows the
     * groupHandler to create or find the required next objective.
     *
     * @param targetSw the target sw
     * @param nextHops the set of next hops
     * @param phpRequired true if penultimate-hop-popping is required
     * @param isBos true if matched label is bottom-of-stack
     * @param meta metadata for creating next objective
     * @param routerIp the router ip representing the destination switch
     * @param destSw the destination sw
     * @return the mpls forwarding objective builder
     */
    private ForwardingObjective.Builder getMplsForwardingObjective(
                                             DeviceId targetSw,
                                             Set<DeviceId> nextHops,
                                             boolean phpRequired,
                                             boolean isBos,
                                             TrafficSelector meta,
                                             IpAddress routerIp,
                                             int segmentId,
                                             DeviceId destSw) {

        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
                .builder().withFlag(ForwardingObjective.Flag.SPECIFIC);

        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
        DestinationSet ds = null;
        DestinationSet.DestinationSetType dstType = null;
        boolean simple = false;
        if (phpRequired) {
            // php case - pop should always be flow-action
            log.debug("getMplsForwardingObjective: php required");
            tbuilder.deferred().copyTtlIn();
            if (isBos) {
                if (routerIp.isIp4()) {
                    tbuilder.deferred().popMpls(EthType.EtherType.IPV4.ethType());
                } else {
                    tbuilder.deferred().popMpls(EthType.EtherType.IPV6.ethType());
                }
                tbuilder.decNwTtl();
                // standard case -> BoS == True; pop results in IP packet and forwarding
                // is via an ECMP group
                ds = DestinationSet.createTypePopBos(destSw);
            } else {
                tbuilder.deferred().popMpls(EthType.EtherType.MPLS_UNICAST.ethType())
                    .decMplsTtl();
                // double-label case -> BoS == False, pop results in MPLS packet
                // depending on configuration we can ECMP this packet or choose one output
                ds = DestinationSet.createTypePopNotBos(destSw);
                if (!srManager.getMplsEcmp()) {
                   simple = true;
                }
            }
        } else {
            // swap with self case - SR CONTINUE
            log.debug("getMplsForwardingObjective: swap with self");
            tbuilder.deferred().decMplsTtl();
            // swap results in MPLS packet with same BoS bit regardless of bit value
            // depending on configuration we can ECMP this packet or choose one output
            // differentiate here between swap with not bos or swap with bos
            ds = isBos ? DestinationSet.createTypeSwapBos(segmentId, destSw) :
                    DestinationSet.createTypeSwapNotBos(segmentId, destSw);
            if (!srManager.getMplsEcmp()) {
                simple = true;
            }
        }

        fwdBuilder.withTreatment(tbuilder.build());
        log.debug("Trying to get a nextObjId for mpls rule on device:{} to ds:{}",
                  targetSw, ds);
        DefaultGroupHandler gh = srManager.getGroupHandler(targetSw);
        if (gh == null) {
            log.warn("getNextObjectiveId query - groupHandler for device {} "
                    + "not found", targetSw);
            return null;
        }

        Map<DeviceId, Set<DeviceId>> dstNextHops = new HashMap<>();
        dstNextHops.put(destSw, nextHops);
        int nextId = gh.getNextObjectiveId(ds, dstNextHops, meta, simple);
        if (nextId <= 0) {
            log.warn("No next objective in {} for ds: {}", targetSw, ds);
            return null;
        } else {
            log.debug("nextObjId found:{} for mpls rule on device:{} to ds:{}",
                      nextId, targetSw, ds);
        }

        fwdBuilder.nextStep(nextId);
        return fwdBuilder;
    }

    /**
     * Creates a filtering objective to permit all untagged packets with a
     * dstMac corresponding to the router's MAC address. For those pipelines
     * that need to internally assign vlans to untagged packets, this method
     * provides per-subnet vlan-ids as metadata.
     * <p>
     * Note that the vlan assignment and filter programming should only be done by
     * the master for a switch. This method is typically called at deviceAdd and
     * programs filters only for the enabled ports of the device. For port-updates,
     * that enable/disable ports after device add, singlePortFilter methods should
     * be called.
     *
     * @param deviceId  the switch dpid for the router
     * @return PortFilterInfo information about the processed ports
     */
    PortFilterInfo populateVlanMacFilters(DeviceId deviceId) {
        log.debug("Installing per-port filtering objective for untagged "
                + "packets in device {}", deviceId);

        List<Port> devPorts = srManager.deviceService.getPorts(deviceId);
        if (devPorts == null || devPorts.isEmpty()) {
            log.warn("Device {} ports not available. Unable to add MacVlan filters",
                     deviceId);
            return null;
        }
        int disabledPorts = 0, errorPorts = 0, filteredPorts = 0;
        for (Port port : devPorts) {
            if (!port.isEnabled()) {
                disabledPorts++;
                continue;
            }
            if (processSinglePortFilters(deviceId, port.number(), true)) {
                filteredPorts++;
            } else {
                errorPorts++;
            }
        }
        log.debug("Filtering on dev:{}, disabledPorts:{}, errorPorts:{}, filteredPorts:{}",
                  deviceId, disabledPorts, errorPorts, filteredPorts);
        return new PortFilterInfo(disabledPorts, errorPorts, filteredPorts);
    }

    /**
     * Creates or removes filtering objectives for a single port. Should only be
     * called by the master for a switch.
     *
     * @param deviceId device identifier
     * @param portnum  port identifier for port to be filtered
     * @param install true to install the filtering objective, false to remove
     * @return true if no errors occurred during the build of the filtering objective
     */
    boolean processSinglePortFilters(DeviceId deviceId, PortNumber portnum, boolean install) {
        ConnectPoint connectPoint = new ConnectPoint(deviceId, portnum);
        VlanId untaggedVlan = srManager.interfaceService.getUntaggedVlanId(connectPoint);
        Set<VlanId> taggedVlans = srManager.interfaceService.getTaggedVlanId(connectPoint);
        VlanId nativeVlan = srManager.interfaceService.getNativeVlanId(connectPoint);

        // Do not configure filter for edge ports where double-tagged hosts are connected.
        if (taggedVlans.size() != 0) {
            // Filter for tagged vlans
            if (!srManager.interfaceService.getTaggedVlanId(connectPoint).stream().allMatch(taggedVlanId ->
                    processSinglePortFiltersInternal(deviceId, portnum, false, taggedVlanId, install))) {
                return false;
            }
            if (nativeVlan != null) {
                // Filter for native vlan
                if (!processSinglePortFiltersInternal(deviceId, portnum, true, nativeVlan, install)) {
                    return false;
                }
            }
        } else if (untaggedVlan != null) {
            // Filter for untagged vlan
            if (!processSinglePortFiltersInternal(deviceId, portnum, true, untaggedVlan, install)) {
                return false;
            }
        } else if (!hasIPConfiguration(connectPoint)) {
            // Filter for unconfigured upstream port, using INTERNAL_VLAN
            if (!processSinglePortFiltersInternal(deviceId, portnum, true,
                                                  srManager.getDefaultInternalVlan(),
                                                  install)) {
                return false;
            }
            // Filter for receiveing pseudowire traffic
            if (!processSinglePortFiltersInternal(deviceId, portnum, false,
                                                  srManager.getPwTransportVlan(),
                                                  install)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Updates filtering objectives for a single port. Should only be called by
     * the master for a switch
     * @param deviceId device identifier
     * @param portNum  port identifier for port to be filtered
     * @param pushVlan true to push vlan, false otherwise
     * @param vlanId vlan identifier
     * @param install true to install the filtering objective, false to remove
     */
    void updateSinglePortFilters(DeviceId deviceId, PortNumber portNum,
                                 boolean pushVlan, VlanId vlanId, boolean install) {
        if (!processSinglePortFiltersInternal(deviceId, portNum, pushVlan, vlanId, install)) {
            log.warn("Failed to update FilteringObjective for {}/{} with vlan {}",
                     deviceId, portNum, vlanId);
        }
    }

    private boolean processSinglePortFiltersInternal(DeviceId deviceId, PortNumber portnum,
                                                      boolean pushVlan, VlanId vlanId, boolean install) {
        boolean doTMAC = true;

        if (!pushVlan) {
            // Skip the tagged vlans belonging to an interface without an IP address
            Set<Interface> ifaces = srManager.interfaceService
                    .getInterfacesByPort(new ConnectPoint(deviceId, portnum))
                    .stream()
                    .filter(intf -> intf.vlanTagged().contains(vlanId) && intf.ipAddressesList().isEmpty())
                    .collect(Collectors.toSet());
            if (!ifaces.isEmpty()) {
                log.debug("processSinglePortFiltersInternal: skipping TMAC for vlan {} at {}/{} - no IP",
                          vlanId, deviceId, portnum);
                doTMAC = false;
            }
        }

        FilteringObjective.Builder fob = buildFilteringObjective(deviceId, portnum, pushVlan, vlanId, doTMAC);
        if (fob == null) {
            // error encountered during build
            return false;
        }
        log.debug("{} filtering objectives for dev/port: {}/{}",
                 install ? "Installing" : "Removing", deviceId, portnum);
        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("Filter for {}/{} {}", deviceId, portnum,
                        install ? "installed" : "removed"),
                (objective, error) -> log.warn("Failed to {} filter for {}/{}: {}",
                        install ? "install" : "remove", deviceId, portnum, error));
        if (install) {
            srManager.flowObjectiveService.filter(deviceId, fob.add(context));
        } else {
            srManager.flowObjectiveService.filter(deviceId, fob.remove(context));
        }
        return true;
    }

    private FilteringObjective.Builder buildFilteringObjective(DeviceId deviceId, PortNumber portnum,
                                                               boolean pushVlan, VlanId vlanId, boolean doTMAC) {
        MacAddress deviceMac;
        try {
            deviceMac = config.getDeviceMac(deviceId);
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Processing SinglePortFilters aborted");
            return null;
        }
        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();

        if (doTMAC) {
            fob.withKey(Criteria.matchInPort(portnum))
                    .addCondition(Criteria.matchEthDst(deviceMac))
                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
        } else {
            fob.withKey(Criteria.matchInPort(portnum))
                    .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);
        }

        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        if (pushVlan) {
            fob.addCondition(Criteria.matchVlanId(VlanId.NONE));
            tBuilder.pushVlan().setVlanId(vlanId);
        } else {
            fob.addCondition(Criteria.matchVlanId(vlanId));
        }

        // NOTE: Some switch hardware share the same filtering flow among different ports.
        //       We use this metadata to let the driver know that there is no more enabled port
        //       within the same VLAN on this device.
        if (noMoreEnabledPort(deviceId, vlanId)) {
            tBuilder.wipeDeferred();
        }

        fob.withMeta(tBuilder.build());

        fob.permit().fromApp(srManager.appId);
        return fob;
    }

    /**
     * Creates or removes filtering objectives for a double-tagged host on a port.
     *
     * @param deviceId device identifier
     * @param portNum  port identifier for port to be filtered
     * @param outerVlan outer VLAN ID
     * @param innerVlan inner VLAN ID
     * @param install true to install the filtering objective, false to remove
     */
    void processDoubleTaggedFilter(DeviceId deviceId, PortNumber portNum, VlanId outerVlan,
                                   VlanId innerVlan, boolean install) {
        FilteringObjective.Builder fob = buildDoubleTaggedFilteringObj(deviceId, portNum, outerVlan, innerVlan);
        if (fob == null) {
            // error encountered during build
            return;
        }
        log.debug("{} double-tagged filtering objectives for dev/port: {}/{}",
                  install ? "Installing" : "Removing", deviceId, portNum);
        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("Filter for {}/{} {}", deviceId, portNum,
                                         install ? "installed" : "removed"),
                (objective, error) -> log.warn("Failed to {} filter for {}/{}: {}",
                                               install ? "install" : "remove", deviceId, portNum, error));
        if (install) {
            srManager.flowObjectiveService.filter(deviceId, fob.add(context));
        } else {
            srManager.flowObjectiveService.filter(deviceId, fob.remove(context));
        }
    }

    private FilteringObjective.Builder buildDoubleTaggedFilteringObj(DeviceId deviceId, PortNumber portNum,
                                                                     VlanId outerVlan, VlanId innerVlan) {
        MacAddress deviceMac;
        try {
            deviceMac = config.getDeviceMac(deviceId);
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Processing DoubleTaggedFilters aborted");
            return null;
        }
        FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
        // Outer vlan id match should be appeared before inner vlan id match.
        fob.withKey(Criteria.matchInPort(portNum))
                .addCondition(Criteria.matchEthDst(deviceMac))
                .addCondition(Criteria.matchVlanId(outerVlan))
                .addCondition(Criteria.matchVlanId(innerVlan))
                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY);

        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
        // Pop outer vlan
        tBuilder.popVlan();

        // NOTE: Some switch hardware share the same filtering flow among different ports.
        //       We use this metadata to let the driver know that there is no more enabled port
        //       within the same VLAN on this device.
        if (noMoreEnabledPort(deviceId, outerVlan)) {
            tBuilder.wipeDeferred();
        }

        fob.withMeta(tBuilder.build());

        fob.permit().fromApp(srManager.appId);
        return fob;
    }

    /**
     * Creates a forwarding objective to punt all IP packets, destined to the
     * router's port IP addresses, to the controller. Note that the input
     * port should not be matched on, as these packets can come from any input.
     * Furthermore, these are applied only by the master instance.
     *
     * @param deviceId the switch dpid for the router
     */
    void populateIpPunts(DeviceId deviceId) {
        Ip4Address routerIpv4, pairRouterIpv4 = null;
        Ip6Address routerIpv6, routerLinkLocalIpv6, pairRouterIpv6 = null;
        try {
            routerIpv4 = config.getRouterIpv4(deviceId);
            routerIpv6 = config.getRouterIpv6(deviceId);
            routerLinkLocalIpv6 = Ip6Address.valueOf(
                    IPv6.getLinkLocalAddress(config.getDeviceMac(deviceId).toBytes()));

            if (config.isPairedEdge(deviceId)) {
                pairRouterIpv4 = config.getRouterIpv4(config.getPairDeviceId(deviceId));
                pairRouterIpv6 = config.getRouterIpv6(config.getPairDeviceId(deviceId));
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting populateIpPunts.");
            return;
        }

        if (!srManager.mastershipService.isLocalMaster(deviceId)) {
            log.debug("Not installing port-IP punts - not the master for dev:{} ",
                      deviceId);
            return;
        }
        Set<IpAddress> allIps = new HashSet<>(config.getPortIPs(deviceId));
        allIps.add(routerIpv4);
        if (routerIpv6 != null) {
            allIps.add(routerIpv6);
            allIps.add(routerLinkLocalIpv6);
        }
        if (pairRouterIpv4 != null) {
            allIps.add(pairRouterIpv4);
        }
        if (pairRouterIpv6 != null) {
            allIps.add(pairRouterIpv6);
        }
        for (IpAddress ipaddr : allIps) {
            populateSingleIpPunts(deviceId, ipaddr);
        }
    }

    /**
     * Creates a forwarding objective to punt all IP packets, destined to the
     * specified IP address, which should be router's port IP address.
     *
     * @param deviceId the switch dpid for the router
     * @param ipAddress the IP address of the router's port
     */
    void populateSingleIpPunts(DeviceId deviceId, IpAddress ipAddress) {
        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipAddress);
        Optional<DeviceId> optDeviceId = Optional.of(deviceId);

        srManager.packetService.requestPackets(sbuilder.build(),
                                               PacketPriority.CONTROL, srManager.appId, optDeviceId);
    }

    /**
     * Removes a forwarding objective to punt all IP packets, destined to the
     * specified IP address, which should be router's port IP address.
     *
     * @param deviceId the switch dpid for the router
     * @param ipAddress the IP address of the router's port
     */
    void revokeSingleIpPunts(DeviceId deviceId, IpAddress ipAddress) {
        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpAddress(ipAddress);
        Optional<DeviceId> optDeviceId = Optional.of(deviceId);

        try {
            if (!ipAddress.equals(config.getRouterIpv4(deviceId)) &&
                    !ipAddress.equals(config.getRouterIpv6(deviceId))) {
                srManager.packetService.cancelPackets(sbuilder.build(),
                                                      PacketPriority.CONTROL, srManager.appId, optDeviceId);
            }
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting revokeSingleIpPunts");
        }
    }

    /**
     * Method to build IPv4 or IPv6 selector.
     *
     * @param addressToMatch the address to match
     */
    private TrafficSelector.Builder buildIpSelectorFromIpAddress(IpAddress addressToMatch) {
        return buildIpSelectorFromIpPrefix(addressToMatch.toIpPrefix());
    }

    /**
     * Method to build IPv4 or IPv6 selector.
     *
     * @param prefixToMatch the prefix to match
     */
    private TrafficSelector.Builder buildIpSelectorFromIpPrefix(IpPrefix prefixToMatch) {
        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        // If the prefix is IPv4
        if (prefixToMatch.isIp4()) {
            selectorBuilder.matchEthType(Ethernet.TYPE_IPV4);
            selectorBuilder.matchIPDst(prefixToMatch.getIp4Prefix());
            return selectorBuilder;
        }
        // If the prefix is IPv6
        selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
        selectorBuilder.matchIPv6Dst(prefixToMatch.getIp6Prefix());
        return selectorBuilder;
    }

    /**
     * Creates forwarding objectives to punt ARP and NDP packets, to the controller.
     * Furthermore, these are applied only by the master instance. Deferred actions
     * are not cleared such that packets can be flooded in the cross connect use case
     *
     * @param deviceId the switch dpid for the router
     */
    void populateArpNdpPunts(DeviceId deviceId) {
        // We are not the master just skip.
        if (!srManager.mastershipService.isLocalMaster(deviceId)) {
            log.debug("Not installing ARP/NDP punts - not the master for dev:{} ",
                      deviceId);
            return;
        }

        ForwardingObjective fwdObj;
        // We punt all ARP packets towards the controller.
        fwdObj = arpFwdObjective(null, true, ARP_NDP_PRIORITY)
                .add(new ObjectiveContext() {
                    @Override
                    public void onError(Objective objective, ObjectiveError error) {
                        log.warn("Failed to install forwarding objective to punt ARP to {}: {}",
                                 deviceId, error);
                    }
                });
        srManager.flowObjectiveService.forward(deviceId, fwdObj);

        if (isIpv6Configured(deviceId)) {
            // We punt all NDP packets towards the controller.
            ndpFwdObjective(null, true, ARP_NDP_PRIORITY).forEach(builder -> {
                 ForwardingObjective obj = builder.add(new ObjectiveContext() {
                    @Override
                    public void onError(Objective objective, ObjectiveError error) {
                        log.warn("Failed to install forwarding objective to punt NDP to {}: {}",
                                deviceId, error);
                    }
                });
                srManager.flowObjectiveService.forward(deviceId, obj);
            });
        }

        srManager.getPairLocalPort(deviceId).ifPresent(port -> {
            ForwardingObjective pairFwdObj;
            // Do not punt ARP packets from pair port
            pairFwdObj = arpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1)
                    .add(new ObjectiveContext() {
                        @Override
                        public void onError(Objective objective, ObjectiveError error) {
                            log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
                                    deviceId, error);
                        }
                    });
            srManager.flowObjectiveService.forward(deviceId, pairFwdObj);

            if (isIpv6Configured(deviceId)) {
                // Do not punt NDP packets from pair port
                ndpFwdObjective(port, false, PacketPriority.CONTROL.priorityValue() + 1).forEach(builder -> {
                    ForwardingObjective obj = builder.add(new ObjectiveContext() {
                        @Override
                        public void onError(Objective objective, ObjectiveError error) {
                            log.warn("Failed to install forwarding objective to ignore ARP to {}: {}",
                                    deviceId, error);
                        }
                    });
                    srManager.flowObjectiveService.forward(deviceId, obj);
                });

                // Do not forward DAD packets from pair port
                pairFwdObj = dad6FwdObjective(port, PacketPriority.CONTROL.priorityValue() + 2)
                        .add(new ObjectiveContext() {
                            @Override
                            public void onError(Objective objective, ObjectiveError error) {
                                log.warn("Failed to install forwarding objective to drop DAD to {}: {}",
                                        deviceId, error);
                            }
                        });
                srManager.flowObjectiveService.forward(deviceId, pairFwdObj);
            }
        });
    }

    private ForwardingObjective.Builder fwdObjBuilder(TrafficSelector selector,
                                                      TrafficTreatment treatment, int priority) {
        return DefaultForwardingObjective.builder()
                .withPriority(priority)
                .withSelector(selector)
                .fromApp(srManager.appId)
                .withFlag(ForwardingObjective.Flag.VERSATILE)
                .withTreatment(treatment)
                .makePermanent();
    }

    private ForwardingObjective.Builder arpFwdObjective(PortNumber port, boolean punt, int priority) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        sBuilder.matchEthType(TYPE_ARP);
        if (port != null) {
            sBuilder.matchInPort(port);
        }

        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
        if (punt) {
            tBuilder.punt();
        }
        return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
    }

    private Set<ForwardingObjective.Builder> ndpFwdObjective(PortNumber port, boolean punt, int priority) {
        Set<ForwardingObjective.Builder> result = Sets.newHashSet();

        Lists.newArrayList(NEIGHBOR_SOLICITATION, NEIGHBOR_ADVERTISEMENT, ROUTER_SOLICITATION, ROUTER_ADVERTISEMENT)
                .forEach(type -> {
                    TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
                    sBuilder.matchEthType(TYPE_IPV6)
                            .matchIPProtocol(PROTOCOL_ICMP6)
                            .matchIcmpv6Type(type);
                    if (port != null) {
                        sBuilder.matchInPort(port);
                    }

                    TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
                    if (punt) {
                        tBuilder.punt();
                    }

                    result.add(fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority));
                });

        return result;
    }

    private ForwardingObjective.Builder dad6FwdObjective(PortNumber port, int priority) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        sBuilder.matchEthType(TYPE_IPV6)
                .matchIPv6Src(Ip6Address.ZERO.toIpPrefix());
                // TODO CORD-1672 Fix this when OFDPA can distinguish ::/0 and ::/128 correctly
                // .matchIPProtocol(PROTOCOL_ICMP6)
                // .matchIcmpv6Type(NEIGHBOR_SOLICITATION);
        if (port != null) {
            sBuilder.matchInPort(port);
        }

        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
        tBuilder.wipeDeferred();
        return fwdObjBuilder(sBuilder.build(), tBuilder.build(), priority);
    }

    /**
     * Block given prefix in routing table.
     *
     * @param address the address to block
     * @param deviceId switch ID to set the rules
     */
    void populateDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address) {
        updateDefaultRouteBlackhole(deviceId, address, true);
    }

    /**
     * Unblock given prefix in routing table.
     *
     * @param address the address to block
     * @param deviceId switch ID to set the rules
     */
    void removeDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address) {
        updateDefaultRouteBlackhole(deviceId, address, false);
    }

    private void updateDefaultRouteBlackhole(DeviceId deviceId, IpPrefix address, boolean install) {
        try {
            if (srManager.deviceConfiguration.isEdgeDevice(deviceId)) {

                TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
                if (address.isIp4()) {
                    sbuilder.matchIPDst(address);
                    sbuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort());
                } else {
                    sbuilder.matchIPv6Dst(address);
                    sbuilder.matchEthType(EthType.EtherType.IPV6.ethType().toShort());
                }

                TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
                tBuilder.wipeDeferred();

                ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
                fob.withFlag(Flag.SPECIFIC)
                        .withSelector(sbuilder.build())
                        .withTreatment(tBuilder.build())
                        .withPriority(getPriorityFromPrefix(address))
                        .fromApp(srManager.appId)
                        .makePermanent();

                log.debug("{} blackhole forwarding objectives for dev: {}",
                        install ? "Installing" : "Removing", deviceId);
                ObjectiveContext context = new DefaultObjectiveContext(
                        (objective) -> log.debug("Forward for {} {}", deviceId,
                                install ? "installed" : "removed"),
                        (objective, error) -> log.warn("Failed to {} forward for {}: {}",
                                install ? "install" : "remove", deviceId, error));
                if (install) {
                    srManager.flowObjectiveService.forward(deviceId, fob.add(context));
                } else {
                    srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
                }
            }
        } catch (DeviceConfigNotFoundException e) {
            log.info("Not populating blackhole for un-configured device {}", deviceId);
        }

    }

    /**
     * Populates a forwarding objective to send packets that miss other high
     * priority Bridging Table entries to a group that contains all ports of
     * its subnet.
     *
     * @param deviceId switch ID to set the rules
     */
    void populateSubnetBroadcastRule(DeviceId deviceId) {
        srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
            updateSubnetBroadcastRule(deviceId, vlanId, true);
        });
    }

    /**
     * Creates or removes a forwarding objective to broadcast packets to its subnet.
     * @param deviceId switch ID to set the rule
     * @param vlanId vlan ID to specify the subnet
     * @param install true to install the rule, false to revoke the rule
     */
    void updateSubnetBroadcastRule(DeviceId deviceId, VlanId vlanId, boolean install) {
        int nextId = srManager.getVlanNextObjectiveId(deviceId, vlanId);

        if (nextId < 0) {
            log.error("Cannot install vlan {} broadcast rule in dev:{} due"
                              + " to vlanId:{} or nextId:{}", vlanId, deviceId, vlanId, nextId);
            return;
        }

        // Driver should treat objective with MacAddress.NONE as the
        // subnet broadcast rule
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        sbuilder.matchVlanId(vlanId);
        sbuilder.matchEthDst(MacAddress.NONE);

        ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
        fob.withFlag(Flag.SPECIFIC)
                .withSelector(sbuilder.build())
                .nextStep(nextId)
                .withPriority(SegmentRoutingService.FLOOD_PRIORITY)
                .fromApp(srManager.appId)
                .makePermanent();
        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("Vlan broadcast rule for {} populated", vlanId),
                (objective, error) ->
                        log.warn("Failed to populate vlan broadcast rule for {}: {}", vlanId, error));

        if (install) {
            srManager.flowObjectiveService.forward(deviceId, fob.add(context));
        } else {
            srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
        }
    }

    private int getPriorityFromPrefix(IpPrefix prefix) {
        return (prefix.isIp4()) ?
                2000 * prefix.prefixLength() + SegmentRoutingService.MIN_IP_PRIORITY :
                500 * prefix.prefixLength() + SegmentRoutingService.MIN_IP_PRIORITY;
    }

    /**
     * Update Forwarding objective for each host and IP address connected to given port.
     * And create corresponding Simple Next objective if it does not exist.
     * Applied only when populating Forwarding objective
     * @param deviceId switch ID to set the rule
     * @param portNumber port number
     * @param prefix IP prefix of the route
     * @param hostMac MAC address of the next hop
     * @param vlanId Vlan ID of the port
     * @param popVlan true to pop vlan tag in TrafficTreatment
     * @param install true to populate the forwarding objective, false to revoke
     */
    void updateFwdObj(DeviceId deviceId, PortNumber portNumber, IpPrefix prefix, MacAddress hostMac,
                      VlanId vlanId, boolean popVlan, boolean install) {
        ForwardingObjective.Builder fob;
        TrafficSelector.Builder sbuilder = buildIpSelectorFromIpPrefix(prefix);
        MacAddress deviceMac;
        try {
            deviceMac = config.getDeviceMac(deviceId);
        } catch (DeviceConfigNotFoundException e) {
            log.warn(e.getMessage() + " Aborting updateFwdObj.");
            return;
        }

        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
        tbuilder.deferred()
                .setEthDst(hostMac)
                .setEthSrc(deviceMac)
                .setOutput(portNumber);

        TrafficSelector.Builder mbuilder = DefaultTrafficSelector.builder();

        if (!popVlan) {
            tbuilder.setVlanId(vlanId);
        } else {
            mbuilder.matchVlanId(vlanId);
        }

        // if the objective is to revoke an existing rule, and for some reason
        // the next-objective does not exist, then a new one should not be created
        int portNextObjId = srManager.getPortNextObjectiveId(deviceId, portNumber,
                                                             tbuilder.build(), mbuilder.build(), install);
        if (portNextObjId == -1) {
            // Warning log will come from getPortNextObjective method
            return;
        }

        fob = DefaultForwardingObjective.builder().withSelector(sbuilder.build())
                .nextStep(portNextObjId).fromApp(srManager.appId).makePermanent()
                .withPriority(getPriorityFromPrefix(prefix)).withFlag(ForwardingObjective.Flag.SPECIFIC);

        ObjectiveContext context = new DefaultObjectiveContext(
                (objective) -> log.debug("IP rule for route {} {}", prefix, install ? "installed" : "revoked"),
                (objective, error) ->
                        log.warn("Failed to {} IP rule for route {}: {}",
                                 install ? "install" : "revoke", prefix, error));
        srManager.flowObjectiveService.forward(deviceId, install ? fob.add(context) : fob.remove(context));

        if (!install) {
            DefaultGroupHandler grpHandler = srManager.getGroupHandler(deviceId);
            if (grpHandler == null) {
                log.warn("updateFwdObj: groupHandler for device {} not found", deviceId);
            } else {
                // Remove L3UG for the given port and host
                grpHandler.removeGroupFromPort(portNumber, tbuilder.build(), mbuilder.build());
            }
        }
    }

    /**
     * Checks if there is other enabled port within the given VLAN on the given device.
     *
     * @param deviceId device ID
     * @param vlanId VLAN ID
     * @return true if there is no more port enabled within the given VLAN on the given device
     */
    boolean noMoreEnabledPort(DeviceId deviceId, VlanId vlanId) {
        Set<ConnectPoint> enabledPorts = srManager.deviceService.getPorts(deviceId).stream()
                .filter(Port::isEnabled)
                .map(port -> new ConnectPoint(port.element().id(), port.number()))
                .collect(Collectors.toSet());

        return enabledPorts.stream().noneMatch(cp ->
            // Given vlanId is included in the vlan-tagged configuration
            srManager.interfaceService.getTaggedVlanId(cp).contains(vlanId) ||
            // Given vlanId is INTERNAL_VLAN and the interface is not configured
            (srManager.interfaceService.getTaggedVlanId(cp).isEmpty() && srManager.getInternalVlanId(cp) == null &&
                    vlanId.equals(srManager.getDefaultInternalVlan())) ||
            // interface is configured and either vlan-untagged or vlan-native matches given vlanId
            (srManager.getInternalVlanId(cp) != null && srManager.getInternalVlanId(cp).equals(vlanId))
        );
    }

    /**
     * Returns a forwarding objective builder for egress forwarding rules.
     * <p>
     * The forwarding objective installs flow rules to egress pipeline to push
     * two vlan headers with given inner, outer vlan ids and outer tpid.
     *
     * @param portNumber port where the next hop attaches to
     * @param dummyVlanId vlan ID of the packet to match
     * @param innerVlan inner vlan ID of the next hop
     * @param outerVlan outer vlan ID of the next hop
     * @param outerTpid outer TPID of the next hop
     * @return forwarding objective builder
     */
    private ForwardingObjective.Builder egressFwdObjBuilder(PortNumber portNumber, VlanId dummyVlanId,
                                                            VlanId innerVlan, VlanId outerVlan, EthType outerTpid) {
        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
        sbuilder.matchVlanId(dummyVlanId);
        TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
        tbuilder.setOutput(portNumber).setVlanId(innerVlan);

        if (outerTpid.equals(EthType.EtherType.QINQ.ethType())) {
            tbuilder.pushVlan(outerTpid);
        } else {
            tbuilder.pushVlan();
        }

        tbuilder.setVlanId(outerVlan);
        return DefaultForwardingObjective.builder()
                .withSelector(sbuilder.build())
                .withTreatment(tbuilder.build())
                .fromApp(srManager.appId)
                .makePermanent()
                .withPriority(DEFAULT_PRIORITY)
                .withFlag(ForwardingObjective.Flag.EGRESS);
    }

    /**
     * Populates IP rules for a route that has double-tagged next hop.
     *
     * @param deviceId device ID of the device that next hop attaches to
     * @param prefix IP prefix of the route
     * @param hostMac MAC address of the next hop
     * @param dummyVlan Dummy Vlan ID allocated for this route
     * @param innerVlan inner Vlan ID of the next hop
     * @param outerVlan outer Vlan ID of the next hop
     * @param outerTpid outer TPID of the next hop
     * @param outPort port where the next hop attaches to
     */
    void populateDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac, VlanId dummyVlan,
                                   VlanId innerVlan, VlanId outerVlan, EthType outerTpid, PortNumber outPort) {
        ForwardingObjective.Builder fwdBuilder;
        log.debug("Populate direct routing entry for double-tagged host route {} at {}:{}",
                  prefix, deviceId, outPort);

        ForwardingObjective.Builder egressFwdBuilder = egressFwdObjBuilder(
                outPort, dummyVlan, innerVlan, outerVlan, outerTpid);
        DefaultObjectiveContext egressFwdContext = new DefaultObjectiveContext(
                objective -> log.debug("Egress rule for IP {} is populated", prefix.address()),
                (objective, error) -> {
                    log.warn("Failed to populate egress rule for IP {}: {}", prefix.address(), error);
                    srManager.dummyVlanIdStore().remove(new DummyVlanIdStoreKey(
                            new ConnectPoint(deviceId, outPort), prefix.address()
                    ));
                });
        try {
            fwdBuilder = routingFwdObjBuilder(deviceId, prefix, hostMac, dummyVlan, outPort, false, false);
        } catch (DeviceConfigNotFoundException e) {
            log.error(e.getMessage() + " Aborting populateDoubleTaggedRoute");
            return;
        }
        if (fwdBuilder == null) {
            log.error("Aborting double-tagged host routing table entry due to error for dev:{} route:{}",
                     deviceId, prefix);
            return;
        }

        // Egress forwarding objective should be installed after the nextObjective for the output port is installed.
        // Installation of routingFwdObj will ensure the installation of the nextObjective.
        int nextId = fwdBuilder.add().nextId();
        DefaultObjectiveContext context = new DefaultObjectiveContext(objective -> {
            log.debug("Direct routing rule for double-tagged host route {} populated. nextId={}", prefix, nextId);
            srManager.flowObjectiveService.forward(deviceId, egressFwdBuilder.add(egressFwdContext));
        }, (objective, error) ->
            log.warn("Failed to populate direct routing rule for double-tagged host route {}: {}", prefix, error)
        );
        srManager.flowObjectiveService.forward(deviceId, fwdBuilder.add(context));
        rulePopulationCounter.incrementAndGet();
    }

    /**
     * Revokes IP rules for a route that has double-tagged next hop.
     *
     * @param deviceId device ID of the device that next hop attaches to
     * @param prefix IP prefix of the route
     * @param hostMac MAC address of the next hop
     * @param hostVlan Vlan ID of the next hop
     * @param innerVlan inner Vlan ID of the next hop
     * @param outerVlan outer Vlan ID of the next hop
     * @param outerTpid outer TPID of the next hop
     * @param outPort port where the next hop attaches to
     */
    void revokeDoubleTaggedRoute(DeviceId deviceId, IpPrefix prefix, MacAddress hostMac,
                                 VlanId hostVlan, VlanId innerVlan, VlanId outerVlan,
                                 EthType outerTpid, PortNumber outPort) {
        revokeRoute(deviceId, prefix, hostMac, hostVlan, outPort, false);

        DummyVlanIdStoreKey key = new DummyVlanIdStoreKey(
                new ConnectPoint(deviceId, outPort), prefix.address());
        VlanId dummyVlanId = srManager.dummyVlanIdStore().get(key);
        if (dummyVlanId == null) {
            log.warn("Failed to retrieve dummy VLAN ID for {}/{} and {}",
                     deviceId, outPort, prefix.address());
            return;
        }
        ForwardingObjective.Builder fob = egressFwdObjBuilder(
                outPort, dummyVlanId, innerVlan, outerVlan, outerTpid);
        DefaultObjectiveContext context = new DefaultObjectiveContext(objective -> {
            log.debug("Egress rule for IP {} revoked", prefix.address());
            srManager.dummyVlanIdStore().remove(key);
        }, (objective, error) -> {
            log.warn("Failed to revoke egress rule for IP {}: {}", prefix.address(), error);
        });
        srManager.flowObjectiveService.forward(deviceId, fob.remove(context));
    }

    /**
     * Checks whether the specified port has IP configuration or not.
     *
     * @param cp ConnectPoint to check the existance of IP configuration
     * @return true if the port has IP configuration; false otherwise.
     */
    private boolean hasIPConfiguration(ConnectPoint cp) {
        Set<Interface> interfaces = srManager.interfaceService.getInterfacesByPort(cp);
        return interfaces.stream().anyMatch(intf -> intf.ipAddressesList().size() > 0);
    }

    /**
     * Updates filtering rules for unconfigured ports on all devices for which
     * this controller instance is master.
     *
     * @param pushVlan true if the filtering rule requires a push vlan action
     * @param oldVlanId the vlanId to be removed
     * @param newVlanId the vlanId to be added
     */
    void updateSpecialVlanFilteringRules(boolean pushVlan, VlanId oldVlanId,
                                         VlanId newVlanId) {
        for (Device dev : srManager.deviceService.getAvailableDevices()) {
            if (srManager.mastershipService.isLocalMaster(dev.id())) {
                for (Port p : srManager.deviceService.getPorts(dev.id())) {
                    if (!hasIPConfiguration(new ConnectPoint(dev.id(), p.number()))
                            && p.isEnabled()) {
                        updateSinglePortFilters(dev.id(), p.number(), pushVlan,
                                                oldVlanId, false);
                        updateSinglePortFilters(dev.id(), p.number(), pushVlan,
                                                newVlanId, true);
                    }
                }
            }
        }
    }

    private boolean isIpv6Configured(DeviceId deviceId) {
        boolean isIpv6Configured;
        try {
            isIpv6Configured = (config.getRouterIpv6(deviceId) != null);
        } catch (DeviceConfigNotFoundException e) {
            isIpv6Configured = false;
        }
        return isIpv6Configured;
    }
}
