diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/manager/impl/EvpnManager.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/manager/impl/EvpnManager.java
new file mode 100755
index 0000000..7f7314b
--- /dev/null
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/manager/impl/EvpnManager.java
@@ -0,0 +1,1132 @@
+/*
+ * Copyright 2017-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.evpnopenflow.manager.impl;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Sets;
+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.osgi.DefaultServiceDirectory;
+import org.onlab.packet.EthType;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.evpnopenflow.manager.EvpnService;
+import org.onosproject.evpnopenflow.rsc.VpnAfConfig;
+import org.onosproject.evpnopenflow.rsc.VpnInstance;
+import org.onosproject.evpnopenflow.rsc.VpnInstanceId;
+import org.onosproject.evpnopenflow.rsc.VpnPort;
+import org.onosproject.evpnopenflow.rsc.VpnPortId;
+import org.onosproject.evpnopenflow.rsc.baseport.BasePortService;
+import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigEvent;
+import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigListener;
+import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigService;
+import org.onosproject.evpnopenflow.rsc.vpninstance.VpnInstanceService;
+import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortEvent;
+import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortListener;
+import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortService;
+import org.onosproject.gluon.rsc.GluonConfig;
+import org.onosproject.incubator.net.resource.label.LabelResource;
+import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
+import org.onosproject.incubator.net.resource.label.LabelResourceId;
+import org.onosproject.incubator.net.resource.label.LabelResourceService;
+import org.onosproject.incubator.net.routing.EvpnInstanceName;
+import org.onosproject.incubator.net.routing.EvpnInstanceNextHop;
+import org.onosproject.incubator.net.routing.EvpnInstancePrefix;
+import org.onosproject.incubator.net.routing.EvpnInstanceRoute;
+import org.onosproject.incubator.net.routing.EvpnNextHop;
+import org.onosproject.incubator.net.routing.EvpnRoute;
+import org.onosproject.incubator.net.routing.EvpnRoute.Source;
+import org.onosproject.incubator.net.routing.EvpnRouteAdminService;
+import org.onosproject.incubator.net.routing.EvpnRouteEvent;
+import org.onosproject.incubator.net.routing.EvpnRouteListener;
+import org.onosproject.incubator.net.routing.EvpnRouteService;
+import org.onosproject.incubator.net.routing.EvpnRouteSet;
+import org.onosproject.incubator.net.routing.EvpnRouteStore;
+import org.onosproject.incubator.net.routing.Label;
+import org.onosproject.incubator.net.routing.RouteDistinguisher;
+import org.onosproject.incubator.net.routing.VpnRouteTarget;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+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.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.Objective.Operation;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type.Reference;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ARP_PRIORITY;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ARP_RESPONSE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BASEPORT;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BGP_EVPN_ROUTE_DELETE_START;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BGP_EVPN_ROUTE_UPDATE_START;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BOTH;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANNOT_FIND_TUNNEL_PORT_DEVICE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANT_FIND_CONTROLLER_DEVICE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANT_FIND_VPN_INSTANCE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CANT_FIND_VPN_PORT;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DELETE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_OPENFLOW_START;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_OPENFLOW_STOP;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EXPORT_EXTCOMMUNITY;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.FAILED_TO_SET_TUNNEL_DST;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.GET_PRIVATE_LABEL;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.HOST_DETECT;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.HOST_VANISHED;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IFACEID;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IFACEID_OF_HOST_IS_NULL;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IMPORT_EXTCOMMUNITY;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INVALID_EVENT_RECEIVED;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INVALID_ROUTE_TARGET_TYPE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INVALID_TARGET_RECEIVED;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.MPLS_OUT_FLOWS;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.NETWORK_CONFIG_EVENT_IS_RECEIVED;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.NOT_MASTER_FOR_SPECIFIC_DEVICE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RELEASE_LABEL_FAILED;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_ADD_ARP_RULES;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_REMOVE_ARP_RULES;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SET;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SLASH;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SWITCH_CHANNEL_ID;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.TUNNEL_DST;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.UPDATE;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_AF_TARGET;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_TARGET;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_BIND;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_TARGET;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_UNBIND;
+import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VXLAN;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of the EVPN service.
+ */
+@Component(immediate = true)
+@Service
+public class EvpnManager implements EvpnService {
+    private final Logger log = getLogger(getClass());
+    private static final EthType.EtherType ARP_TYPE = EthType.EtherType.ARP;
+
+    protected ApplicationId appId;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected HostService hostService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected EvpnRouteService evpnRouteService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected EvpnRouteStore evpnRouteStore;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected EvpnRouteAdminService evpnRouteAdminService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected MastershipService mastershipService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LabelResourceAdminService labelAdminService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LabelResourceService labelService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected VpnInstanceService vpnInstanceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected FlowObjectiveService flowObjectiveService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DriverService driverService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected VpnPortService vpnPortService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected VpnAfConfigService vpnAfConfigService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigService configService;
+
+    public Set<EvpnInstanceRoute> evpnInstanceRoutes = new HashSet<>();
+    private final HostListener hostListener = new InnerHostListener();
+    private final VpnPortListener vpnPortListner = new InnerVpnPortListener();
+    private final VpnAfConfigListener vpnAfConfigListener = new
+            InnerVpnAfConfigListener();
+    private final InternalRouteEventListener routeListener = new
+            InternalRouteEventListener();
+
+    private final NetworkConfigListener configListener = new
+            InternalNetworkConfigListener();
+
+    @Activate
+    public void activate() {
+        appId = coreService.registerApplication(APP_ID);
+        hostService.addListener(hostListener);
+        vpnPortService.addListener(vpnPortListner);
+        vpnAfConfigService.addListener(vpnAfConfigListener);
+        configService.addListener(configListener);
+        evpnRouteService.addListener(routeListener);
+
+        labelAdminService
+                .createGlobalPool(LabelResourceId.labelResourceId(1),
+                                  LabelResourceId.labelResourceId(1000));
+        log.info(EVPN_OPENFLOW_START);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        hostService.removeListener(hostListener);
+        vpnPortService.removeListener(vpnPortListner);
+        vpnAfConfigService.removeListener(vpnAfConfigListener);
+        configService.removeListener(configListener);
+        log.info(EVPN_OPENFLOW_STOP);
+    }
+
+    @Override
+    public void onBgpEvpnRouteUpdate(EvpnRoute route) {
+        if (EvpnRoute.Source.LOCAL.equals(route.source())) {
+            return;
+        }
+        log.info(BGP_EVPN_ROUTE_UPDATE_START, route);
+        // deal with public route and transfer to private route
+        if (vpnInstanceService.getInstances().isEmpty()) {
+            log.info("unable to get instnaces from vpninstance");
+            return;
+        }
+
+        vpnInstanceService.getInstances().forEach(vpnInstance -> {
+            log.info("got instnaces from vpninstance but not entered here");
+            List<VpnRouteTarget> vpnImportRouteRt = new
+                    LinkedList<>(vpnInstance.getImportRouteTargets());
+            List<VpnRouteTarget> expRt = route.exportRouteTarget();
+            List<VpnRouteTarget> similar = new LinkedList<>(expRt);
+            similar.retainAll(vpnImportRouteRt);
+
+            if (!similar.isEmpty()) {
+                EvpnInstancePrefix evpnPrefix = EvpnInstancePrefix
+                        .evpnPrefix(route.prefixMac(), route.prefixIp());
+
+                EvpnInstanceNextHop evpnNextHop = EvpnInstanceNextHop
+                        .evpnNextHop(route.ipNextHop(), route.label());
+
+                EvpnInstanceRoute evpnPrivateRoute = new
+                        EvpnInstanceRoute(vpnInstance.vpnInstanceName(),
+                                          route.routeDistinguisher(),
+                                          vpnImportRouteRt,
+                                          route.exportRouteTarget(),
+                                          evpnPrefix,
+                                          evpnNextHop,
+                                          route.prefixIp(),
+                                          route.ipNextHop(),
+                                          route.label());
+
+                //update route in route subsystem
+                //TODO: added by shahid
+                evpnInstanceRoutes.add(evpnPrivateRoute);
+
+            }
+        });
+
+        deviceService.getAvailableDevices(Device.Type.SWITCH)
+                .forEach(device -> {
+                    log.info("switch device is found");
+                    Set<Host> hosts = getHostsByVpn(device, route);
+                    for (Host h : hosts) {
+                        addArpFlows(device.id(),
+                                    route,
+                                    Objective.Operation.ADD,
+                                    h);
+                        ForwardingObjective.Builder objective =
+                                getMplsOutBuilder(device.id(),
+                                                  route,
+                                                  h);
+                        log.info(MPLS_OUT_FLOWS, h);
+                        flowObjectiveService.forward(device.id(),
+                                                     objective.add());
+                    }
+                });
+        log.info("no switch device is found");
+    }
+
+    @Override
+    public void onBgpEvpnRouteDelete(EvpnRoute route) {
+        if (EvpnRoute.Source.LOCAL.equals(route.source())) {
+            return;
+        }
+        log.info(BGP_EVPN_ROUTE_DELETE_START, route);
+        // deal with public route deleted and transfer to private route
+        vpnInstanceService.getInstances().forEach(vpnInstance -> {
+            List<VpnRouteTarget> vpnRouteRt = new
+                    LinkedList<>(vpnInstance.getImportRouteTargets());
+            List<VpnRouteTarget> localRt = route.exportRouteTarget();
+            List<VpnRouteTarget> similar = new LinkedList<>(localRt);
+            similar.retainAll(vpnRouteRt);
+
+            if (!similar.isEmpty()) {
+                EvpnInstancePrefix evpnPrefix = EvpnInstancePrefix
+                        .evpnPrefix(route.prefixMac(), route.prefixIp());
+
+                EvpnInstanceNextHop evpnNextHop = EvpnInstanceNextHop
+                        .evpnNextHop(route.ipNextHop(), route.label());
+
+                EvpnInstanceRoute evpnPrivateRoute = new
+                        EvpnInstanceRoute(vpnInstance.vpnInstanceName(),
+                                          route.routeDistinguisher(),
+                                          vpnRouteRt,
+                                          route.exportRouteTarget(),
+                                          evpnPrefix,
+                                          evpnNextHop,
+                                          route.prefixIp(),
+                                          route.ipNextHop(),
+                                          route.label());
+                //TODO: Added by Shahid
+                //evpnRouteAdminService.withdraw(Sets.newHashSet
+                //       (evpnPrivateRoute));
+
+            }
+        });
+        deviceService.getAvailableDevices(Device.Type.SWITCH)
+                .forEach(device -> {
+                    Set<Host> hosts = getHostsByVpn(device, route);
+                    for (Host h : hosts) {
+                        addArpFlows(device.id(),
+                                    route,
+                                    Objective.Operation.REMOVE,
+                                    h);
+                        ForwardingObjective.Builder objective
+                                = getMplsOutBuilder(device.id(),
+                                                    route,
+                                                    h);
+                        flowObjectiveService.forward(device.id(),
+                                                     objective.remove());
+                    }
+                });
+    }
+
+    private void addArpFlows(DeviceId deviceId,
+                             EvpnRoute route,
+                             Operation type,
+                             Host host) {
+        DriverHandler handler = driverService.createHandler(deviceId);
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(ARP_TYPE.ethType().toShort())
+                .matchArpTpa(route.prefixIp().address().getIp4Address())
+                .matchInPort(host.location().port()).build();
+
+        ExtensionTreatmentResolver resolver = handler
+                .behaviour(ExtensionTreatmentResolver.class);
+        ExtensionTreatment ethSrcToDst = resolver
+                .getExtensionInstruction(ExtensionTreatmentType
+                                                 .ExtensionTreatmentTypes
+                                                 .NICIRA_MOV_ETH_SRC_TO_DST
+                                                 .type());
+        ExtensionTreatment arpShaToTha = resolver
+                .getExtensionInstruction(ExtensionTreatmentType
+                                                 .ExtensionTreatmentTypes
+                                                 .NICIRA_MOV_ARP_SHA_TO_THA
+                                                 .type());
+        ExtensionTreatment arpSpaToTpa = resolver
+                .getExtensionInstruction(ExtensionTreatmentType
+                                                 .ExtensionTreatmentTypes
+                                                 .NICIRA_MOV_ARP_SPA_TO_TPA
+                                                 .type());
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .extension(ethSrcToDst, deviceId).setEthSrc(route.prefixMac())
+                .setArpOp(ARP_RESPONSE).extension(arpShaToTha, deviceId)
+                .extension(arpSpaToTpa, deviceId).setArpSha(route.prefixMac())
+                .setArpSpa(route.prefixIp().address().getIp4Address())
+                .setOutput(PortNumber.IN_PORT)
+                .build();
+
+        ForwardingObjective.Builder objective = DefaultForwardingObjective
+                .builder().withTreatment(treatment).withSelector(selector)
+                .fromApp(appId).withFlag(ForwardingObjective.Flag.SPECIFIC)
+                .withPriority(ARP_PRIORITY);
+        if (type.equals(Objective.Operation.ADD)) {
+            log.info(ROUTE_ADD_ARP_RULES);
+            flowObjectiveService.forward(deviceId, objective.add());
+        } else {
+            log.info(ROUTE_REMOVE_ARP_RULES);
+            flowObjectiveService.forward(deviceId, objective.remove());
+        }
+    }
+
+    private Set<Host> getHostsByVpn(Device device, EvpnRoute route) {
+        Set<Host> vpnHosts = Sets.newHashSet();
+        Set<Host> hosts = hostService.getConnectedHosts(device.id());
+        for (Host h : hosts) {
+            String ifaceId = h.annotations().value(IFACEID);
+            if (!vpnPortService.exists(VpnPortId.vpnPortId(ifaceId))) {
+                continue;
+            }
+
+            VpnPort vpnPort = vpnPortService
+                    .getPort(VpnPortId.vpnPortId(ifaceId));
+            VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
+
+            VpnInstance vpnInstance = vpnInstanceService
+                    .getInstance(vpnInstanceId);
+
+            List<VpnRouteTarget> expRt = route.exportRouteTarget();
+            List<VpnRouteTarget> similar = new LinkedList<>(expRt);
+            similar.retainAll(vpnInstance.getImportRouteTargets());
+            //TODO: currently checking for RT comparision.
+            //TODO: Need to check about RD comparision is really required.
+            //if (route.routeDistinguisher()
+            //.equals(vpnInstance.routeDistinguisher())) {
+            if (!similar.isEmpty()) {
+                vpnHosts.add(h);
+            }
+        }
+        return vpnHosts;
+    }
+
+    private ForwardingObjective.Builder getMplsOutBuilder(DeviceId deviceId,
+                                                          EvpnRoute route,
+                                                          Host h) {
+        DriverHandler handler = driverService.createHandler(deviceId);
+        ExtensionTreatmentResolver resolver = handler
+                .behaviour(ExtensionTreatmentResolver.class);
+        ExtensionTreatment treatment = resolver
+                .getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+        try {
+            treatment.setPropertyValue(TUNNEL_DST, route.ipNextHop());
+        } catch (Exception e) {
+            log.error(FAILED_TO_SET_TUNNEL_DST, deviceId);
+        }
+        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
+        builder.extension(treatment, deviceId);
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchInPort(h.location().port()).matchEthSrc(h.mac())
+                .matchEthDst(route.prefixMac()).build();
+
+        TrafficTreatment build = builder.pushMpls()
+                .setMpls(MplsLabel.mplsLabel(route.label().getLabel()))
+                .setOutput(getTunnlePort(deviceId)).build();
+
+        return DefaultForwardingObjective
+                .builder().withTreatment(build).withSelector(selector)
+                .fromApp(appId).withFlag(ForwardingObjective.Flag.SPECIFIC)
+                .withPriority(60000);
+
+    }
+
+    private ForwardingObjective.Builder getMplsInBuilder(DeviceId deviceId,
+                                                         Host host,
+                                                         Label label) {
+        TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchInPort(getTunnlePort(deviceId))
+                .matchEthType(EthType.EtherType.MPLS_UNICAST.ethType()
+                                      .toShort())
+                .matchMplsBos(true)
+                .matchMplsLabel(MplsLabel.mplsLabel(label.getLabel())).build();
+        TrafficTreatment treatment = builder.popMpls(EthType
+                                                             .EtherType
+                                                             .IPV4.ethType())
+                .setOutput(host.location().port()).build();
+        return DefaultForwardingObjective
+                .builder().withTreatment(treatment).withSelector(selector)
+                .fromApp(appId).withFlag(ForwardingObjective.Flag.SPECIFIC)
+                .withPriority(60000);
+    }
+
+    /**
+     * Get local tunnel ports.
+     *
+     * @param ports Iterable of Port
+     * @return Collection of PortNumber
+     */
+    private Collection<PortNumber> getLocalTunnelPorts(Iterable<Port>
+                                                               ports) {
+        Collection<PortNumber> localTunnelPorts = new ArrayList<>();
+        if (ports != null) {
+            log.info("port value is not null {}", ports);
+            Sets.newHashSet(ports).stream()
+                    .filter(p -> !p.number().equals(PortNumber.LOCAL))
+                    .forEach(p -> {
+                        log.info("number is not matched but no vxlan port");
+                        if (p.annotations().value(AnnotationKeys.PORT_NAME)
+                                .startsWith(VXLAN)) {
+                            localTunnelPorts.add(p.number());
+                        }
+                    });
+        }
+        return localTunnelPorts;
+    }
+
+    private PortNumber getTunnlePort(DeviceId deviceId) {
+        Iterable<Port> ports = deviceService.getPorts(deviceId);
+        Collection<PortNumber> localTunnelPorts = getLocalTunnelPorts(ports);
+        if (localTunnelPorts.isEmpty()) {
+            log.error(CANNOT_FIND_TUNNEL_PORT_DEVICE, deviceId);
+            return null;
+        }
+        return localTunnelPorts.iterator().next();
+    }
+
+    private void setFlows(DeviceId deviceId, Host host, Label label,
+                          List<VpnRouteTarget> rtImport,
+                          Operation type) {
+        log.info("Set the flows to OVS");
+        ForwardingObjective.Builder objective = getMplsInBuilder(deviceId,
+                                                                 host,
+                                                                 label);
+        if (type.equals(Objective.Operation.ADD)) {
+            flowObjectiveService.forward(deviceId, objective.add());
+        } else {
+            flowObjectiveService.forward(deviceId, objective.remove());
+        }
+
+        // download remote flows if and only routes are present.
+        evpnRouteStore.getRouteTables().forEach(routeTableId -> {
+            Collection<EvpnRouteSet> routes
+                    = evpnRouteStore.getRoutes(routeTableId);
+            if (routes != null) {
+                routes.forEach(route -> {
+                    Collection<EvpnRoute> evpnRoutes = route.routes();
+                    for (EvpnRoute evpnRoute : evpnRoutes) {
+                        EvpnRoute evpnRouteTem = evpnRoute;
+                        Set<Host> hostByMac = hostService
+                                .getHostsByMac(evpnRouteTem
+                                                       .prefixMac());
+
+                        if (!hostByMac.isEmpty()
+                                || (!(compareLists(rtImport, evpnRouteTem
+                                .exportRouteTarget())))) {
+                            log.info("Route target import/export is not matched");
+                            continue;
+                        }
+                        log.info("Set the ARP flows");
+                        addArpFlows(deviceId, evpnRouteTem, type, host);
+                        ForwardingObjective.Builder build = getMplsOutBuilder(deviceId,
+                                                                              evpnRouteTem,
+                                                                              host);
+                        log.info("Set the MPLS  flows");
+                        if (type.equals(Objective.Operation.ADD)) {
+                            flowObjectiveService.forward(deviceId, build.add());
+                        } else {
+                            flowObjectiveService.forward(deviceId, build.remove());
+                        }
+                    }
+                });
+            }
+        });
+    }
+
+    /**
+     * comparison for tow lists.
+     *
+     * @param list1 import list
+     * @param list2 export list
+     * @return true or false
+     */
+    public static boolean compareLists(List<VpnRouteTarget> list1,
+                                       List<VpnRouteTarget> list2) {
+        if (list1 == null && list2 == null) {
+            return true;
+        }
+
+        if (list1 != null && list2 != null) {
+            if (list1.size() == list2.size()) {
+                for (VpnRouteTarget li1Long : list1) {
+                    boolean isEqual = false;
+                    for (VpnRouteTarget li2Long : list2) {
+                        if (li1Long.equals(li2Long)) {
+                            isEqual = true;
+                            break;
+                        }
+                    }
+                    if (!isEqual) {
+                        return false;
+                    }
+                }
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public void onHostDetected(Host host) {
+        log.info(HOST_DETECT, host);
+        DeviceId deviceId = host.location().deviceId();
+        if (!mastershipService.isLocalMaster(deviceId)) {
+            log.info(NOT_MASTER_FOR_SPECIFIC_DEVICE);
+            return;
+        }
+
+        String ifaceId = host.annotations().value(IFACEID);
+        if (ifaceId == null) {
+            log.error(IFACEID_OF_HOST_IS_NULL);
+            return;
+        }
+        VpnPortId vpnPortId = VpnPortId.vpnPortId(ifaceId);
+        // Get VPN port id from EVPN app store
+        if (!vpnPortService.exists(vpnPortId)) {
+            log.info(CANT_FIND_VPN_PORT, ifaceId);
+            return;
+        }
+
+        VpnPort vpnPort = vpnPortService.getPort(vpnPortId);
+        VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
+        if (!vpnInstanceService.exists(vpnInstanceId)) {
+            log.info(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
+            return;
+        }
+
+        Label privateLabel = applyLabel();
+        // create private route and get label
+        setPrivateRoute(host, vpnInstanceId, privateLabel,
+                        Objective.Operation.ADD);
+        VpnInstance vpnInstance = vpnInstanceService.getInstance(vpnInstanceId);
+
+        List<VpnRouteTarget> rtImport
+                = new LinkedList<>(vpnInstance.getImportRouteTargets());
+        List<VpnRouteTarget> rtExport
+                = new LinkedList<>(vpnInstance.getExportRouteTargets());
+        //download flows
+        setFlows(deviceId, host, privateLabel, rtImport,
+                 Objective.Operation.ADD);
+    }
+
+    /**
+     * update or withdraw evpn route from route admin service.
+     *
+     * @param host          host
+     * @param vpnInstanceId vpn instance id
+     * @param privateLabel  private label
+     * @param type          operation type
+     */
+    private void setPrivateRoute(Host host, VpnInstanceId vpnInstanceId,
+                                 Label privateLabel,
+                                 Operation type) {
+        DeviceId deviceId = host.location().deviceId();
+        Device device = deviceService.getDevice(deviceId);
+        VpnInstance vpnInstance = vpnInstanceService.getInstance(vpnInstanceId);
+        RouteDistinguisher rd = vpnInstance.routeDistinguisher();
+        Set<VpnRouteTarget> importRouteTargets
+                = vpnInstance.getImportRouteTargets();
+        Set<VpnRouteTarget> exportRouteTargets
+                = vpnInstance.getExportRouteTargets();
+        EvpnInstanceName instanceName = vpnInstance.vpnInstanceName();
+        String url = device.annotations().value(SWITCH_CHANNEL_ID);
+        String controllerIp = url.substring(0, url.lastIndexOf(":"));
+
+        if (controllerIp == null) {
+            log.error(CANT_FIND_CONTROLLER_DEVICE, device.id().toString());
+            return;
+        }
+        IpAddress ipAddress = IpAddress.valueOf(controllerIp);
+        // create private route
+        EvpnInstanceNextHop evpnNextHop = EvpnInstanceNextHop
+                .evpnNextHop(ipAddress, privateLabel);
+        EvpnInstancePrefix evpnPrefix = EvpnInstancePrefix
+                .evpnPrefix(host.mac(), IpPrefix.valueOf(host.ipAddresses()
+                                                                 .iterator()
+                                                                 .next()
+                                                                 .getIp4Address(), 32));
+        EvpnInstanceRoute evpnPrivateRoute
+                = new EvpnInstanceRoute(instanceName,
+                                        rd,
+                                        new LinkedList<>(importRouteTargets),
+                                        new LinkedList<>(exportRouteTargets),
+                                        evpnPrefix,
+                                        evpnNextHop,
+                                        IpPrefix.valueOf(host.ipAddresses()
+                                                                 .iterator()
+                                                                 .next()
+                                                                 .getIp4Address(), 32),
+                                        ipAddress,
+                                        privateLabel);
+
+        // change to public route
+        EvpnRoute evpnRoute
+                = new EvpnRoute(Source.LOCAL,
+                                host.mac(),
+                                IpPrefix.valueOf(host.ipAddresses()
+                                                         .iterator()
+                                                         .next()
+                                                         .getIp4Address(), 32),
+                                ipAddress,
+                                rd,
+                                new LinkedList<>(importRouteTargets),
+                                new LinkedList<>(exportRouteTargets),
+                                privateLabel);
+        if (type.equals(Objective.Operation.ADD)) {
+            //evpnRouteAdminService.update(Sets.newHashSet(evpnPrivateRoute));
+            evpnInstanceRoutes.add(evpnPrivateRoute);
+            evpnRouteAdminService.update(Sets.newHashSet(evpnRoute));
+
+        } else {
+            //evpnRouteAdminService.withdraw(Sets.newHashSet(evpnPrivateRoute));
+            evpnInstanceRoutes.remove(evpnPrivateRoute);
+            evpnRouteAdminService.withdraw(Sets.newHashSet(evpnRoute));
+        }
+    }
+
+    /**
+     * Generate the label for evpn route from global pool.
+     */
+    private Label applyLabel() {
+        Collection<LabelResource> privateLabels = labelService
+                .applyFromGlobalPool(1);
+        Label privateLabel = Label.label(0);
+        if (!privateLabels.isEmpty()) {
+            privateLabel = Label.label(Integer.parseInt(
+                    privateLabels.iterator().next()
+                            .labelResourceId().toString()));
+        }
+        log.info(GET_PRIVATE_LABEL, privateLabel);
+        return privateLabel;
+    }
+
+    @Override
+    public void onHostVanished(Host host) {
+        log.info(HOST_VANISHED, host);
+        DeviceId deviceId = host.location().deviceId();
+        if (!mastershipService.isLocalMaster(deviceId)) {
+            return;
+        }
+        String ifaceId = host.annotations().value(IFACEID);
+        if (ifaceId == null) {
+            log.error(IFACEID_OF_HOST_IS_NULL);
+            return;
+        }
+        // Get info from Gluon Shim
+        VpnPort vpnPort = vpnPortService.getPort(VpnPortId.vpnPortId(ifaceId));
+        VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
+        if (!vpnInstanceService.exists(vpnInstanceId)) {
+            log.info(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
+            return;
+        }
+        VpnInstance vpnInstance = vpnInstanceService.getInstance(vpnInstanceId);
+
+        Label label = releaseLabel(vpnInstance, host);
+        // create private route and get label
+        setPrivateRoute(host, vpnInstanceId, label, Objective.Operation.REMOVE);
+        // download flows
+        List<VpnRouteTarget> rtImport
+                = new LinkedList<>(vpnInstance.getImportRouteTargets());
+        List<VpnRouteTarget> rtExport
+                = new LinkedList<>(vpnInstance.getExportRouteTargets());
+        setFlows(deviceId, host, label, rtImport,
+                 Objective.Operation.REMOVE);
+    }
+
+    /**
+     * Release the label from the evpn route.
+     *
+     * @param vpnInstance vpn instance
+     * @param host        host
+     */
+    private Label releaseLabel(VpnInstance vpnInstance, Host host) {
+        EvpnInstanceName instanceName = vpnInstance.vpnInstanceName();
+
+        //Get all vpn-instance routes and check for label.
+        Label label = null;
+        for (EvpnInstanceRoute evpnInstanceRoute : evpnInstanceRoutes) {
+            if (evpnInstanceRoute.evpnInstanceName().equals(instanceName)) {
+                label = evpnInstanceRoute.getLabel();
+                // delete private route and get label ,change to public route
+                boolean isRelease
+                        = labelService
+                        .releaseToGlobalPool(
+                                Sets.newHashSet(
+                                        LabelResourceId
+                                                .labelResourceId(label.getLabel())));
+                if (!isRelease) {
+                    log.error(RELEASE_LABEL_FAILED, label.getLabel());
+                }
+                break;
+            }
+        }
+        return label;
+    }
+
+    private class InternalRouteEventListener implements EvpnRouteListener {
+
+        @Override
+        public void event(EvpnRouteEvent event) {
+            if (!(event.subject() instanceof EvpnRoute)) {
+                return;
+            }
+            EvpnRoute route = (EvpnRoute) event.subject();
+            if (EvpnRouteEvent.Type.ROUTE_ADDED == event.type()) {
+                onBgpEvpnRouteUpdate(route);
+            } else if (EvpnRouteEvent.Type.ROUTE_REMOVED == event.type()) {
+                onBgpEvpnRouteDelete(route);
+            }
+        }
+    }
+
+    private class InnerHostListener implements HostListener {
+
+        @Override
+        public void event(HostEvent event) {
+            Host host = event.subject();
+            if (HostEvent.Type.HOST_ADDED == event.type()) {
+                onHostDetected(host);
+            } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
+                onHostVanished(host);
+            }
+        }
+
+    }
+
+    private class InnerVpnPortListener implements VpnPortListener {
+
+        @Override
+        public void event(VpnPortEvent event) {
+            VpnPort vpnPort = event.subject();
+            if (VpnPortEvent.Type.VPN_PORT_DELETE == event.type()) {
+                onVpnPortDelete(vpnPort);
+            } else if (VpnPortEvent.Type.VPN_PORT_SET == event.type()) {
+                onVpnPortSet(vpnPort);
+            }
+        }
+    }
+
+    @Override
+    public void onVpnPortDelete(VpnPort vpnPort) {
+        // delete the flows of this vpn
+        hostService.getHosts().forEach(host -> {
+            VpnPortId vpnPortId = vpnPort.id();
+            VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
+            if (!vpnInstanceService.exists(vpnInstanceId)) {
+                log.error(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
+                return;
+            }
+            VpnInstance vpnInstance = vpnInstanceService
+                    .getInstance(vpnInstanceId);
+            List<VpnRouteTarget> rtImport
+                    = new LinkedList<>(vpnInstance.getImportRouteTargets());
+            List<VpnRouteTarget> rtExport
+                    = new LinkedList<>(vpnInstance.getExportRouteTargets());
+
+            if (vpnPortId.vpnPortId()
+                    .equals(host.annotations().value(IFACEID))) {
+                log.info(VPN_PORT_UNBIND);
+                Label label = releaseLabel(vpnInstance, host);
+                // create private route and get label
+                DeviceId deviceId = host.location().deviceId();
+                setPrivateRoute(host, vpnInstanceId, label,
+                                Objective.Operation.REMOVE);
+                // download flows
+                setFlows(deviceId, host, label, rtImport,
+                         Objective.Operation.REMOVE);
+            }
+        });
+    }
+
+    @Override
+    public void onVpnPortSet(VpnPort vpnPort) {
+        // delete the flows of this vpn
+        hostService.getHosts().forEach(host -> {
+            VpnPortId vpnPortId = vpnPort.id();
+            VpnInstanceId vpnInstanceId = vpnPort.vpnInstanceId();
+            VpnInstance vpnInstance = vpnInstanceService
+                    .getInstance(vpnInstanceId);
+            if (vpnInstance == null) {
+                log.info("why vpn instance is null");
+                return;
+            }
+            List<VpnRouteTarget> rtImport
+                    = new LinkedList<>(vpnInstance.getImportRouteTargets());
+/*            List<VpnRouteTarget> rtExport
+                    = new LinkedList<>(vpnInstance.getExportRouteTargets());*/
+
+            if (!vpnInstanceService.exists(vpnInstanceId)) {
+                log.error(CANT_FIND_VPN_INSTANCE, vpnInstanceId);
+                return;
+            }
+
+            if (vpnPortId.vpnPortId()
+                    .equals(host.annotations().value(IFACEID))) {
+                log.info(VPN_PORT_BIND);
+                Label label = applyLabel();
+                // create private route and get label
+                DeviceId deviceId = host.location().deviceId();
+                setPrivateRoute(host, vpnInstanceId, label,
+                                Objective.Operation.ADD);
+                // download flows
+                setFlows(deviceId, host, label, rtImport,
+                         Objective.Operation.ADD);
+            }
+        });
+    }
+
+    /**
+     * process the gluon configuration and will update the configuration into
+     * vpn port service.
+     *
+     * @param action action
+     * @param key    key
+     * @param value  json node
+     */
+    private void processEtcdResponse(String action, String key, JsonNode
+            value) {
+        String[] list = key.split(SLASH);
+        String target = list[list.length - 2];
+        switch (target) {
+            case VPN_INSTANCE_TARGET:
+                VpnInstanceService vpnInstanceService
+                        = DefaultServiceDirectory
+                        .getService(VpnInstanceService.class);
+                vpnInstanceService.processGluonConfig(action, key, value);
+                break;
+            case VPN_PORT_TARGET:
+                VpnPortService vpnPortService = DefaultServiceDirectory
+                        .getService(VpnPortService.class);
+                vpnPortService.processGluonConfig(action, key, value);
+                break;
+            case VPN_AF_TARGET:
+                VpnAfConfigService vpnAfConfigService =
+                        DefaultServiceDirectory.getService(VpnAfConfigService
+                                                                   .class);
+                vpnAfConfigService.processGluonConfig(action, key, value);
+                break;
+            case BASEPORT:
+                BasePortService basePortService =
+                        DefaultServiceDirectory.getService(BasePortService
+                                                                   .class);
+                basePortService.processGluonConfig(action, key, value);
+                break;
+            default:
+                log.info("why target type is invalid {}", target);
+                log.info(INVALID_TARGET_RECEIVED);
+                break;
+        }
+    }
+
+    /**
+     * parse the gluon configuration received from network config system.
+     *
+     * @param jsonNode json node
+     * @param key      key
+     * @param action   action
+     */
+    private void parseEtcdResponse(JsonNode jsonNode,
+                                   String key,
+                                   String action) {
+        JsonNode modifyValue = null;
+        if (action.equals(SET)) {
+            modifyValue = jsonNode.get(key);
+        }
+        processEtcdResponse(action, key, modifyValue);
+    }
+
+    /**
+     * Listener for network config events.
+     */
+    private class InternalNetworkConfigListener implements
+            NetworkConfigListener {
+
+        @Override
+        public void event(NetworkConfigEvent event) {
+            String subject;
+            log.info(NETWORK_CONFIG_EVENT_IS_RECEIVED, event.type());
+            if (!event.configClass().equals(GluonConfig.class)) {
+                return;
+            }
+            log.info("Event is received from network configuration {}", event
+                    .type());
+            switch (event.type()) {
+                case CONFIG_UPDATED:
+                    subject = (String) event.subject();
+                    GluonConfig gluonConfig = configService
+                            .getConfig(subject, GluonConfig.class);
+                    JsonNode jsonNode = gluonConfig.node();
+                    parseEtcdResponse(jsonNode, subject, SET);
+                    break;
+                case CONFIG_REMOVED:
+                    subject = (String) event.subject();
+                    parseEtcdResponse(null, subject, DELETE);
+                    break;
+                default:
+                    log.info(INVALID_EVENT_RECEIVED);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * update import and export route target information in route admin service.
+     *
+     * @param evpnInstanceName   evpn instance name
+     * @param exportRouteTargets export route targets
+     * @param importRouteTargets import route targets
+     * @param action             action holds update or delete
+     */
+    private void updateImpExpRtInRoute(EvpnInstanceName evpnInstanceName,
+                                       Set<VpnRouteTarget> exportRouteTargets,
+                                       Set<VpnRouteTarget> importRouteTargets,
+                                       String action) {
+
+        for (EvpnInstanceRoute evpnInstanceRoute : evpnInstanceRoutes) {
+            if (evpnInstanceRoute.evpnInstanceName().equals(evpnInstanceName)) {
+                evpnInstanceRoute
+                        .setExportRtList(new LinkedList<>(exportRouteTargets));
+                evpnInstanceRoute
+                        .setImportRtList(new LinkedList<>(importRouteTargets));
+                if (action.equals(UPDATE)) {
+                    evpnInstanceRoutes.add(evpnInstanceRoute);
+                } else if (action.equals(DELETE)) {
+                    evpnInstanceRoutes.remove(evpnInstanceRoute);
+                }
+                //Get the public route and update route targets.
+                EvpnNextHop evpnNextHop = EvpnNextHop
+                        .evpnNextHop(evpnInstanceRoute.getNextHopl(),
+                                     evpnInstanceRoute.importRouteTarget(),
+                                     evpnInstanceRoute.exportRouteTarget(),
+                                     evpnInstanceRoute.getLabel());
+                Collection<EvpnRoute> evpnPublicRoutes
+                        = evpnRouteStore.getRoutesForNextHop(evpnNextHop.nextHop());
+                for (EvpnRoute pubRoute : evpnPublicRoutes) {
+                    EvpnRoute evpnPubRoute = pubRoute;
+                    if (evpnPubRoute.label().equals(evpnInstanceRoute
+                                                            .getLabel())) {
+                        evpnPubRoute
+                                .setExportRtList(new LinkedList<>(exportRouteTargets));
+                        evpnPubRoute
+                                .setImportRtList(new LinkedList<>(importRouteTargets));
+                        if (action.equals(UPDATE)) {
+                            evpnRouteAdminService.update(Sets.newHashSet(evpnPubRoute));
+                        } else if (action.equals(DELETE)) {
+                            evpnRouteAdminService
+                                    .withdraw(Sets.newHashSet(evpnPubRoute));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * update or withdraw evpn route based on vpn af configuration.
+     *
+     * @param vpnAfConfig vpn af configuration
+     * @param action      action holds update or delete
+     */
+
+    private void processEvpnRouteUpdate(VpnAfConfig vpnAfConfig,
+                                        String action) {
+        Collection<VpnInstance> instances
+                = vpnInstanceService.getInstances();
+        for (VpnInstance vpnInstance : instances) {
+            Set<VpnRouteTarget> configRouteTargets
+                    = vpnInstance.getConfigRouteTargets();
+            for (VpnRouteTarget vpnRouteTarget : configRouteTargets) {
+                if (vpnRouteTarget.equals(vpnAfConfig.routeTarget())) {
+                    Set<VpnRouteTarget> exportRouteTargets
+                            = vpnInstance.getExportRouteTargets();
+                    Set<VpnRouteTarget> importRouteTargets
+                            = vpnInstance.getImportRouteTargets();
+                    String routeTargetType = vpnAfConfig.routeTargetType();
+                    if (action.equals(UPDATE)) {
+                        vpnInstanceService
+                                .updateImpExpRouteTargets(routeTargetType,
+                                                          exportRouteTargets,
+                                                          importRouteTargets,
+                                                          vpnRouteTarget);
+                    } else if (action.equals(DELETE)) {
+                        switch (routeTargetType) {
+                            case EXPORT_EXTCOMMUNITY:
+                                exportRouteTargets.remove(vpnRouteTarget);
+                                break;
+                            case IMPORT_EXTCOMMUNITY:
+                                importRouteTargets.remove(vpnRouteTarget);
+                                break;
+                            case BOTH:
+                                exportRouteTargets.remove(vpnRouteTarget);
+                                importRouteTargets.remove(vpnRouteTarget);
+                                break;
+                            default:
+                                log.info(INVALID_ROUTE_TARGET_TYPE);
+                                break;
+                        }
+                    }
+                    updateImpExpRtInRoute(vpnInstance.vpnInstanceName(),
+                                          exportRouteTargets,
+                                          importRouteTargets,
+                                          action);
+                }
+            }
+        }
+    }
+
+    private class InnerVpnAfConfigListener implements VpnAfConfigListener {
+
+        @Override
+        public void event(VpnAfConfigEvent event) {
+            VpnAfConfig vpnAfConfig = event.subject();
+            if (VpnAfConfigEvent.Type.VPN_AF_CONFIG_DELETE == event.type()) {
+                processEvpnRouteUpdate(vpnAfConfig, DELETE);
+            } else if (VpnAfConfigEvent.Type.VPN_AF_CONFIG_SET
+                    == event.type() || VpnAfConfigEvent.Type
+                    .VPN_AF_CONFIG_UPDATE == event.type()) {
+                processEvpnRouteUpdate(vpnAfConfig, UPDATE);
+            }
+        }
+    }
+}
