<type xmlns:mdsalutil="urn:opendaylight:genius:mdsalutil">mdsalutil:odl-mdsalutil</type>
<name>mdsalutil-service</name>
</mdsalutil>
+ <notification-service>
+ <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-service</type>
+ <name>binding-notification-adapter</name>
+ </notification-service>
</module>
</modules>
<services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
public static final long SCF_L3VPN_ID_POOL_START = 20000;
public static final long SCF_L3VPN_ID_POOL_END = 65535;
public static final long ETHERTYPE_IPV4 = 0x0800L;
+ public static final long INVALID_VPN_TAG = -1;
}
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.netvirt.cloudservicechain.api.ICloudServiceChain;
import org.opendaylight.netvirt.cloudservicechain.listeners.ElanDpnInterfacesListener;
+import org.opendaylight.netvirt.cloudservicechain.listeners.NodeListener;
import org.opendaylight.netvirt.cloudservicechain.listeners.VpnPseudoPortListener;
+import org.opendaylight.netvirt.cloudservicechain.listeners.VpnToDpnListener;
import org.opendaylight.netvirt.cloudservicechain.listeners.VrfListener;
import org.opendaylight.netvirt.cloudservicechain.utils.VpnPseudoPortCache;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
private static final Logger LOG = LoggerFactory.getLogger(CloudServiceChainProvider.class);
private IMdsalApiManager mdsalManager;
private FibRpcService fibRpcService;
+ private NotificationService notificationService;
VPNServiceChainHandler vpnServiceChainHandler;
ElanServiceChainHandler elanServiceChainHandler;
VpnPseudoPortListener vpnPseudoPortListener;
VrfListener labelListener;
ElanDpnInterfacesListener elanDpnInterfacesListener;
+ VpnToDpnListener vpnToDpnListener;
+ NodeListener nodeListener;
+
+ public CloudServiceChainProvider(NotificationService notificationServiceDependency,
+ IMdsalApiManager mdsalManager, FibRpcService fibRpcService) {
+ this.notificationService = notificationServiceDependency;
+ this.mdsalManager = mdsalManager;
+ this.fibRpcService = fibRpcService;
+ }
@Override
public void onSessionInitiated(ProviderContext session) {
vpnPseudoPortListener = new VpnPseudoPortListener(dataBroker);
labelListener = new VrfListener(dataBroker, mdsalManager);
elanDpnInterfacesListener = new ElanDpnInterfacesListener(dataBroker, mdsalManager);
+ vpnToDpnListener = new VpnToDpnListener(dataBroker, mdsalManager);
+ nodeListener = new NodeListener(dataBroker, mdsalManager);
+
+ notificationService.registerNotificationListener(vpnToDpnListener);
elanServiceChainHandler = new ElanServiceChainHandler(dataBroker, mdsalManager);
}
}
- public void setMdsalManager(IMdsalApiManager mdsalManager) {
- this.mdsalManager = mdsalManager;
- }
-
- public void setFibRpcService(FibRpcService fibManager) {
- this.fibRpcService = fibManager;
- if ( this.vpnServiceChainHandler != null ) {
- this.vpnServiceChainHandler.setFibRpcService(fibManager);
- }
- }
-
@Override
public void close() throws Exception {
package org.opendaylight.netvirt.cloudservicechain;
import java.math.BigInteger;;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
* @param scfTag Service Function tag
* @param scsTag Service Chain tag
* @param lportTag Lport tag
- * @return fake VpnPseudoPort interface name
+ * @return the fake VpnPseudoPort interface name
*/
- private String getVpnPseudoPortIfName(Long dpId, int scfTag, int scsTag, int lportTag) {
+ private String buildVpnPseudoPortIfName(Long dpId, int scfTag, int scsTag, int lportTag) {
return new StringBuilder("VpnPseudo.").append(dpId).append(NwConstants.FLOWID_SEPARATOR)
.append(lportTag).append(NwConstants.FLOWID_SEPARATOR)
.append(scfTag).append(NwConstants.FLOWID_SEPARATOR)
}
-
/**
* L3VPN Service chaining: It moves traffic from a ServiceChain to a L3VPN
*
// These Flows must be installed in the DPN where the last SF in the ServiceChain is located
// + ScForwardingTable (75): (This one is created and maintained by ScHopManager)
// - Match: scfTag + servChainId + lportTagOfvVSF Instr: VpnPseudoPortTag + SI=L3VPN + GOTO LPortDisp
+ // And these 2 flows must be installed in all Dpns where the Vpn is present:
// + LPortDisp (17):
// - Match: VpnPseudoPortTag + SI==L3VPN Instr: setVpnTag + GOTO FIB
// + FIB (21): (one entry per VrfEntry, and it is maintained by FibManager)
LOG.debug("Router distinguisher (rd): {}, lportTag: {} ", rd, vpnPseudoLportTag);
// Find out the set of DPNs for the given VPN ID
if (vpnInstance != null) {
- Long vpnId = vpnInstance.getVpnId();
- BigInteger dpId = BigInteger.valueOf(dpnId);
- Flow flow = VpnServiceChainUtils.buildLPortDispFromScfToL3VpnFlow(vpnId, dpId, vpnPseudoLportTag,
- addOrRemove);
- if ( addOrRemove == NwConstants.ADD_FLOW ) {
- mdsalManager.installFlow(BigInteger.valueOf(dpnId), flow);
- } else {
- // Only remove if it is the LastServiceChain using it.
- if ( isLastServiceChain ) {
- mdsalManager.removeFlow(BigInteger.valueOf(dpnId), flow);
+
+ if ( addOrRemove == NwConstants.ADD_FLOW
+ || (addOrRemove == NwConstants.DEL_FLOW && isLastServiceChain) ) {
+
+ Long vpnId = vpnInstance.getVpnId();
+ List<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+ if ( vpnToDpnList != null ) {
+ List<BigInteger> dpns = new ArrayList<BigInteger>();
+ for (VpnToDpnList dpnInVpn : vpnToDpnList ) {
+ dpns.add(dpnInVpn.getDpnId());
+ }
+ if ( !dpns.contains(dpnId) ) {
+ LOG.debug("Dpn {} is not included in the current VPN Footprint", dpnId);
+ dpns.add(BigInteger.valueOf(dpnId));
+ }
+ for ( BigInteger dpn : dpns ) {
+ VpnServiceChainUtils.programLPortDispatcherFlowForScfToVpn(mdsalManager, vpnId, dpn,
+ vpnPseudoLportTag, addOrRemove);
+ }
+ } else {
+ LOG.debug("Could not find VpnToDpn list for VPN {} with rd {}", vpnName, rd);
}
}
- // Update the Vpn footprint by adding or removing the fake interfaces
- String intfName = getVpnPseudoPortIfName(dpnId, scfTag, servChainTag, vpnPseudoLportTag);
+ // We need to keep a fake VpnInterface in the DPN where the last vSF (before the VpnPseudoPort) is
+ // located, because in case the last real VpnInterface is removed from that DPN, we still need
+ // the Fib table programmed there
+ String intfName = buildVpnPseudoPortIfName(dpnId, scfTag, servChainTag, vpnPseudoLportTag);
if (addOrRemove == NwConstants.ADD_FLOW ) {
// Including this DPN in the VPN footprint even if there is no VpnInterface here.
// This is needed so that FibManager maintains the FIB table in this DPN
--- /dev/null
+/*
+ * Copyright (c) 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.cloudservicechain.listeners;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MatchFieldType;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.cloudservicechain.CloudServiceChainConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// Rationale: for vpn-servicechain and elan-servicechain to coexist in the same deployment, it is necessary a flow
+// in LPortDispatcher that sets SI to ELAN in case that VPN does not apply
+/**
+ * Listens for Node Up events in order to install the L2 to L3 default
+ * fallback flow. This flow, with minimum priority, consists on matching on
+ * SI=2 and sets SI=3.
+ *
+ */
+public class NodeListener extends AbstractDataChangeListener<Node> implements AutoCloseable {
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private final IMdsalApiManager mdsalMgr;
+
+ private static final String L3_TO_L2_DEFAULT_FLOW_REF = "L3VPN_to_Elan_Fallback_Default_Rule";
+
+ private static final Logger logger = LoggerFactory.getLogger(NodeListener.class);
+
+ public NodeListener(final DataBroker db, final IMdsalApiManager mdsalManager) {
+ super(Node.class);
+ this.broker = db;
+ this.mdsalMgr = mdsalManager;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration =
+ db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.create(Nodes.class).child(Node.class),
+ NodeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("vpnmanager's NodeListener registration Listener failed.", e);
+ throw new IllegalStateException("vpnmanager's NodeListener registration Listener failed.", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ logger.error("Error when cleaning up NodeListener in VpnManager.", e);
+ }
+ listenerRegistration = null;
+ }
+ logger.debug("VpnManager's NodeListener Closed");
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Node> identifier, Node del) {
+ BigInteger dpnId = getDpnIdFromNodeId(del.getId());
+ if ( dpnId == null ) {
+ return;
+ }
+ logger.debug("Removing L3VPN to ELAN default Fallback flow in LPortDispatcher table");
+ Flow flowToRemove = new FlowBuilder().setFlowName(L3_TO_L2_DEFAULT_FLOW_REF)
+ .setId(new FlowId(L3_TO_L2_DEFAULT_FLOW_REF))
+ .setTableId(NwConstants.LPORT_DISPATCHER_TABLE).build();
+ mdsalMgr.removeFlow(dpnId, flowToRemove);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Node> identifier, Node original, Node update) {
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Node> identifier, Node add) {
+ BigInteger dpnId = getDpnIdFromNodeId(add.getId());
+ if ( dpnId == null ) {
+ return;
+ }
+
+ logger.debug("Installing L3VPN to ELAN default Fallback flow in LPortDispatcher table");
+ BigInteger[] metadataToMatch = new BigInteger[] {
+ MetaDataUtil.getServiceIndexMetaData(NwConstants.L3VPN_SERVICE_INDEX),
+ MetaDataUtil.METADATA_MASK_SERVICE_INDEX
+ };
+ List<MatchInfo> matches = Arrays.asList(new MatchInfo(MatchFieldType.metadata, metadataToMatch));
+
+ BigInteger metadataToWrite = MetaDataUtil.getServiceIndexMetaData(NwConstants.ELAN_SERVICE_INDEX);
+ int instructionKey = 0;
+ List<Instruction> instructions =
+ Arrays.asList(MDSALUtil.buildAndGetWriteMetadaInstruction(metadataToWrite,
+ MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
+ ++instructionKey),
+ MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_INTERFACE_TABLE, ++instructionKey));
+
+ Flow flow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, L3_TO_L2_DEFAULT_FLOW_REF,
+ NwConstants.TABLE_MISS_PRIORITY, L3_TO_L2_DEFAULT_FLOW_REF,
+ 0, 0, CloudServiceChainConstants.COOKIE_L3_BASE,
+ matches, instructions);
+ mdsalMgr.installFlow(dpnId, flow);
+ }
+
+
+ private BigInteger getDpnIdFromNodeId(NodeId nodeId) {
+ String[] node = nodeId.getValue().split(":");
+ if(node.length < 2) {
+ logger.warn("Unexpected nodeId {}", nodeId.getValue());
+ return null;
+ }
+ return new BigInteger(node[1]);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netvirt.cloudservicechain.listeners;
+
+import java.math.BigInteger;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.cloudservicechain.CloudServiceChainConstants;
+import org.opendaylight.netvirt.cloudservicechain.utils.VpnServiceChainUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.OdlL3vpnListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class VpnToDpnListener implements OdlL3vpnListener {
+
+ private final DataBroker broker;
+ private final IMdsalApiManager mdsalMgr;
+
+ private static final Logger logger = LoggerFactory.getLogger(VpnToDpnListener.class);
+
+ public VpnToDpnListener(final DataBroker db, final IMdsalApiManager mdsalManager) {
+ this.broker = db;
+ this.mdsalMgr = mdsalManager;
+ }
+
+ @Override
+ public void onAddDpnEvent(AddDpnEvent notification) {
+
+ programLPortDispatcherFlowForScfToVpn(notification.getAddEventData().getDpnId(),
+ notification.getAddEventData().getVpnName(),
+ notification.getAddEventData().getRd(),
+ NwConstants.ADD_FLOW);
+
+ }
+
+ @Override
+ public void onRemoveDpnEvent(RemoveDpnEvent notification) {
+
+ programLPortDispatcherFlowForScfToVpn(notification.getRemoveEventData().getDpnId(),
+ notification.getRemoveEventData().getVpnName(),
+ notification.getRemoveEventData().getRd(),
+ NwConstants.DEL_FLOW);
+
+ }
+
+ private void programLPortDispatcherFlowForScfToVpn(BigInteger dpnId, String vpnName, String rd, int addOrRemove) {
+ String addedOrRemovedTxt = addOrRemove == NwConstants.ADD_FLOW ? " added " : " removed";
+ logger.debug("DpnToVpn {}event received: dpn={} vpn={} rd={}", addedOrRemovedTxt, dpnId, vpnName, rd);
+ if ( dpnId == null ) {
+ logger.warn("Dpn to Vpn {} event received, but no DPN specified in event", addedOrRemovedTxt);
+ return;
+ }
+
+ if ( vpnName == null ) {
+ logger.warn("Dpn to Vpn {} event received, but no VPN specified in event", addedOrRemovedTxt);
+ return;
+ }
+
+ if ( rd == null ) {
+ logger.warn("Dpn to Vpn {} event received, but no RD specified in event", addedOrRemovedTxt);
+ return;
+ }
+
+ Optional<Long> vpnPseudoLportTag = VpnServiceChainUtils.getVpnPseudoLportTag(broker, rd);
+ if ( !vpnPseudoLportTag.isPresent() || vpnPseudoLportTag.get() == null ) {
+ logger.debug("Dpn to Vpn {} event received: Could not find VpnPseudoLportTag for VPN name={} rd={}",
+ addedOrRemovedTxt, vpnName, rd);
+ return;
+ }
+ long vpnId = (addOrRemove == NwConstants.ADD_FLOW ) ? VpnServiceChainUtils.getVpnId(broker, vpnName)
+ : CloudServiceChainConstants.INVALID_VPN_TAG;
+ VpnServiceChainUtils.programLPortDispatcherFlowForScfToVpn(mdsalMgr, vpnId, dpnId,
+ vpnPseudoLportTag.get().intValue(), addOrRemove);
+ }
+}
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.netvirt.cloudservicechain.CloudServiceChainConstants;
+import org.opendaylight.netvirt.vpnmanager.VpnConstants;
import org.opendaylight.netvirt.vpnmanager.VpnUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
.child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
}
+ /**
+ * * Retrieves the VpnId searching by VpnInstanceName
+ *
+ * @param broker
+ * @param vpnName
+ * @return
+ */
+ public static long getVpnId(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
+ .l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id =
+ getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
+ .l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance =
+ MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ return vpnInstance.isPresent() ? vpnInstance.get().getVpnId() : VpnConstants.INVALID_ID;
+ }
+
/**
* Retrieves the VPN's Route Distinguisher out from the VpnName
* @param broker
return vpnVrfEntries;
}
+
+ /**
+ * Installs/removes a flow in LPortDispatcher table that is in charge of
+ * handling packets that falls back from SCF Pipeline to L3Vpn.
+ *
+ * @param mdsalManager MDSAL Util API accessor
+ * @param vpnId Dataplane identifier of the VPN, the Vrf Tag.
+ * @param dpId The DPN where the flow must be installed/removed
+ * @param vpnPseudoLportTag Dataplane identifier for the VpnPseudoPort
+ * @param addOrRemove States if the flow must be created or removed
+ */
+ public static void programLPortDispatcherFlowForScfToVpn(IMdsalApiManager mdsalManager, long vpnId, BigInteger dpId,
+ Integer vpnPseudoLportTag, int addOrRemove) {
+ Flow flow = buildLPortDispFromScfToL3VpnFlow(vpnId, dpId, vpnPseudoLportTag, addOrRemove);
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ mdsalManager.installFlow(dpId, flow);
+ } else {
+ mdsalManager.removeFlow(dpId, flow);
+ }
+ }
+
/**
* Build the flow that must be inserted when there is a ScHop whose egressPort is a VPN Pseudo Port. In that case,
* packets must be moved from the SCF to VPN Pipeline
* Flow matches: VpnPseudo port lPortTag + SI=L3VPN
* Actions: Write vrfTag in Metadata + goto FIB Table
- * @param vpnId Id of the Vpn that is the target of the packet
+ * @param vpnId Dataplane identifier of the VPN, the Vrf Tag.
* @param dpId The DPN where the flow must be installed/removed
- * @param addOrRemove
- * @param lportTag lportTag of the VpnPseudoLPort
- * @return
+ * @param lportTag Dataplane identifier for the VpnPseudoPort
+ * @param addOrRemove States if it must build a Flow to be created or
+ * removed
+ *
+ * @return the Flow object
*/
public static Flow buildLPortDispFromScfToL3VpnFlow(Long vpnId, BigInteger dpId, Integer lportTag,
int addOrRemove) {
/**
* @param lportTag
* @param serviceIndex
- * @return
+ * @return the list of Matches
*/
public static List<MatchInfo> buildMatchOnLportTagAndSI(Integer lportTag, short serviceIndex) {
List<MatchInfo> matches = new ArrayList<MatchInfo>();
}
/**
- * Builds a Flow entry that sets the VpnTag in metadata and sends to FIB table.
- * @param vpnTag
- * @return
+ * Builds a The Instructions that sets the VpnTag in metadata and sends to FIB table.
+ *
+ * @param vpnTag Dataplane identifier of the VPN.
+ * @return the list of Instructions
*/
public static List<Instruction> buildSetVrfTagAndGotoFibInstructions(Integer vpnTag) {
List<Instruction> result = new ArrayList<Instruction>();
}
+ public static Optional<Long> getVpnPseudoLportTag(DataBroker broker, String rd) {
+ VpnToPseudoPortTagKey key = new VpnToPseudoPortTagKey(rd);
+ InstanceIdentifier<VpnToPseudoPortTag> path = InstanceIdentifier.builder(VpnToPseudoPortTagData.class)
+ .child(VpnToPseudoPortTag.class, key)
+ .build();
+ Optional<VpnToPseudoPortTag> lPortTagOpc = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
+
+ return lPortTagOpc.isPresent() ? Optional.fromNullable(lPortTagOpc.get().getLportTag())
+ : Optional.<Long>absent();
+ }
+
/**
* Updates the mapping between VPNs and their respective VpnPseudoLport Tags
*
@Override
public java.lang.AutoCloseable createInstance() {
FibRpcService fibRpcService = getRpcregistryDependency().getRpcService(FibRpcService.class);
- CloudServiceChainProvider provider = new CloudServiceChainProvider();
- provider.setMdsalManager(getMdsalutilDependency());
- provider.setFibRpcService(fibRpcService);
+ CloudServiceChainProvider provider = new CloudServiceChainProvider(getNotificationServiceDependency(),
+ getMdsalutilDependency(),
+ fibRpcService );
getBrokerDependency().registerProvider(provider);
return provider;
}
}
}
}
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
}
}
}
VrfEntry ve = stubCreateDCGWVrfEntry();
ArgumentCaptor<Flow> argumentCaptor = ArgumentCaptor.forClass(Flow.class);
- verify(mdsalMgr, times(1)).installFlow((BigInteger)anyObject(), argumentCaptor.capture());
+ verify(mdsalMgr, times(2)).installFlow((BigInteger)anyObject(), argumentCaptor.capture());
List<Flow> installedFlowsCaptured = argumentCaptor.getAllValues();
- assert (installedFlowsCaptured.size() == 1);
+ assert (installedFlowsCaptured.size() == 2);
Flow expectedLportDispatcherFlowEntity = VpnServiceChainUtils.buildLPortDispFromScfToL3VpnFlow(vpnId,
new BigInteger(String.valueOf(dpnId)), dpnId, NwConstants.ADD_FLOW);
sn = optSn.get();
oldVpnId = sn.getVpnId();
List<String> ips = sn.getRouterInterfaceFixedIps();
- for (String ipValue : ips) {
- IpAddress ip = new IpAddress(ipValue.toCharArray());
- if (oldVpnId != null) {
- InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId
- .getValue(), ipValue);
- Optional<VpnPortipToPort> optionalVpnPort = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType
- .CONFIGURATION, id);
- if (optionalVpnPort.isPresent()) {
- removeVpnPortFixedIpToPort(oldVpnId.getValue(), ipValue);
+ if ( ips != null ) {
+ for (String ipValue : ips) {
+ IpAddress ip = new IpAddress(ipValue.toCharArray());
+ if (oldVpnId != null) {
+ InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), ipValue);
+ Optional<VpnPortipToPort> optionalVpnPort = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (optionalVpnPort.isPresent()) {
+ removeVpnPortFixedIpToPort(oldVpnId.getValue(), ipValue);
+ }
}
+ createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, sn.getRouterInterfaceName().getValue(),
+ sn.getRouterIntfMacAddress(), true, true, false);
}
- createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, sn.getRouterInterfaceName().getValue(),
- sn.getRouterIntfMacAddress(), true, true, false);
+ } else {
+ LOG.warn("No fixed IPs configured for router interface. VpnId={} subnetId={}", vpnId, subnet);
}
+
}
sn = updateSubnetNode(subnet, null, null, null, null, vpnId);
boolean isLockAcquired = false;