leaf interface-name {
type string;
}
+
+ leaf remote-dp-id {
+ type uint64;
+ }
}
}
package org.opendaylight.netvirt.policyservice;
+import java.math.BigInteger;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@PostConstruct
public void init() {
LOG.info("init");
- createIdPool();
+ createIdPools();
}
- private void createIdPool() {
- CreateIdPoolInput createPoolInput = new CreateIdPoolInputBuilder()
- .setPoolName(PolicyServiceConstants.POLICY_CLASSIFIER_POOL_NAME)
- .setLow(PolicyServiceConstants.POLICY_CLASSIFIER_LOW_ID)
- .setHigh(PolicyServiceConstants.POLICY_CLASSIFIER_HIGH_ID).build();
+ public long getPolicyClassifierId(String policyClassifierName) {
+ return allocateId(policyClassifierName, PolicyServiceConstants.POLICY_CLASSIFIER_POOL_NAME);
+ }
+
+ public void releasePolicyClassifierId(String policyClassifierName) {
+ releaseId(policyClassifierName, PolicyServiceConstants.POLICY_CLASSIFIER_POOL_NAME);
+ }
+
+ public long getPolicyClassifierGroupId(String policyClassifierName, BigInteger remoteDpId) {
+ return allocateId(getPolicyClassifierGroupKey(policyClassifierName, remoteDpId),
+ PolicyServiceConstants.POLICY_GROUP_POOL_NAME);
+ }
+
+ public void releasePolicyClassifierGroupId(String policyClassifierName, BigInteger remoteDpId) {
+ releaseId(getPolicyClassifierGroupKey(policyClassifierName, remoteDpId),
+ PolicyServiceConstants.POLICY_GROUP_POOL_NAME);
+ }
+
+ public static String getPolicyClassifierGroupKey(String policyClassifier, BigInteger remoteDpId) {
+ return policyClassifier + '-' + remoteDpId;
+ }
+
+ private void createIdPools() {
+ createIdPool(PolicyServiceConstants.POLICY_CLASSIFIER_POOL_NAME,
+ PolicyServiceConstants.POLICY_CLASSIFIER_LOW_ID, PolicyServiceConstants.POLICY_CLASSIFIER_HIGH_ID);
+ createIdPool(PolicyServiceConstants.POLICY_GROUP_POOL_NAME, PolicyServiceConstants.POLICY_GROUP_LOW_ID,
+ PolicyServiceConstants.POLICY_GROUP_HIGH_ID);
+ }
+
+ private void createIdPool(String poolName, long lowId, long highId) {
+ CreateIdPoolInput createPoolInput = new CreateIdPoolInputBuilder().setPoolName(poolName).setLow(lowId)
+ .setHigh(highId).build();
try {
Future<RpcResult<Void>> result = idManager.createIdPool(createPoolInput);
}
}
- public long getPolicyClassifierId(String policyClassifierName) {
- AllocateIdInput getIdInput = new AllocateIdInputBuilder()
- .setPoolName(PolicyServiceConstants.POLICY_CLASSIFIER_POOL_NAME).setIdKey(policyClassifierName).build();
+ private long allocateId(String key, String poolName) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(key).build();
try {
Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
RpcResult<AllocateIdOutput> rpcResult = result.get();
return rpcResult.getResult().getIdValue();
} catch (InterruptedException | ExecutionException e) {
- LOG.warn("Exception thrown while allocating id for key {}", policyClassifierName);
+ LOG.warn("Exception thrown while allocating id for key {}", key);
}
return PolicyServiceConstants.INVALID_ID;
}
- public void releasePolicyClassifierId(String policyClassifierName) {
- ReleaseIdInput idInput = new ReleaseIdInputBuilder()
- .setPoolName(PolicyServiceConstants.POLICY_CLASSIFIER_POOL_NAME).setIdKey(policyClassifierName).build();
+ private void releaseId(String key, String poolName) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(key).build();
try {
Future<RpcResult<Void>> result = idManager.releaseId(idInput);
RpcResult<Void> rpcResult = result.get();
if (!rpcResult.isSuccessful()) {
- LOG.warn("RPC Call to release {} returned with Errors {}", policyClassifierName, rpcResult.getErrors());
+ LOG.warn("RPC Call to release {} returned with Errors {}", key, rpcResult.getErrors());
}
} catch (InterruptedException | ExecutionException e) {
- LOG.warn("Exception thrown while releasing id for key {}", policyClassifierName);
+ LOG.warn("Exception thrown while releasing id for key {}", key);
}
}
-
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Hewlett Packard Enterprise, Co. 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.policyservice;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.netvirt.policyservice.util.PolicyServiceFlowUtil;
+import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Program policy classifier fast-failover groups per remote DPN.<br>
+ * Group id is allocated for combination of policy classifier and DPN id.<br>
+ * The group buckets are built based on the underlay networks defined for the
+ * policy classifier.<br>
+ * Each bucket in the group contains the tunnel egress actions for the actual
+ * tunnel interface associated with the underlay network.
+ *
+ */
+@Singleton
+public class PolicyRouteGroupProgrammer {
+ private static final Logger LOG = LoggerFactory.getLogger(PolicyRouteGroupProgrammer.class);
+
+ private final DataBroker dataBroker;
+ private final PolicyIdManager policyIdManager;
+ private final PolicyServiceUtil policyServiceUtil;
+ private final PolicyServiceFlowUtil policyServiceFlowUtil;
+ private final DataStoreJobCoordinator coordinator;
+
+ @Inject
+ public PolicyRouteGroupProgrammer(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
+ final PolicyServiceUtil policyServiceUtil, final PolicyServiceFlowUtil policyServiceFlowUtil) {
+ this.dataBroker = dataBroker;
+ this.policyIdManager = policyIdManager;
+ this.policyServiceUtil = policyServiceUtil;
+ this.policyServiceFlowUtil = policyServiceFlowUtil;
+ this.coordinator = DataStoreJobCoordinator.getInstance();
+ }
+
+ public void programPolicyClassifierGroups(String policyClassifier, List<BigInteger> localDpIds,
+ List<BigInteger> remoteDpIds, int addOrRemove) {
+ if (remoteDpIds == null || remoteDpIds.isEmpty()) {
+ LOG.debug("No remote DPNs found for policy classifier {}", policyClassifier);
+ return;
+ }
+
+ coordinator.enqueueJob(policyClassifier, () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ remoteDpIds.forEach(remoteDpId -> {
+ programPolicyClassifierGroups(policyClassifier, localDpIds, remoteDpId, tx, addOrRemove);
+ });
+ return Collections.singletonList(tx.submit());
+ });
+ }
+
+ public void programPolicyClassifierGroups(String policyClassifier, BigInteger dpId,
+ List<TunnelInterface> tunnelInterfaces, int addOrRemove) {
+ if (tunnelInterfaces == null) {
+ LOG.debug("No tunnel interfaces found for policy classifier {} DPN {}", policyClassifier, dpId);
+ return;
+
+ }
+ coordinator.enqueueJob(policyClassifier, () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ tunnelInterfaces.forEach(tunnelInterface -> {
+ BigInteger remoteDpId = tunnelInterface.getRemoteDpId();
+ programPolicyClassifierGroups(policyClassifier, Collections.singletonList(dpId), remoteDpId, tx,
+ addOrRemove);
+ });
+ return Collections.singletonList(tx.submit());
+ });
+ }
+
+ private void programPolicyClassifierGroups(String policyClassifier, List<BigInteger> localDpIds,
+ BigInteger remoteDpId, WriteTransaction tx, int addOrRemove) {
+ long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifier, remoteDpId);
+ if (groupId == PolicyServiceConstants.INVALID_ID) {
+ LOG.error("Failed to get group id for policy classifier {}", policyClassifier);
+ return;
+ }
+
+ if (localDpIds == null || localDpIds.isEmpty()) {
+ LOG.debug("No DPNs found for policy classifier {}", policyClassifier);
+ return;
+ }
+
+ String groupName = PolicyIdManager.getPolicyClassifierGroupKey(policyClassifier, remoteDpId);
+ localDpIds.forEach(srcDpId -> {
+ if (!remoteDpId.equals(srcDpId)) {
+ policyServiceFlowUtil.updateGroupToTx(srcDpId, groupId, groupName, GroupTypes.GroupFf, addOrRemove, tx);
+ }
+ });
+ }
+
+ public void programPolicyClassifierGroupBuckets(String policyClassifier, List<String> underlayNetworks,
+ int addOrRemove) {
+ if (underlayNetworks == null) {
+ return;
+ }
+
+ coordinator.enqueueJob(policyClassifier, () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+
+ for (int idx = 0; idx < underlayNetworks.size(); idx++) {
+ final int bucketId = idx;
+ String underlayNetwork = underlayNetworks.get(idx);
+ Optional.ofNullable(policyServiceUtil.getUnderlayNetworkDpnToInterfaces(underlayNetwork))
+ .map(dpnToInterfaceList -> {
+ dpnToInterfaceList.forEach(dpnToInterfaces -> {
+ BigInteger dpId = dpnToInterfaces.getDpId();
+ List<TunnelInterface> tunnelInterfaces = dpnToInterfaces.getTunnelInterface();
+ programPolicyClassifierGroupBuckets(policyClassifier, tunnelInterfaces, dpId, bucketId,
+ addOrRemove, tx);
+ });
+ return dpnToInterfaceList;
+ }).orElseGet(() -> {
+ LOG.debug("No DpnToInterface found for underlay network {}", underlayNetwork);
+ return null;
+ });
+ }
+ return Collections.singletonList(tx.submit());
+ });
+ }
+
+ public void programPolicyClassifierGroupBuckets(String policyClassifier, List<TunnelInterface> tunnelInterfaces,
+ BigInteger dpId, int bucketId, int addOrRemove) {
+ coordinator.enqueueJob(policyClassifier, () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ programPolicyClassifierGroupBuckets(policyClassifier, tunnelInterfaces, dpId, bucketId, addOrRemove, tx);
+ return Collections.singletonList(tx.submit());
+ });
+ }
+
+ private void programPolicyClassifierGroupBuckets(String policyClassifier, List<TunnelInterface> tunnelInterfaces,
+ BigInteger dpId, int bucketId, int addOrRemove, WriteTransaction tx) {
+ if (tunnelInterfaces == null) {
+ LOG.debug("No tunnel interfaces found for policy classifier {} DPN {}", policyClassifier, dpId);
+ return;
+ }
+
+ tunnelInterfaces.forEach(tunnelInterface -> {
+ String interfaceName = tunnelInterface.getInterfaceName();
+ BigInteger remoteDpId = tunnelInterface.getRemoteDpId();
+ long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifier, remoteDpId);
+ policyServiceFlowUtil.updateInterfaceBucketToTx(dpId, groupId, bucketId, interfaceName, addOrRemove, tx);
+ });
+ }
+}
public static final String POLICY_CLASSIFIER_POOL_NAME = "policyClassifierPool";
public static final Long POLICY_CLASSIFIER_LOW_ID = 1L;
public static final Long POLICY_CLASSIFIER_HIGH_ID = 30000L;
+ public static final String POLICY_GROUP_POOL_NAME = "policyGroupPool";
+ public static final Long POLICY_GROUP_LOW_ID = 310000L;
+ public static final Long POLICY_GROUP_HIGH_ID = 320000L;
public static final long INVALID_ID = 0;
public static final int POLICY_FLOW_PRIOPITY = 42;
}
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.netvirt.policyservice.PolicyAceFlowProgrammer;
import org.opendaylight.netvirt.policyservice.PolicyIdManager;
+import org.opendaylight.netvirt.policyservice.PolicyRouteGroupProgrammer;
import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.PolicyProfiles;
private final PolicyIdManager policyIdManager;
private final PolicyServiceUtil policyServiceUtil;
private final PolicyAceFlowProgrammer aceFlowProgrammer;
+ private final PolicyRouteGroupProgrammer routeGroupProgramer;
@Inject
public PolicyProfileChangeListener(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
- final PolicyServiceUtil policyServiceUtil, final PolicyAceFlowProgrammer aceFlowProgrammer) {
+ final PolicyServiceUtil policyServiceUtil, final PolicyAceFlowProgrammer aceFlowProgrammer,
+ final PolicyRouteGroupProgrammer routeGroupProgramer) {
this.dataBroker = dataBroker;
this.policyIdManager = policyIdManager;
this.policyServiceUtil = policyServiceUtil;
this.aceFlowProgrammer = aceFlowProgrammer;
+ this.routeGroupProgramer = routeGroupProgramer;
}
@Override
LOG.info("Policy profile {} removed", policyClassifier);
List<String> underlayNetworks = PolicyServiceUtil
.getUnderlayNetworksFromPolicyRoutes(policyProfile.getPolicyRoute());
- handlePolicyProfileUpdate(policyClassifier, underlayNetworks, false);
+ policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(underlayNetworks, policyClassifier, false);
+ List<BigInteger> dpnIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
+ List<BigInteger> remoteDpIds = policyServiceUtil.getUnderlayNetworksRemoteDpns(underlayNetworks);
+ routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpnIds, remoteDpIds, NwConstants.DEL_FLOW);
+ updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.DEL_FLOW);
policyIdManager.releasePolicyClassifierId(policyClassifier);
-
+ releasePolicyClassifierGroupIds(policyClassifier, dpnIds);
}
@Override
protected void update(InstanceIdentifier<PolicyProfile> key, PolicyProfile origPolicyProfile,
PolicyProfile updatedPolicyProfile) {
- LOG.info("Policy profile {} updated", updatedPolicyProfile.getPolicyClassifier());
List<String> origUnderlayNetworks = PolicyServiceUtil
.getUnderlayNetworksFromPolicyRoutes(origPolicyProfile.getPolicyRoute());
List<String> updatedUnderlayNetworks = PolicyServiceUtil
.getUnderlayNetworksFromPolicyRoutes(updatedPolicyProfile.getPolicyRoute());
-
List<String> removedUnderlayNetworks = new ArrayList<>(origUnderlayNetworks);
removedUnderlayNetworks.removeAll(updatedUnderlayNetworks);
- policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(removedUnderlayNetworks,
- origPolicyProfile.getPolicyClassifier(), false);
+ List<String> addedUnderlayNetworks = new ArrayList<>(updatedUnderlayNetworks);
+ addedUnderlayNetworks.removeAll(origUnderlayNetworks);
+
+ String policyClassifier = updatedPolicyProfile.getPolicyClassifier();
+ LOG.info("Policy profile {} updated", policyClassifier);
+ policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(removedUnderlayNetworks, policyClassifier, false);
+ policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(addedUnderlayNetworks, policyClassifier, true);
+
+ // rewrite all group buckets
+ routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, origUnderlayNetworks,
+ NwConstants.DEL_FLOW);
+ routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, updatedUnderlayNetworks,
+ NwConstants.ADD_FLOW);
updatedUnderlayNetworks.removeAll(origUnderlayNetworks);
policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(updatedUnderlayNetworks,
updatedPolicyProfile.getPolicyClassifier(), true);
+ updatePolicyAclRules(policyClassifier, updatedUnderlayNetworks, NwConstants.ADD_FLOW);
}
@Override
protected void add(InstanceIdentifier<PolicyProfile> key, PolicyProfile policyProfile) {
- LOG.info("Policy profile {} added", policyProfile.getPolicyClassifier());
+ String policyClassifier = policyProfile.getPolicyClassifier();
+ LOG.info("Policy profile {} added", policyClassifier);
List<String> underlayNetworks = PolicyServiceUtil
.getUnderlayNetworksFromPolicyRoutes(policyProfile.getPolicyRoute());
- handlePolicyProfileUpdate(policyProfile.getPolicyClassifier(), underlayNetworks, true);
+ policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(underlayNetworks, policyClassifier, true);
+ List<BigInteger> dpnIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
+ List<BigInteger> remoteDpIds = policyServiceUtil.getUnderlayNetworksRemoteDpns(underlayNetworks);
+ routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpnIds, remoteDpIds, NwConstants.ADD_FLOW);
+ routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, underlayNetworks,
+ NwConstants.ADD_FLOW);
+ updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.ADD_FLOW);
}
- private void handlePolicyProfileUpdate(String policyClassifier, List<String> underlayNetworks, boolean isAdded) {
- policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(underlayNetworks, policyClassifier, isAdded);
+ private void updatePolicyAclRules(String policyClassifier, List<String> underlayNetworks, int addOrRemove) {
List<PolicyAclRule> aclRules = policyServiceUtil.getPolicyClassifierAclRules(policyClassifier);
if (aclRules == null || aclRules.isEmpty()) {
LOG.debug("No policy ACE rules found for policy classifier {}", policyClassifier);
.getPolicyAce(aclRule.getAclName(), aceRule.getRuleName());
if (policyAceOpt.isPresent()) {
aceFlowProgrammer.programAceFlows(policyAceOpt.get(), policyClassifier, dpIds,
- isAdded ? NwConstants.ADD_FLOW : NwConstants.DEL_FLOW);
+ addOrRemove);
}
});
return aceRules;
});
}
+ private void releasePolicyClassifierGroupIds(String policyClassifier, List<BigInteger> dpnIds) {
+ dpnIds.forEach(dpnId -> {
+ policyIdManager.releasePolicyClassifierGroupId(policyClassifier, dpnId);
+ });
+ }
}
import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepInfoAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterface;
return;
}
- BigInteger dpnId = getTunnelDpnId(tunnelState);
+ BigInteger srcDpId = getTepDpnId(tunnelState.getSrcInfo());
+ BigInteger dstDpId = getTepDpnId(tunnelState.getDstInfo());
String tunnelInterfaceName = tunnelState.getTunnelInterfaceName();
- if (BigInteger.ZERO.equals(dpnId)) {
+ if (BigInteger.ZERO.equals(srcDpId) || BigInteger.ZERO.equals(dstDpId)) {
LOG.warn("No valid DPN found for tunnel {}", tunnelInterfaceName);
return;
}
IpAddress tunnelIp = getTunnelIp(tunnelState);
if (tunnelIp == null) {
- LOG.warn("No tunnel ip found for tunnel {} DPN {}", tunnelInterfaceName, dpnId);
+ LOG.warn("No tunnel ip found for tunnel {} DPN {}", tunnelInterfaceName, srcDpId);
return;
}
- String underlayNetwork = policyServiceUtil.getTunnelUnderlayNetwork(dpnId, tunnelIp);
+ String underlayNetwork = policyServiceUtil.getTunnelUnderlayNetwork(srcDpId, tunnelIp);
if (underlayNetwork == null) {
- LOG.debug("No underlay networks defined for tunnel {} DPN {}", tunnelInterfaceName, dpnId);
+ LOG.debug("No underlay networks defined for tunnel {} DPN {}", tunnelInterfaceName, srcDpId);
return;
}
- LOG.info("Handle tunnel state update for interface {} on DPN {} underlay network", tunnelInterfaceName, dpnId,
+ LOG.info("Handle tunnel state update for interface {} on DPN {} underlay network", tunnelInterfaceName, srcDpId,
underlayNetwork);
- policyServiceUtil.updateTunnelInterfaceForUnderlayNetwork(underlayNetwork, dpnId, tunnelInterfaceName, isAdded);
+ policyServiceUtil.updateTunnelInterfaceForUnderlayNetwork(underlayNetwork, srcDpId, dstDpId,
+ tunnelInterfaceName, isAdded);
}
private static boolean isVxlanTunnel(StateTunnelList tunnelState) {
&& tunnelState.getTransportType().isAssignableFrom(TunnelTypeVxlan.class);
}
- private static BigInteger getTunnelDpnId(StateTunnelList tunnelState) {
- if (tunnelState.getSrcInfo() != null && tunnelState.getSrcInfo().getTepDeviceId() != null) {
- return new BigInteger(tunnelState.getSrcInfo().getTepDeviceId());
+ private static BigInteger getTepDpnId(TepInfoAttributes tepInfoAttributes) {
+ if (tepInfoAttributes != null && tepInfoAttributes.getTepDeviceId() != null) {
+ return new BigInteger(tepInfoAttributes.getTepDeviceId());
}
return BigInteger.ZERO;
package org.opendaylight.netvirt.policyservice.listeners;
+
import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.netvirt.policyservice.PolicyAceFlowProgrammer;
+import org.opendaylight.netvirt.policyservice.PolicyRouteGroupProgrammer;
import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.UnderlayNetworks;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.UnderlayNetwork;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.PolicyProfile;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterface;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final DataBroker dataBroker;
private final PolicyServiceUtil policyServiceUtil;
private final PolicyAceFlowProgrammer aceFlowProgrammer;
+ private final PolicyRouteGroupProgrammer routeGroupProgramer;
@Inject
public UnderlayNetworkDpnListener(final DataBroker dataBroker, final PolicyServiceUtil policyServiceUtil,
- final PolicyAceFlowProgrammer aceFlowProgrammer) {
+ final PolicyAceFlowProgrammer aceFlowProgrammer, final PolicyRouteGroupProgrammer routeGroupProgramer) {
this.dataBroker = dataBroker;
this.policyServiceUtil = policyServiceUtil;
this.aceFlowProgrammer = aceFlowProgrammer;
+ this.routeGroupProgramer = routeGroupProgramer;
}
@Override
@Override
protected void remove(InstanceIdentifier<DpnToInterface> key, DpnToInterface dpnToInterface) {
+ String underlayNetwork = key.firstKeyOf(UnderlayNetwork.class).getNetworkName();
+ BigInteger dpId = dpnToInterface.getDpId();
+ List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
+ LOG.info("DPN {} removed from underlay network {} with tunnels {}", dpId, underlayNetwork, tunnelInterfaces);
+ List<PolicyProfile> profiles = policyServiceUtil.getUnderlayNetworkPolicyProfiles(underlayNetwork);
+ if (profiles == null || profiles.isEmpty()) {
+ LOG.debug("No policy profiles found for underlay network {}", underlayNetwork);
+ return;
+ }
+
+ populatePolicyGroupsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.DEL_FLOW);
+ populatePolicyAclRulesToDpn(underlayNetwork, dpId, profiles, NwConstants.DEL_FLOW);
}
@Override
protected void update(InstanceIdentifier<DpnToInterface> key, DpnToInterface origDpnToInterface,
DpnToInterface updatedDpnToInterface) {
+ String underlayNetwork = key.firstKeyOf(UnderlayNetwork.class).getNetworkName();
+ BigInteger dpId = updatedDpnToInterface.getDpId();
+ LOG.info("DPN {} updated to underlay network {} with tunnels {}", dpId, underlayNetwork,
+ updatedDpnToInterface.getTunnelInterface());
+ List<PolicyProfile> profiles = policyServiceUtil.getUnderlayNetworkPolicyProfiles(underlayNetwork);
+ if (profiles == null || profiles.isEmpty()) {
+ LOG.debug("No policy profiles found for underlay network {}", underlayNetwork);
+ return;
+ }
+
+ List<TunnelInterface> origTunnelInterfaces = Optional.ofNullable(origDpnToInterface.getTunnelInterface())
+ .orElse(Collections.emptyList());
+ List<TunnelInterface> updatedTunnelInterfaces = Optional.ofNullable(updatedDpnToInterface.getTunnelInterface())
+ .orElse(Collections.emptyList());
+ List<TunnelInterface> removedTunnelInterfaces = new ArrayList<>(origTunnelInterfaces);
+ removedTunnelInterfaces.removeAll(updatedTunnelInterfaces);
+ List<TunnelInterface> addedTunnelInterfaces = new ArrayList<>(updatedTunnelInterfaces);
+ addedTunnelInterfaces.removeAll(origTunnelInterfaces);
+
+ populatePolicyRoutesToDpn(underlayNetwork, profiles, removedTunnelInterfaces, dpId, NwConstants.DEL_FLOW);
+ populatePolicyRoutesToDpn(underlayNetwork, profiles, addedTunnelInterfaces, dpId, NwConstants.ADD_FLOW);
}
@Override
protected void add(InstanceIdentifier<DpnToInterface> key, DpnToInterface dpnToInterface) {
String underlayNetwork = key.firstKeyOf(UnderlayNetwork.class).getNetworkName();
BigInteger dpId = dpnToInterface.getDpId();
- LOG.info("DPN {} added to underlay network {}", dpId, underlayNetwork);
- populatePolicyRulesToDpn(underlayNetwork, dpId);
-
- }
-
- private void populatePolicyRulesToDpn(String underlayNetwork, BigInteger dpId) {
+ List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
+ LOG.info("DPN {} added to underlay network {} with tunnels {}", dpId, underlayNetwork, tunnelInterfaces);
List<PolicyProfile> profiles = policyServiceUtil.getUnderlayNetworkPolicyProfiles(underlayNetwork);
if (profiles == null || profiles.isEmpty()) {
LOG.debug("No policy profiles found for underlay network {}", underlayNetwork);
return;
}
+ populatePolicyGroupsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
+ populatePolicyRoutesToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
+ populatePolicyAclRulesToDpn(underlayNetwork, dpId, profiles, NwConstants.ADD_FLOW);
+ }
+
+ private void populatePolicyGroupsToDpn(String underlayNetwork, List<PolicyProfile> profiles,
+ List<TunnelInterface> tunnelInterfaces, BigInteger dpId, int addOrRemove) {
+ profiles.forEach(profile -> {
+ String policyClassifier = profile.getPolicyClassifier();
+ routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpId, tunnelInterfaces, addOrRemove);
+ });
+ }
+
+ private void populatePolicyRoutesToDpn(String underlayNetwork, List<PolicyProfile> profiles,
+ List<TunnelInterface> tunnelInterfaces, BigInteger dpId, int addOrRemove) {
+ profiles.forEach(profile -> {
+ String policyClassifier = profile.getPolicyClassifier();
+ Optional.ofNullable(policyServiceUtil.getUnderlayNetworksForClassifier(policyClassifier))
+ .map(underlayNetworks -> {
+ int bucketId = underlayNetworks.indexOf(underlayNetwork);
+ if (bucketId != -1) {
+ routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, tunnelInterfaces,
+ dpId, bucketId, addOrRemove);
+ } else {
+ LOG.warn("Policy classifier {} routes do not contain {}", policyClassifier,
+ underlayNetwork);
+ }
+ return underlayNetworks;
+ }).orElseGet(() -> {
+ LOG.warn("No underlay networks found for classifier {} while populating {} flows",
+ policyClassifier, underlayNetwork);
+ return null;
+ });
+ });
+ }
+
+ private void populatePolicyAclRulesToDpn(String underlayNetwork, BigInteger dpId, List<PolicyProfile> profiles,
+ int addOrRemove) {
profiles.forEach(profile -> {
String policyClassifier = profile.getPolicyClassifier();
Optional.ofNullable(policyServiceUtil.getPolicyClassifierAclRules(policyClassifier)).ifPresent(aclRules -> {
aclRules.forEach(aclRule -> {
- Optional.ofNullable(aclRule.getAceRule()).ifPresent(aceRules -> {
+ Optional.ofNullable(aclRule.getAceRule()).map(aceRules -> {
aceRules.forEach(aceRule -> {
com.google.common.base.Optional<Ace> policyAceOpt = policyServiceUtil
.getPolicyAce(aclRule.getAclName(), aceRule.getRuleName());
LOG.warn("Failed to get ACL {} rule {}", aclRule.getAclName(), aceRule.getRuleName());
}
});
+ return aceRules;
+ }).orElseGet(() -> {
+ LOG.debug("No ACE rule found for policy ACL {}", aclRule.getAclName());
+ return null;
});
});
});
});
}
-
}
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
+import org.opendaylight.genius.mdsalutil.ActionInfo;
import org.opendaylight.genius.mdsalutil.FlowEntity;
+import org.opendaylight.genius.mdsalutil.GroupEntity;
import org.opendaylight.genius.mdsalutil.InstructionInfo;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.mdsalutil.MatchInfoBase;
import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.policyservice.PolicyServiceConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@Singleton
public class PolicyServiceFlowUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(PolicyServiceFlowUtil.class);
private final IMdsalApiManager mdsalManager;
+ private final IInterfaceManager interfaceManager;
@Inject
- public PolicyServiceFlowUtil(final IMdsalApiManager mdsalManager) {
+ public PolicyServiceFlowUtil(final IMdsalApiManager mdsalManager, final IInterfaceManager interfaceManager) {
this.mdsalManager = mdsalManager;
+ this.interfaceManager = interfaceManager;
}
public List<InstructionInfo> getPolicyClassifierInstructions(long policyClassifierId) {
mdsalManager.removeFlowToTx(flowEntity, tx);
}
}
+
+ public void updateGroupToTx(BigInteger dpId, long groupId, String groupName, GroupTypes groupType, int addOrRemove,
+ WriteTransaction tx) {
+ if (addOrRemove == NwConstants.ADD_FLOW && mdsalManager.groupExists(dpId, groupId)) {
+ LOG.trace("Group {} id {} already exists", groupName, groupId);
+ return;
+ }
+
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpId, groupId, groupName, groupType,
+ Collections.emptyList());
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ LOG.debug("Add group {} to DPN {}", groupId, dpId);
+ mdsalManager.addGroupToTx(groupEntity, tx);
+ } else {
+ LOG.debug("Remove group {} from DPN {}", groupId, dpId);
+ mdsalManager.removeGroupToTx(groupEntity, tx);
+ }
+ }
+
+ public void updateInterfaceBucketToTx(BigInteger dpId, long groupId, int bucketId, String interfaceName,
+ int addOrRemove, WriteTransaction tx) {
+ if (groupId == PolicyServiceConstants.INVALID_ID) {
+ LOG.error("No valid group id found for interface {} DPN {}", interfaceName, dpId);
+ return;
+ }
+
+ if (addOrRemove == NwConstants.DEL_FLOW) {
+ LOG.debug("Remove bucket for interface {} from group {} DPN {}", interfaceName, groupId, dpId);
+ mdsalManager.removeBucketToTx(dpId, groupId, bucketId, tx);
+ return;
+ }
+
+ List<ActionInfo> egressActions = interfaceManager.getInterfaceEgressActions(interfaceName);
+ if (egressActions == null || egressActions.isEmpty()) {
+ LOG.error("Failed to get egress actions for interface {} DPN {}", interfaceName, dpId);
+ return;
+ }
+
+ Long port = interfaceManager.getPortForInterface(interfaceName);
+ if (port == null) {
+ LOG.error("Failed to get port for interface {}", interfaceName);
+ return;
+ }
+
+ Bucket bucket = MDSALUtil.buildBucket(MDSALUtil.buildActions(egressActions), MDSALUtil.GROUP_WEIGHT, bucketId,
+ port, MDSALUtil.WATCH_GROUP);
+ LOG.debug("Add bucket for interface {} to group {} DPN {}", interfaceName, groupId, dpId);
+ mdsalManager.addBucketToTx(dpId, groupId, bucket, tx);
+ }
}
}
}
- public void updateTunnelInterfaceForUnderlayNetwork(String underlayNetwork, BigInteger dpId, String tunnelInterface,
- boolean isAdded) {
+ public void updateTunnelInterfaceForUnderlayNetwork(String underlayNetwork, BigInteger srcDpId, BigInteger dstDpId,
+ String tunnelInterfaceName, boolean isAdded) {
coordinator.enqueueJob(underlayNetwork, () -> {
- InstanceIdentifier<TunnelInterface> identifier = getUnderlyNetworkTunnelIdentifier(underlayNetwork, dpId,
- tunnelInterface);
+ InstanceIdentifier<TunnelInterface> identifier = getUnderlyNetworkTunnelIdentifier(underlayNetwork, srcDpId,
+ tunnelInterfaceName);
WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
if (isAdded) {
- tx.merge(LogicalDatastoreType.OPERATIONAL, identifier,
- new TunnelInterfaceBuilder().setInterfaceName(tunnelInterface).build(), true);
- LOG.info("Add tunnel {} on DPN {} to underlay network {}", tunnelInterface, dpId, underlayNetwork);
+ TunnelInterface tunnelInterface = new TunnelInterfaceBuilder().setInterfaceName(tunnelInterfaceName)
+ .setRemoteDpId(dstDpId).build();
+ tx.merge(LogicalDatastoreType.OPERATIONAL, identifier, tunnelInterface, true);
+ LOG.info("Add tunnel {} on DPN {} to underlay network {}", tunnelInterfaceName, srcDpId,
+ underlayNetwork);
} else {
tx.delete(LogicalDatastoreType.OPERATIONAL, identifier);
- LOG.info("Remove tunnel {} from DPN {} on underlay network {}", tunnelInterface, dpId, underlayNetwork);
+ LOG.info("Remove tunnel {} from DPN {} on underlay network {}", tunnelInterfaceName, srcDpId,
+ underlayNetwork);
}
return Collections.singletonList(tx.submit());
});
.collect(Collectors.toList());
}
+ public List<BigInteger> getUnderlayNetworksRemoteDpns(List<String> underlayNetworks) {
+ if (underlayNetworks == null) {
+ return Collections.emptyList();
+ }
+
+ return underlayNetworks.stream().map(t -> getUnderlayNetworkRemoteDpns(t)).flatMap(t -> t.stream()).distinct()
+ .collect(Collectors.toList());
+ }
+
public String getTunnelUnderlayNetwork(BigInteger dpId, IpAddress tunnelIp) {
Node ovsdbNode = bridgeManager.getBridgeNode(dpId);
if (ovsdbNode == null) {
return dpnToInterfaces.stream().map(t -> t.getDpId()).collect(Collectors.toList());
}
+ public static List<BigInteger> getRemoteDpnsFromDpnToInterfaces(List<DpnToInterface> dpnToInterfaces) {
+ if (dpnToInterfaces == null) {
+ return Collections.emptyList();
+ }
+
+ return dpnToInterfaces.stream().map(dpnToInterface -> getRemoteDpnsFromDpnToInterface(dpnToInterface))
+ .flatMap(t -> t.stream()).distinct().collect(Collectors.toList());
+ }
+
+ public static List<BigInteger> getRemoteDpnsFromDpnToInterface(DpnToInterface dpnToInterface) {
+ List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
+ if (tunnelInterfaces == null) {
+ return Collections.emptyList();
+ }
+
+ return tunnelInterfaces.stream().map(tunnelInterface -> tunnelInterface.getRemoteDpId())
+ .collect(Collectors.toList());
+ }
+
public static List<String> getUnderlayNetworksFromPolicyRoutes(List<PolicyRoute> policyRoutes) {
if (policyRoutes == null) {
return Collections.emptyList();
return aclType != null && aclType.isAssignableFrom(PolicyAcl.class);
}
- private List<BigInteger> getUnderlayNetworkDpns(String underlayNetwork) {
- InstanceIdentifier<UnderlayNetwork> identifier = getUnderlyNetworkIdentifier(underlayNetwork);
+ public List<DpnToInterface> getUnderlayNetworkDpnToInterfaces(String underlayNetwork) {
+ InstanceIdentifier<UnderlayNetwork> identifier = InstanceIdentifier.create(UnderlayNetworks.class)
+ .child(UnderlayNetwork.class, new UnderlayNetworkKey(underlayNetwork));
try {
Optional<UnderlayNetwork> optUnderlayNetwork = SingleTransactionDataBroker.syncReadOptional(dataBroker,
LogicalDatastoreType.OPERATIONAL, identifier);
- return optUnderlayNetwork.isPresent()
- ? getDpnsFromDpnToInterfaces(optUnderlayNetwork.get().getDpnToInterface())
+ return optUnderlayNetwork.isPresent() ? optUnderlayNetwork.get().getDpnToInterface()
: Collections.emptyList();
} catch (ReadFailedException e) {
LOG.warn("Failed to get DPNs for underlay network {}", underlayNetwork);
.netvirt.policy.rev170207.underlay.networks.underlay.network
.PolicyProfileKey(policyClassifier));
}
+
+ public List<BigInteger> getUnderlayNetworkDpns(String underlayNetwork) {
+ return getDpnsFromDpnToInterfaces(getUnderlayNetworkDpnToInterfaces(underlayNetwork));
+ }
+
+ public List<BigInteger> getUnderlayNetworkRemoteDpns(String underlayNetwork) {
+ return getRemoteDpnsFromDpnToInterfaces(getUnderlayNetworkDpnToInterfaces(underlayNetwork));
+ }
}
interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" />
<reference id="iMdsalApiManager"
interface="org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager" />
+ <reference id="iInterfaceManager"
+ interface="org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager" />
<reference id="iAclServiceUtil"
interface="org.opendaylight.netvirt.aclservice.api.utils.IAclServiceUtil" />
<reference id="iElanBridgeManager"