X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=vpnmanager%2Fvpnmanager-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fvpnservice%2FVpnInterfaceManager.java;h=b33fea8d226418e66572bde08f04bed564c31d7a;hb=f30638fcc162d85f21f33cef401b4fb5da05caaf;hp=e7bca5339d9d60ec61aaa03e9dce96f612775bcb;hpb=d26469882fcbee50d42d4281e18eac0cc2ffb45f;p=vpnservice.git diff --git a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java index e7bca533..b33fea8d 100644 --- a/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java +++ b/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -7,75 +7,145 @@ */ package org.opendaylight.vpnservice; +import org.opendaylight.vpnservice.utilities.InterfaceUtils; + +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.JdkFutureAdapters; + +import org.opendaylight.controller.md.sal.binding.api.*; +import org.opendaylight.vpnservice.mdsalutil.*; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; + +import java.math.BigInteger; +import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.ArrayList; +import java.util.concurrent.*; import com.google.common.base.Optional; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.FutureCallback; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.bgpmanager.api.IBgpManager; +import org.opendaylight.fibmanager.api.IFibManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.yangtools.concepts.ListenerRegistration; -import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacencyList; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies; +import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig; +import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances; +import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance; +import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey; -import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class VpnInterfaceManager extends AbstractDataChangeListener implements AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class); - private ListenerRegistration listenerRegistration; + private ListenerRegistration listenerRegistration, opListenerRegistration; + private ConcurrentMap vpnIntfMap = new ConcurrentHashMap(); + private ExecutorService executorService = Executors.newSingleThreadExecutor(); private final DataBroker broker; - - private static final FutureCallback DEFAULT_CALLBACK = - new FutureCallback() { - public void onSuccess(Void result) { - LOG.info("Success in Datastore write operation"); - } - - public void onFailure(Throwable error) { - LOG.error("Error in Datastore write operation", error); - }; - }; - + private final IBgpManager bgpManager; + private IFibManager fibManager; + private IMdsalApiManager mdsalManager; + private OdlInterfaceRpcService interfaceManager; + private ItmRpcService itmProvider; + private IdManagerService idManager; + private OdlArputilService arpManager; + private InterfaceStateChangeListener interfaceListener; + private VpnInterfaceOpListener vpnInterfaceOpListener; + private ArpNotificationHandler arpNotificationHandler; + protected enum UpdateRouteAction { + ADVERTISE_ROUTE, WITHDRAW_ROUTE + } /** * Responsible for listening to data change related to VPN Interface * Bind VPN Service on the interface and informs the BGP service - * + * * @param db - dataBroker service reference */ - public VpnInterfaceManager(final DataBroker db) { + public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) { super(VpnInterface.class); broker = db; + this.bgpManager = bgpManager; + interfaceListener = new InterfaceStateChangeListener(db, this); + vpnInterfaceOpListener = new VpnInterfaceOpListener(); + arpNotificationHandler = new ArpNotificationHandler(this, broker); + notificationService.registerNotificationListener(arpNotificationHandler); registerListener(db); } + public void setMdsalManager(IMdsalApiManager mdsalManager) { + this.mdsalManager = mdsalManager; + } + + public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) { + this.interfaceManager = interfaceManager; + interfaceListener.setInterfaceManager(interfaceManager); + } + + public void setITMProvider(ItmRpcService itmProvider) { + this.itmProvider = itmProvider; + } + + public void setFibManager(IFibManager fibManager) { + this.fibManager = fibManager; + } + + public void setIdManager(IdManagerService idManager) { + this.idManager = idManager; + } + + public void setArpManager(OdlArputilService arpManager) { + this.arpManager = arpManager; + } + @Override public void close() throws Exception { if (listenerRegistration != null) { try { listenerRegistration.close(); + opListenerRegistration.close(); } catch (final Exception e) { LOG.error("Error when cleaning up DataChangeListener.", e); } listenerRegistration = null; + opListenerRegistration = null; } LOG.info("VPN Interface Manager Closed"); } @@ -84,106 +154,782 @@ public class VpnInterfaceManager extends AbstractDataChangeListener getInterfaceListenerPath() { + return InstanceIdentifier.create(InterfacesState.class) + .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class); + } + @Override protected void add(final InstanceIdentifier identifier, final VpnInterface vpnInterface) { - LOG.info("key: " + identifier + ", value=" + vpnInterface ); + LOG.trace("VPN Interface key: {} , value: {}", identifier, vpnInterface ); addInterface(identifier, vpnInterface); } private void addInterface(final InstanceIdentifier identifier, final VpnInterface vpnInterface) { + LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface ); final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class); String interfaceName = key.getName(); - InstanceIdentifierBuilder idBuilder = - InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName)); - InstanceIdentifier id = idBuilder.build(); - Optional port = read(LogicalDatastoreType.CONFIGURATION, id); - if (port.isPresent()) { - Interface interf = port.get(); - bindServiceOnInterface(interf); - updateNextHops(identifier, vpnInterface); + + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = + InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName); + if (interfaceState != null) { + // Interface state is up + processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex()); + } else { + LOG.trace("VPN interfaces are not yet operational."); } } - private void updateNextHops(final InstanceIdentifier identifier, VpnInterface intf) { - //Read NextHops - InstanceIdentifier path = identifier.augmentation(Adjacencies.class); - Optional adjacencies = read(LogicalDatastoreType.CONFIGURATION, path); + protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag) { + + VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName); + if(vpnInterface == null) { + LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName); + return; + } + String vpnName = vpnInterface.getVpnInstanceName(); + LOG.info("Binding vpn service to interface {} ", interfaceName); + long vpnId = VpnUtil.getVpnId(broker, vpnName); + if (vpnId == VpnConstants.INVALID_ID) { + LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now."); + return; + } + synchronized (interfaceName.intern()) { + if (VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName()) != null) { + LOG.trace("VPN Interface already provisioned , bailing out from here."); + return; + } + bindService(dpId, vpnName, interfaceName, lPortTag); + updateDpnDbs(dpId, vpnName, interfaceName, true); + processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface); + } + + } + + private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) { + long vpnId = VpnUtil.getVpnId(broker, vpnName); + if (dpId == null) { + dpId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName); + } + if(!dpId.equals(BigInteger.ZERO)) { + if(add) + updateMappingDbs(vpnId, dpId, interfaceName, vpnName); + else + removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName); + } + + } + + private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) { + int priority = VpnConstants.DEFAULT_FLOW_PRIORITY; + long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName); + + int instructionKey = 0; + List instructions = new ArrayList(); + + instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey)); + instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey)); + + BoundServices + serviceInfo = + InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName), + VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority, + VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions); + VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, + InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo); + makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName, + vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW); + + } + + private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier identifier, VpnInterface intf) { String intfName = intf.getName(); - if (adjacencies.isPresent()) { - List nextHops = adjacencies.get().getAdjacency(); - List value = new ArrayList<>(); + synchronized (intfName) { + // Read NextHops + InstanceIdentifier path = identifier.augmentation(Adjacencies.class); + Optional adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path); - if (!nextHops.isEmpty()) { - LOG.info("NextHops are " + nextHops); + if (adjacencies.isPresent()) { + List nextHops = adjacencies.get().getAdjacency(); + List value = new ArrayList<>(); + + // Get the rd of the vpn instance + String rd = getRouteDistinguisher(intf.getVpnInstanceName()); + + String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId); + if (nextHopIp == null){ + LOG.error("NextHop for interface {} is null", intfName); + } + + LOG.trace("NextHops are {}", nextHops); for (Adjacency nextHop : nextHops) { - //TODO: Generate label for the prefix and store it in the next hop model - long label = 200; + String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress()); + long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil + .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix)); + String adjNextHop = nextHop.getNextHopIp(); + value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIp((adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp) + .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build()); + if(nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) { + VpnUtil.syncUpdate( + broker, + LogicalDatastoreType.OPERATIONAL, + VpnUtil.getPrefixToInterfaceIdentifier( + VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix), + VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix)); + } else { + //Extra route adjacency + VpnUtil.syncUpdate( + broker, + LogicalDatastoreType.OPERATIONAL, + VpnUtil.getVpnToExtrarouteIdentifier( + (rd != null) ? rd : intf.getVpnInstanceName(), nextHop.getIpAddress()), + VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIp())); - //TODO: Update BGP - updatePrefixToBGP(nextHop); - value.add(new AdjacencyBuilder(nextHop).setLabel(label).build()); + } + } + + Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value); + VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug); + InstanceIdentifier interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName); + VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface); + for (Adjacency nextHop : aug.getAdjacency()) { + long label = nextHop.getLabel(); + //String adjNextHop = nextHop.getNextHopIp(); + if (rd != null) { + addPrefixToBGP(rd, nextHop.getIpAddress(), + nextHopIp, label); + } else { + // ### add FIB route directly + addFibEntryToDS(intf.getVpnInstanceName(), nextHop.getIpAddress(), + nextHopIp, (int) label); + } } } - Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value); - VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug); - InstanceIdentifier interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName); - asyncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK); } } - private void bindServiceOnInterface(Interface intf) { - //TODO: Create Ingress flow on the interface to bind the VPN service + private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName, + long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){ + List matches = new ArrayList(); + BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId)); + BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX, + MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID); + + // Matching Arp reply flows + matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP })); + matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + metadata, metadataMask })); + + matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() })); + + // Instruction to punt to controller + List instructions = new ArrayList(); + List actionsInfos = new ArrayList(); + actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {})); + instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + + // Install the flow entry in L3_INTERFACE_TABLE + String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE, + NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation()); + FlowEntity flowEntity; + flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef, + NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0, + VpnUtil.getCookieArpFlow(lPortTag), matches, instructions); + + if (addOrRemoveFlow == NwConstants.ADD_FLOW) { + LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName); + mdsalManager.installFlow(flowEntity); + } else { + LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName); + mdsalManager.removeFlow(flowEntity); + } } - private void updatePrefixToBGP(Adjacency nextHop) { - //TODO: Update the Prefix to BGP + private String getRouteDistinguisher(String vpnName) { + InstanceIdentifier id = InstanceIdentifier.builder(VpnInstances.class) + .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build(); + Optional vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id); + String rd = ""; + if(vpnInstance.isPresent()) { + VpnInstance instance = vpnInstance.get(); + VpnAfConfig config = instance.getIpv4Family(); + rd = config.getRouteDistinguisher(); + } + return rd; } - private Optional read(LogicalDatastoreType datastoreType, - InstanceIdentifier path) { + private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) { + String routeDistinguisher = getRouteDistinguisher(vpnName); + String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher; + InstanceIdentifier id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId); + Optional dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id); + org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces + vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build(); - ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + if (dpnInVpn.isPresent()) { + VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child( + org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance + .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class, + new VpnInterfacesKey(intfName)), vpnInterface); + } else { + VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, + VpnUtil.getVpnInstanceOpDataIdentifier(rd), + VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId)); + VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId); + List vpnInterfaces = new ArrayList<>(); + vpnInterfaces.add(vpnInterface); + VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, + vpnToDpnList.setVpnInterfaces(vpnInterfaces).build()); - Optional result = Optional.absent(); - try { - result = tx.read(datastoreType, path).get(); - } catch (Exception e) { - throw new RuntimeException(e); + /** + * FIXME: DC Gateway tunnel should be built dynamically + //this is the first VM in this VPN on the DPN, may be a new DPN has come up, + //if tunnel to DC GW does not exist, create it + //if(!tunnelExists(dpnID, bgpManager.getDCGWIP())) + String dcGW = bgpManager.getDCGwIP(); + if(dcGW != null && !dcGW.isEmpty()) + { + LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW); + itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray())); + }*/ + fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd); } + } - return result; + private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) { + //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn + String rd = VpnUtil.getVpnRd(broker, vpnName); + InstanceIdentifier id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId); + Optional dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id); + if (dpnInVpn.isPresent()) { + List vpnInterfaces = dpnInVpn.get().getVpnInterfaces(); + org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces + currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build(); + + if (vpnInterfaces.remove(currVpnInterface)) { + if (vpnInterfaces.isEmpty()) { + VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK); + fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd); + } else { + VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child( + org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data + .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class, + new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK); + } + } + } } + private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) { + try { + bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label); + } catch(Exception e) { + LOG.error("Add prefix failed", e); + } + } + + private InstanceIdentifier getWildCardPath() { return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class); } @Override - protected void remove( InstanceIdentifier identifier, VpnInterface del) { - // TODO Auto-generated method stub + protected void remove( InstanceIdentifier identifier, VpnInterface vpnInterface) { + LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface ); + final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class); + String interfaceName = key.getName(); + + InstanceIdentifier interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName); + Optional existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId); + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = + InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName); + + if (existingVpnInterface.isPresent() && interfaceState != null) { + processVpnInterfaceDown(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex(), false); + } else { + LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName); + } + } + + protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown) { + VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName); + if(vpnInterface == null) { + LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName); + return; + } + String vpnName = vpnInterface.getVpnInstanceName(); + InstanceIdentifier identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName); + + synchronized (interfaceName.intern()) { + removeAdjacenciesFromVpn(identifier, vpnInterface); + LOG.info("Unbinding vpn service from interface {} ", interfaceName); + unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown); + + //wait till DCN for removal of vpn interface in operational DS arrives + Runnable notifyTask = new VpnNotifyTask(); + synchronized (interfaceName.intern()) { + vpnIntfMap.put(interfaceName, notifyTask); + synchronized (notifyTask) { + try { + notifyTask.wait(VpnConstants.WAIT_TIME_IN_MILLISECONDS); + } catch (InterruptedException e) { + } + } + } + + } + } + + private void removeAdjacenciesFromVpn(final InstanceIdentifier identifier, VpnInterface intf) { + //Read NextHops + InstanceIdentifier path = identifier.augmentation(Adjacencies.class); + Optional adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path); + + String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName()); + if (adjacencies.isPresent()) { + List nextHops = adjacencies.get().getAdjacency(); + if (!nextHops.isEmpty()) { + LOG.trace("NextHops are " + nextHops); + for (Adjacency nextHop : nextHops) { + VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, + VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress())); + /*VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, + VpnUtil.getPrefixToInterfaceIdentifier( + VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), + nextHop.getIpAddress()), + VpnUtil.DEFAULT_CALLBACK);*/ + if (rd.equals(intf.getVpnInstanceName())) { + //this is an internal vpn - the rd is assigned to the vpn instance name; + //remove from FIB directly + removeFibEntryFromDS(intf.getVpnInstanceName(), nextHop.getIpAddress()); + } else { + removePrefixFromBGP(rd, nextHop.getIpAddress()); + } + } + } + } + } + + + private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, + int lPortTag, boolean isInterfaceStateDown) { + if (!isInterfaceStateDown) { + VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, + InterfaceUtils.buildServiceId(vpnInterfaceName, + VpnConstants.L3VPN_SERVICE_IDENTIFIER), + VpnUtil.DEFAULT_CALLBACK); + } + long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName); + makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName, + vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW); + } + + + private void removePrefixFromBGP(String rd, String prefix) { + try { + bgpManager.deletePrefix(rd, prefix); + } catch(Exception e) { + LOG.error("Delete prefix failed", e); + } } @Override - protected void update(InstanceIdentifier identifier, - VpnInterface original, VpnInterface update) { - // TODO Auto-generated method stub + protected void update(InstanceIdentifier identifier, VpnInterface original, VpnInterface update) { + if (LOG.isTraceEnabled()) { + LOG.trace("Updating VPN Interface : key " + identifier + ", original value=" + original + ", update " + + "value=" + update); + } + String oldVpnName = original.getVpnInstanceName(); + String newVpnName = update.getVpnInstanceName(); + List oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency(); + List newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency(); + if (oldAdjs == null) { + oldAdjs = new ArrayList<>(); + } + if (newAdjs == null) { + newAdjs = new ArrayList<>(); + } + //handles switching between + if (!oldVpnName.equals(newVpnName)) { + remove(identifier, original); + add(identifier, update); + } + //handle both addition and removal of adjacencies + //currently, new adjacency may be an extra route + if (!oldAdjs.equals(newAdjs)) { + for (Adjacency adj : newAdjs) { + if (oldAdjs.contains(adj)) { + oldAdjs.remove(adj); + } else { + // add new adjacency - right now only extra route will hit this path + addNewAdjToVpnInterface(identifier, adj); + } + } + for (Adjacency adj : oldAdjs) { + delAdjFromVpnInterface(identifier, adj); + } + } + } + + public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, String srcInterface){ + SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface) + .setIpaddress(srcIP).setSrcIpAddress(targetIP).setMacaddress(srcMac).build(); + final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP); + Future> future = arpManager.sendArpResponse(input); + Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback>() { + @Override + public void onFailure(Throwable error) { + LOG.error("Error - {}", msgFormat, error); + } + + @Override + public void onSuccess(RpcResult result) { + if(!result.isSuccessful()) { + LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors())); + } else { + LOG.debug("Successful RPC Result - {}", msgFormat); + } + } + }); + } + private String getErrorText(Collection errors) { + StringBuilder errorText = new StringBuilder(); + for(RpcError error : errors) { + errorText.append(",").append(error.getErrorType()).append("-") + .append(error.getMessage()); + } + return errorText.toString(); } - private void asyncWrite(LogicalDatastoreType datastoreType, - InstanceIdentifier path, T data, FutureCallback callback) { - WriteTransaction tx = broker.newWriteOnlyTransaction(); - tx.put(datastoreType, path, data, true); - Futures.addCallback(tx.submit(), callback); + private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) { + return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString(); + } + + + + public synchronized void addFibEntryToDS(String rd, String prefix, + String nexthop, int label) { + + VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix). + setNextHopAddress(nexthop).setLabel((long)label).build(); + LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label); + + List vrfEntryList = new ArrayList(); + vrfEntryList.add(vrfEntry); + + InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)); + InstanceIdentifier vrfTableId = idBuilder.build(); + + VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd). + setVrfEntry(vrfEntryList).build(); + + VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew); } + + public synchronized void removeFibEntryFromDS(String rd, String prefix) { + + LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd); + + InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix)); + InstanceIdentifier vrfEntryId = idBuilder.build(); + VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, VpnUtil.DEFAULT_CALLBACK); + + } + + public synchronized void removeVrfFromDS(String rd) { + LOG.debug("Removing vrf table for rd {}", rd); + + InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)); + InstanceIdentifier vrfTableId = idBuilder.build(); + + VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK); + + } + + protected void addNewAdjToVpnInterface(InstanceIdentifier identifier, Adjacency adj) { + + Optional optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier); + + if (optVpnInterface.isPresent()) { + VpnInterface currVpnIntf = optVpnInterface.get(); + String prefix = VpnUtil.getIpPrefix(adj.getIpAddress()); + String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName()); + InstanceIdentifier adjPath = identifier.augmentation(Adjacencies.class); + Optional optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath); + long label = + VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, + VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix)); + + List adjacencies; + if (optAdjacencies.isPresent()) { + adjacencies = optAdjacencies.get().getAdjacency(); + } else { + //This code will not be hit since VM adjacency will always be there + adjacencies = new ArrayList<>(); + } + + adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIp(adj.getNextHopIp()) + .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build()); + + Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies); + VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug); + + VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf); + addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label, currVpnIntf.getName()); + + } + + } + + protected void delAdjFromVpnInterface(InstanceIdentifier identifier, Adjacency adj) { + Optional optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier); + + if (optVpnInterface.isPresent()) { + VpnInterface currVpnIntf = optVpnInterface.get(); + + InstanceIdentifier path = identifier.augmentation(Adjacencies.class); + Optional optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path); + if (optAdjacencies.isPresent()) { + List adjacencies = optAdjacencies.get().getAdjacency(); + + if (!adjacencies.isEmpty()) { + String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName()); + LOG.trace("Adjacencies are " + adjacencies); + Iterator adjIt = adjacencies.iterator(); + while (adjIt.hasNext()) { + Adjacency adjElem = adjIt.next(); + if (adjElem.getIpAddress().equals(adj.getIpAddress())) { + VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, + VpnUtil.getNextHopLabelKey(rd, adj.getIpAddress())); + adjIt.remove(); + + Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies); + VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), + currVpnIntf.getVpnInstanceName(), + aug); + + VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf); + + delExtraRoute(adj.getIpAddress(), rd, currVpnIntf.getVpnInstanceName()); + break; + } + + } + } + } + } + + } + + protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label, String intfName) { + + //add extra route to vpn mapping; advertise with nexthop as tunnel ip + VpnUtil.syncUpdate( + broker, + LogicalDatastoreType.OPERATIONAL, + VpnUtil.getVpnToExtrarouteIdentifier( + (rd != null) ? rd : routerID, destination), + VpnUtil.getVpnToExtraroute(destination, nextHop)); + + if(intfName != null && !intfName.isEmpty()) { + BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName); + String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId); + if (nextHopIp == null && !nextHopIp.isEmpty()) { + LOG.error("NextHop for interface {} is null. Adding extra route {} without nextHop", intfName, + destination); + } + nextHop = nextHopIp; + } + if (rd != null) { + addPrefixToBGP(rd, destination, nextHop, label); + } else { + // ### add FIB route directly + addFibEntryToDS(routerID, destination, nextHop, label); + } + } + + protected void delExtraRoute(String destination, String rd, String routerID) { + if (rd != null) { + removePrefixFromBGP(rd, destination); + } else { + // ### add FIB route directly + removeFibEntryFromDS(routerID, destination); + } + } + + class VpnInterfaceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener { + + public VpnInterfaceOpListener() { + super(VpnInterface.class); + } + + @Override + protected void remove(InstanceIdentifier identifier, VpnInterface del) { + final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class); + String interfaceName = key.getName(); + + //increment the vpn interface count in Vpn Instance Op Data + Long ifCnt = 0L; + String rd = getRouteDistinguisher(del.getVpnInstanceName()); + if(rd == null || rd.isEmpty()) rd = del.getVpnInstanceName(); + VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd); + if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) { + ifCnt = vpnInstOp.getVpnInterfaceCount(); + } + + LOG.trace("VpnInterfaceOpListener remove: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt); + + if(ifCnt != 0) { + VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL, + VpnUtil.getVpnInstanceOpDataIdentifier(rd), + VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK); + } + + // Vpn Interface removed => No more adjacencies from it. + // Hence clean up interface from vpn-dpn-interface list. + Adjacency adjacency = del.getAugmentation(Adjacencies.class).getAdjacency().get(0); + Optional prefixToInterface = Optional.absent(); + prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, + VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), + VpnUtil.getIpPrefix(adjacency.getIpAddress()))); + if (!prefixToInterface.isPresent()) { + prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, + VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), + VpnUtil.getIpPrefix(adjacency.getNextHopIp()))); + } + if (prefixToInterface.isPresent()) { + VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, + VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), + prefixToInterface.get().getIpAddress()), + VpnUtil.DEFAULT_CALLBACK); + updateDpnDbs(prefixToInterface.get().getDpnId(), del.getVpnInstanceName(), interfaceName, false); + } + notifyTaskIfRequired(interfaceName); + } + + private void notifyTaskIfRequired(String intfName) { + Runnable notifyTask = vpnIntfMap.remove(intfName); + if (notifyTask == null) { + return; + } + executorService.execute(notifyTask); + } + + @Override + protected void update(InstanceIdentifier identifier, VpnInterface original, VpnInterface update) { + } + + @Override + protected void add(InstanceIdentifier identifier, VpnInterface add) { + final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class); + String interfaceName = key.getName(); + + //increment the vpn interface count in Vpn Instance Op Data + Long ifCnt = 0L; + String rd = getRouteDistinguisher(add.getVpnInstanceName()); + if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName(); + VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd); + if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) { + ifCnt = vpnInstOp.getVpnInterfaceCount(); + } + + LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt); + + VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL, + VpnUtil.getVpnInstanceOpDataIdentifier(rd), + VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK); + + + } + } + + protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) { + + LOG.info("Tunnel event triggered {} for Dpn:{} ", action.name(), dpnId); + InstanceIdentifierBuilder idBuilder = InstanceIdentifier.builder(VpnInstances.class); + InstanceIdentifier vpnInstancesId = idBuilder.build(); + Optional vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId); + + if (vpnInstances.isPresent()) { + List vpnInstanceList = vpnInstances.get().getVpnInstance(); + Iterator vpnInstIter = vpnInstanceList.iterator(); + while (vpnInstIter.hasNext()) { + VpnInstance vpnInstance = vpnInstIter.next(); + try { + VpnAfConfig vpnConfig = vpnInstance.getIpv4Family(); + String rd = vpnConfig.getRouteDistinguisher(); + if (rd == null || rd.isEmpty()) { + rd = vpnInstance.getVpnInstanceName(); + } + InstanceIdentifier id = + VpnUtil.getVpnToDpnListIdentifier(rd, dpnId); + Optional dpnInVpn = + VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id); + if (dpnInVpn.isPresent()) { + // if (action == UpdateRouteAction.ADVERTISE_ROUTE) { + // fibManager.populateFibOnNewDpn(dpnId, VpnUtil + // .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd); + // } + List + vpnInterfaces = dpnInVpn.get().getVpnInterfaces(); + for (org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data + .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) { + InstanceIdentifier vpnIntfId = + VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName()); + InstanceIdentifier path = + vpnIntfId.augmentation(Adjacencies.class); + Optional adjacencies = + VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path); + + if (adjacencies.isPresent()) { + List adjacencyList = adjacencies.get().getAdjacency(); + Iterator adjacencyIterator = adjacencyList.iterator(); + + while (adjacencyIterator.hasNext()) { + Adjacency adjacency = adjacencyIterator.next(); + try { + if (action == UpdateRouteAction.ADVERTISE_ROUTE) + bgpManager.addPrefix(rd, adjacency.getIpAddress(), + adjacency.getNextHopIp(), + adjacency.getLabel().intValue()); + else if (action == UpdateRouteAction.WITHDRAW_ROUTE) + bgpManager.deletePrefix(rd, adjacency.getIpAddress()); + } catch (Exception e) { + LOG.error("Exception when updating prefix {} in vrf {} to BGP", + adjacency.getIpAddress(), rd); + } + } + } + + } + // if (action == UpdateRouteAction.WITHDRAW_ROUTE) { + // fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd); + // } + } + } catch (Exception e) { + LOG.error("updatePrefixesForDPN {} in vpn {} failed", dpnId, vpnInstance.getVpnInstanceName(), e); + } + } + } + } + }