package org.opendaylight.netvirt.policyservice;
+import com.google.common.collect.ImmutableMap;
+
import java.math.BigInteger;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
private static final Logger LOG = LoggerFactory.getLogger(PolicyIdManager.class);
private final IdManagerService idManager;
+ private final Map<String,
+ Map<String, Long>> idCache = ImmutableMap.of(//
+ PolicyServiceConstants.POLICY_CLASSIFIER_POOL_NAME, new ConcurrentHashMap<String, Long>(),
+ PolicyServiceConstants.POLICY_GROUP_POOL_NAME, new ConcurrentHashMap<String, Long>());
@Inject
public PolicyIdManager(final IdManagerService idManager) {
}
private long allocateId(String key, String poolName) {
+ Long id = idCache.get(poolName).get(key);
+ if (id != null) {
+ return id;
+ }
+
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();
+ Long idValue = rpcResult.getResult().getIdValue();
+ if (idValue != null) {
+ idCache.get(poolName).put(key, idValue);
+ return idValue;
+ }
} catch (InterruptedException | ExecutionException e) {
LOG.warn("Exception thrown while allocating id for key {}", key);
}
}
private void releaseId(String key, String poolName) {
+ idCache.get(poolName).remove(key);
ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(key).build();
try {
Future<RpcResult<Void>> result = idManager.releaseId(idInput);
--- /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 com.google.common.base.Optional;
+
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+
+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.genius.mdsalutil.InstructionInfo;
+import org.opendaylight.genius.mdsalutil.MatchInfoBase;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Program POLICY_ROUTING_TABLE flows. Each flow is composed from<br>
+ * * OF matches - logical tunnel lport tag and policy classifier metadata
+ * bits<br>
+ * * OF actions - set policy classifier group id based on the remote DPN
+ * associated with the logical tunnel.
+ *
+ */
+@Singleton
+public class PolicyRouteFlowProgrammer {
+ private static final Logger LOG = LoggerFactory.getLogger(PolicyRouteFlowProgrammer.class);
+
+ private final DataBroker dataBroker;
+ private final PolicyIdManager policyIdManager;
+ private final PolicyServiceUtil policyServiceUtil;
+ private final PolicyServiceFlowUtil policyFlowUtil;
+ private final DataStoreJobCoordinator coordinator;
+
+ @Inject
+ public PolicyRouteFlowProgrammer(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
+ final PolicyServiceUtil policyServiceUtil, final PolicyServiceFlowUtil policyFlowUtil) {
+ this.dataBroker = dataBroker;
+ this.policyIdManager = policyIdManager;
+ this.policyServiceUtil = policyServiceUtil;
+ this.policyFlowUtil = policyFlowUtil;
+ this.coordinator = DataStoreJobCoordinator.getInstance();
+ }
+
+ public void programPolicyClassifierFlows(String policyClassifierName, List<BigInteger> localDpIds,
+ List<BigInteger> remoteDpIds, int addOrRemove) {
+ long policyClassifierId = policyIdManager.getPolicyClassifierId(policyClassifierName);
+ if (policyClassifierId == PolicyServiceConstants.INVALID_ID) {
+ LOG.error("Failed to get policy classifier id for classifier {}", policyClassifierName);
+ return;
+ }
+
+ coordinator.enqueueJob(policyClassifierName, () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ remoteDpIds.forEach(remoteDpId -> {
+ long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifierName, remoteDpId);
+ if (groupId != PolicyServiceConstants.INVALID_ID) {
+ List<InstructionInfo> instructions = policyFlowUtil.getPolicyRouteInstructions(groupId);
+ localDpIds.forEach(localDpId -> {
+ if (!remoteDpId.equals(localDpId)) {
+ programPolicyClassifierFlow(policyClassifierName, policyClassifierId, instructions,
+ localDpId, remoteDpId, tx, addOrRemove);
+ }
+ });
+ } else {
+ LOG.error("Failed to get group id for policy classifier {} DPN {}", policyClassifierName,
+ remoteDpId);
+ }
+ });
+ return Collections.singletonList(tx.submit());
+ });
+
+ }
+
+ public void programPolicyClassifierFlow(String policyClassifierName, BigInteger localDpId, BigInteger remoteDpId,
+ int addOrRemove) {
+ programPolicyClassifierFlow(policyClassifierName, localDpId, remoteDpId, addOrRemove, false);
+ }
+
+ public void programPolicyClassifierFlow(String policyClassifierName, BigInteger localDpId, BigInteger remoteDpId,
+ int addOrRemove, boolean createIfMissing) {
+ long policyClassifierId = policyIdManager.getPolicyClassifierId(policyClassifierName);
+ if (policyClassifierId == PolicyServiceConstants.INVALID_ID) {
+ LOG.error("Failed to get policy classifier id for classifier {}", policyClassifierName);
+ return;
+ }
+
+ long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifierName, remoteDpId);
+ if (groupId == PolicyServiceConstants.INVALID_ID) {
+ LOG.error("Failed to get group id for policy classifier {} DPN {}", policyClassifierName, remoteDpId);
+ return;
+ }
+
+ if (addOrRemove == NwConstants.ADD_FLOW && createIfMissing) {
+ addPolicyClassifierGroup(policyClassifierName, localDpId, remoteDpId, addOrRemove, groupId);
+ }
+
+ List<InstructionInfo> instructions = policyFlowUtil.getPolicyRouteInstructions(groupId);
+ coordinator.enqueueJob(policyClassifierName, () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ programPolicyClassifierFlow(policyClassifierName, policyClassifierId, instructions, localDpId, remoteDpId,
+ tx, addOrRemove);
+ return Collections.singletonList(tx.submit());
+ });
+
+ }
+
+ private void programPolicyClassifierFlow(String policyClassifierName, long policyClassifierId,
+ List<InstructionInfo> instructions, BigInteger localDpId, BigInteger remoteDpId, WriteTransaction tx,
+ int addOrRemove) {
+ Optional<Integer> lportTagOpt = policyServiceUtil.getLogicalTunnelLportTag(localDpId, remoteDpId);
+ if (!lportTagOpt.isPresent()) {
+ LOG.debug("Missing lport-tag for policy classifier {} logical tunnel for source DPN {} dst DPN {}",
+ policyClassifierName, localDpId, remoteDpId);
+ return;
+ }
+
+ List<MatchInfoBase> matches = policyFlowUtil.getPolicyRouteMatches(policyClassifierId, lportTagOpt.get());
+ LOG.debug("{} policy classifier {} route on source DPN {} dest DPN {}",
+ addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", policyClassifierName, localDpId,
+ remoteDpId);
+ policyFlowUtil.updateFlowToTx(localDpId, NwConstants.EGRESS_POLICY_ROUTING_TABLE,
+ PolicyIdManager.getPolicyClassifierGroupKey(policyClassifierName, remoteDpId),
+ PolicyServiceConstants.POLICY_FLOW_PRIOPITY, NwConstants.EGRESS_POLICY_ROUTING_COOKIE, matches,
+ instructions, addOrRemove, tx);
+ }
+
+ private void addPolicyClassifierGroup(String policyClassifierName, BigInteger localDpId, BigInteger remoteDpId,
+ int addOrRemove, long groupId) {
+ coordinator.enqueueJob(policyClassifierName, () -> {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ policyFlowUtil.updateGroupToTx(localDpId, groupId,
+ PolicyIdManager.getPolicyClassifierGroupKey(policyClassifierName, remoteDpId), GroupTypes.GroupFf,
+ addOrRemove, tx);
+ return Collections.singletonList(tx.submit());
+ });
+ }
+
+}
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.netvirt.policyservice.PolicyAceFlowProgrammer;
import org.opendaylight.netvirt.policyservice.PolicyIdManager;
+import org.opendaylight.netvirt.policyservice.PolicyRouteFlowProgrammer;
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;
private final PolicyIdManager policyIdManager;
private final PolicyServiceUtil policyServiceUtil;
private final PolicyAceFlowProgrammer aceFlowProgrammer;
+ private final PolicyRouteFlowProgrammer routeFlowProgrammer;
private final PolicyRouteGroupProgrammer routeGroupProgramer;
@Inject
public PolicyProfileChangeListener(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
final PolicyServiceUtil policyServiceUtil, final PolicyAceFlowProgrammer aceFlowProgrammer,
- final PolicyRouteGroupProgrammer routeGroupProgramer) {
+ final PolicyRouteFlowProgrammer routeFlowProgrammer, final PolicyRouteGroupProgrammer routeGroupProgramer) {
this.dataBroker = dataBroker;
this.policyIdManager = policyIdManager;
this.policyServiceUtil = policyServiceUtil;
this.aceFlowProgrammer = aceFlowProgrammer;
+ this.routeFlowProgrammer = routeFlowProgrammer;
this.routeGroupProgramer = routeGroupProgramer;
}
List<BigInteger> remoteDpIds = policyServiceUtil.getUnderlayNetworksRemoteDpns(underlayNetworks);
routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpnIds, remoteDpIds, NwConstants.DEL_FLOW);
updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.DEL_FLOW);
+ routeFlowProgrammer.programPolicyClassifierFlows(policyClassifier, dpnIds, remoteDpIds, NwConstants.DEL_FLOW);
policyIdManager.releasePolicyClassifierId(policyClassifier);
releasePolicyClassifierGroupIds(policyClassifier, dpnIds);
}
routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, underlayNetworks,
NwConstants.ADD_FLOW);
updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.ADD_FLOW);
+ routeFlowProgrammer.programPolicyClassifierFlows(policyClassifier, dpnIds, remoteDpIds, NwConstants.ADD_FLOW);
}
private void updatePolicyAclRules(String policyClassifier, List<String> underlayNetworks, int addOrRemove) {
package org.opendaylight.netvirt.policyservice.listeners;
import java.math.BigInteger;
+import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.netvirt.policyservice.PolicyRouteFlowProgrammer;
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.TunnelTypeLogicalGroup;
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.policy.profiles.PolicyProfile;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterface;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
/**
* Listen on operational {@link StateTunnelList} changes and update
- * {@link DpnToInterface} accordingly for tunnel interfaces of type VxLAN.
+ * {@link DpnToInterface} accordingly for tunnel interfaces of type VxLAN.<br>
+ * When logical tunnel interface state is added or removed, the corresponding
+ * POLICY_ROUTING_TABLE entries will be updated.
*
*/
@Singleton
private final DataBroker dataBroker;
private final PolicyServiceUtil policyServiceUtil;
+ private final PolicyRouteFlowProgrammer routeFlowProgrammer;
@Inject
- public TunnelStateChangeListener(DataBroker dataBroker, final PolicyServiceUtil policyServiceUtil) {
+ public TunnelStateChangeListener(DataBroker dataBroker, final PolicyServiceUtil policyServiceUtil,
+ final PolicyRouteFlowProgrammer routeFlowProgrammer) {
this.dataBroker = dataBroker;
this.policyServiceUtil = policyServiceUtil;
+ this.routeFlowProgrammer = routeFlowProgrammer;
}
@Override
@Override
protected void remove(InstanceIdentifier<StateTunnelList> key, StateTunnelList tunnelState) {
- LOG.debug("Tunnel state {} removed", tunnelState);
- handleTunnelUpdate(tunnelState, false);
+ LOG.trace("Tunnel state {} removed", tunnelState);
+ if (isLogicalGroupTunnel(tunnelState)) {
+ populatePolicyRoutesToDpn(tunnelState, NwConstants.DEL_FLOW);
+ } else if (isVxlanTunnel(tunnelState)) {
+ updateTunnelToUnderlayNetworkOperDs(tunnelState, false);
+ }
}
@Override
@Override
protected void add(InstanceIdentifier<StateTunnelList> key, StateTunnelList tunnelState) {
- LOG.debug("Tunnel state {} added", tunnelState);
- handleTunnelUpdate(tunnelState, true);
+ LOG.trace("Tunnel state {} added", tunnelState);
+ if (isVxlanTunnel(tunnelState)) {
+ updateTunnelToUnderlayNetworkOperDs(tunnelState, true);
+ } else if (isLogicalGroupTunnel(tunnelState)) {
+ populatePolicyRoutesToDpn(tunnelState, NwConstants.ADD_FLOW);
+ }
}
- private void handleTunnelUpdate(StateTunnelList tunnelState, boolean isAdded) {
- if (!isVxlanTunnel(tunnelState)) {
+ private void populatePolicyRoutesToDpn(StateTunnelList tunnelState, int addOrRemove) {
+ BigInteger srcDpId = getTepDpnId(tunnelState.getSrcInfo());
+ BigInteger dstDpId = getTepDpnId(tunnelState.getDstInfo());
+ String tunnelInterfaceName = tunnelState.getTunnelInterfaceName();
+ if (BigInteger.ZERO.equals(srcDpId) || BigInteger.ZERO.equals(dstDpId)) {
+ LOG.warn("No valid DPN found for logical tunnel {}", tunnelInterfaceName);
+ return;
+ }
+
+ List<PolicyProfile> policyProfiles = policyServiceUtil.getAllPolicyProfiles();
+ if (policyProfiles == null || policyProfiles.isEmpty()) {
+ LOG.debug("No policy profiles found on addition of {}", tunnelInterfaceName);
return;
}
+ policyProfiles.forEach(policyProfile -> {
+ String policyClassifier = policyProfile.getPolicyClassifier();
+ List<String> underlayNetworks = PolicyServiceUtil
+ .getUnderlayNetworksFromPolicyRoutes(policyProfile.getPolicyRoute());
+ underlayNetworks.forEach(underlayNetwork -> {
+ if (policyServiceUtil.underlayNetworkContainsDpn(underlayNetwork, srcDpId)
+ && policyServiceUtil.underlayNetworkContainsRemoteDpn(underlayNetwork, dstDpId)) {
+ routeFlowProgrammer.programPolicyClassifierFlow(policyClassifier, srcDpId, dstDpId, addOrRemove,
+ true);
+ } else {
+ LOG.trace("logical tunnel {} source DPN {} dest DPN {} not associated to policy classifier {}",
+ tunnelInterfaceName, srcDpId, dstDpId, policyClassifier);
+ }
+ });
+ });
+ }
+
+ private void updateTunnelToUnderlayNetworkOperDs(StateTunnelList tunnelState, boolean isAdded) {
BigInteger srcDpId = getTepDpnId(tunnelState.getSrcInfo());
BigInteger dstDpId = getTepDpnId(tunnelState.getDstInfo());
String tunnelInterfaceName = tunnelState.getTunnelInterfaceName();
return;
}
- LOG.info("Handle tunnel state update for interface {} on DPN {} underlay network", tunnelInterfaceName, srcDpId,
- underlayNetwork);
+ LOG.info("Handle tunnel state update for interface {} on DPN {} underlay network {}", tunnelInterfaceName,
+ srcDpId, underlayNetwork);
policyServiceUtil.updateTunnelInterfaceForUnderlayNetwork(underlayNetwork, srcDpId, dstDpId,
tunnelInterfaceName, isAdded);
}
&& tunnelState.getTransportType().isAssignableFrom(TunnelTypeVxlan.class);
}
+ private static boolean isLogicalGroupTunnel(StateTunnelList tunnelState) {
+ return tunnelState.getTransportType() != null
+ && tunnelState.getTransportType().isAssignableFrom(TunnelTypeLogicalGroup.class);
+ }
+
private static BigInteger getTepDpnId(TepInfoAttributes tepInfoAttributes) {
if (tepInfoAttributes != null && tepInfoAttributes.getTepDeviceId() != null) {
return new BigInteger(tepInfoAttributes.getTepDeviceId());
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.netvirt.policyservice.PolicyAceFlowProgrammer;
+import org.opendaylight.netvirt.policyservice.PolicyRouteFlowProgrammer;
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;
private final DataBroker dataBroker;
private final PolicyServiceUtil policyServiceUtil;
private final PolicyAceFlowProgrammer aceFlowProgrammer;
+ private final PolicyRouteFlowProgrammer routeFlowProgrammer;
private final PolicyRouteGroupProgrammer routeGroupProgramer;
@Inject
public UnderlayNetworkDpnListener(final DataBroker dataBroker, final PolicyServiceUtil policyServiceUtil,
- final PolicyAceFlowProgrammer aceFlowProgrammer, final PolicyRouteGroupProgrammer routeGroupProgramer) {
+ final PolicyAceFlowProgrammer aceFlowProgrammer, final PolicyRouteFlowProgrammer routeFlowProgrammer,
+ final PolicyRouteGroupProgrammer routeGroupProgramer) {
this.dataBroker = dataBroker;
this.policyServiceUtil = policyServiceUtil;
this.aceFlowProgrammer = aceFlowProgrammer;
+ this.routeFlowProgrammer = routeFlowProgrammer;
this.routeGroupProgramer = routeGroupProgramer;
}
return;
}
- populatePolicyGroupsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.DEL_FLOW);
- populatePolicyAclRulesToDpn(underlayNetwork, dpId, profiles, NwConstants.DEL_FLOW);
+ populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.DEL_FLOW);
}
@Override
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);
+ populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, removedTunnelInterfaces, dpId, NwConstants.DEL_FLOW);
+ populatePolicyGroupsToDpn(underlayNetwork, profiles, addedTunnelInterfaces, dpId, NwConstants.ADD_FLOW);
+ populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, addedTunnelInterfaces, dpId, NwConstants.ADD_FLOW);
}
@Override
}
populatePolicyGroupsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
- populatePolicyRoutesToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
+ populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
populatePolicyAclRulesToDpn(underlayNetwork, dpId, profiles, NwConstants.ADD_FLOW);
+ populatePolicyRoutesToDpn(profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
}
private void populatePolicyGroupsToDpn(String underlayNetwork, List<PolicyProfile> profiles,
});
}
- private void populatePolicyRoutesToDpn(String underlayNetwork, List<PolicyProfile> profiles,
+ private void populatePolicyGroupBucketsToDpn(String underlayNetwork, List<PolicyProfile> profiles,
List<TunnelInterface> tunnelInterfaces, BigInteger dpId, int addOrRemove) {
profiles.forEach(profile -> {
String policyClassifier = profile.getPolicyClassifier();
com.google.common.base.Optional<Ace> policyAceOpt = policyServiceUtil
.getPolicyAce(aclRule.getAclName(), aceRule.getRuleName());
if (policyAceOpt.isPresent()) {
- aceFlowProgrammer.programAceFlows(policyAceOpt.get(), dpId, NwConstants.ADD_FLOW);
+ aceFlowProgrammer.programAceFlows(policyAceOpt.get(), dpId, addOrRemove);
} else {
LOG.warn("Failed to get ACL {} rule {}", aclRule.getAclName(), aceRule.getRuleName());
}
});
});
}
+
+ private void populatePolicyRoutesToDpn(List<PolicyProfile> profiles, List<TunnelInterface> tunnelInterfaces,
+ BigInteger dpId, int addOrRemove) {
+ if (tunnelInterfaces == null) {
+ LOG.debug("No tunnel interfaces found for DPN {}", dpId);
+ return;
+ }
+
+ profiles.forEach(policyProfile -> {
+ String policyClassifier = policyProfile.getPolicyClassifier();
+ tunnelInterfaces.forEach(tunnelInterface -> {
+ BigInteger remoteDpId = tunnelInterface.getRemoteDpId();
+ routeFlowProgrammer.programPolicyClassifierFlow(policyClassifier, dpId, remoteDpId, addOrRemove);
+ });
+ });
+ }
}
import org.opendaylight.genius.mdsalutil.MatchInfoBase;
import org.opendaylight.genius.mdsalutil.MetaDataUtil;
import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
+import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchRegister;
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.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
return instructions;
}
+ public List<MatchInfoBase> getPolicyRouteMatches(long policyClassifierId, int lportTag) {
+ List<MatchInfoBase> matches = new ArrayList<>();
+ // FIXME reg6 masking support will allow matching only based on the lport-tag bits
+ matches.add(new NxMatchRegister(NxmNxReg6.class,
+ MetaDataUtil.getReg6ValueForLPortDispatcher(lportTag, NwConstants.DEFAULT_EGRESS_SERVICE_INDEX)));
+ matches.add(new MatchMetadata(MetaDataUtil.getPolicyClassifierMetaData(policyClassifierId),
+ MetaDataUtil.METADATA_MASK_POLICY_CLASSIFER_ID));
+ return matches;
+ }
+
+ public List<InstructionInfo> getPolicyRouteInstructions(long groupId) {
+ List<InstructionInfo> instructions = new ArrayList<>();
+ instructions.add(new InstructionApplyActions(Collections.singletonList(new ActionGroup(groupId))));
+ return instructions;
+ }
+
public void updateFlowToTx(BigInteger dpId, short tableId, String flowName, int priority, BigInteger cookie,
List<? extends MatchInfoBase> matches, List<InstructionInfo> instructions, int addOrRemove,
WriteTransaction tx) {
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);
+ LOG.debug("Add bucket id {} for interface {} to group {} DPN {}", bucketId, interfaceName, groupId, dpId);
mdsalManager.addBucketToTx(dpId, groupId, bucket, tx);
}
}
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
+import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
+import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
import org.opendaylight.netvirt.elanmanager.api.IElanBridgeManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AccessLists;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.AclBase;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.AceKey;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Actions;
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.TunnelTypeLogicalGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.PolicyAcl;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.PolicyProfiles;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.SetPolicyClassifier;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterfaceBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.DirectionEgress;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final DataBroker dataBroker;
private final IElanBridgeManager bridgeManager;
+ private final ItmRpcService itmRpcService;
+ private final IInterfaceManager interfaceManager;
private final DataStoreJobCoordinator coordinator;
@Inject
- public PolicyServiceUtil(final DataBroker dataBroker, final IElanBridgeManager bridgeManager) {
+ public PolicyServiceUtil(final DataBroker dataBroker, final IElanBridgeManager bridgeManager,
+ final ItmRpcService itmRpcService, final IInterfaceManager interfaceManager) {
this.dataBroker = dataBroker;
this.bridgeManager = bridgeManager;
+ this.itmRpcService = itmRpcService;
+ this.interfaceManager = interfaceManager;
this.coordinator = DataStoreJobCoordinator.getInstance();
}
return Optional.absent();
}
- if (setPolicyClassifier.getDirection() == null
- || !setPolicyClassifier.getDirection().isAssignableFrom(DirectionEgress.class)) {
+ Class<? extends DirectionBase> direction;
+ try {
+ direction = setPolicyClassifier.getDirection();
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Failed to parse policy classifier direction");
+ return null;
+ }
+
+ if (direction == null || !direction.isAssignableFrom(DirectionEgress.class)) {
LOG.trace("Ignoring non egress policy ACE rule {}", ace.getRuleName());
return Optional.absent();
}
return Optional.of(setPolicyClassifier.getPolicyClassifier());
-
}
public Optional<Ace> getPolicyAce(String aclName, String ruleName) {
}
}
+ public List<PolicyProfile> getAllPolicyProfiles() {
+ InstanceIdentifier<PolicyProfiles> identifier = InstanceIdentifier.create(PolicyProfiles.class);
+ try {
+ Optional<PolicyProfiles> optProfiles = SingleTransactionDataBroker.syncReadOptional(dataBroker,
+ LogicalDatastoreType.CONFIGURATION, identifier);
+ return optProfiles.isPresent() ? optProfiles.get().getPolicyProfile() : Collections.emptyList();
+ } catch (ReadFailedException e) {
+ LOG.warn("Failed to get policy profiles");
+ return Collections.emptyList();
+ }
+ }
+
public List<String> getUnderlayNetworksForClassifier(String policyClassifier) {
InstanceIdentifier<PolicyProfile> identifier = getPolicyClassifierIdentifier(policyClassifier);
try {
org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks
.underlay.network.PolicyProfile> identifier = getUnderlayNetworkPolicyClassifierIdentifier(
policyClassifier, underlayNetwork);
+
if (isAdded) {
tx.merge(LogicalDatastoreType.OPERATIONAL, identifier,
new PolicyProfileBuilder().setPolicyClassifier(policyClassifier).build(), true);
LOG.info("Add policy classifier {} to underlay network {}", policyClassifier, underlayNetwork);
} else {
tx.delete(LogicalDatastoreType.OPERATIONAL, identifier);
- LOG.info("Remove policy classifier {} from underlay network {}", policyClassifier,
- underlayNetwork);
+ LOG.info("Remove policy classifier {} from underlay network {}", policyClassifier, underlayNetwork);
}
return Collections.singletonList(tx.submit());
});
.collect(Collectors.toList());
}
+ public boolean underlayNetworkContainsDpn(String underlayNetwork, BigInteger dpId) {
+ return dpnToInterfacesContainsDpn(getUnderlayNetworkDpnToInterfaces(underlayNetwork), dpId);
+ }
+
+ public boolean underlayNetworkContainsRemoteDpn(String underlayNetwork, BigInteger dpId) {
+ return dpnToInterfacesContainsRemoteDpn(getUnderlayNetworkDpnToInterfaces(underlayNetwork), dpId);
+ }
+
+ public static boolean dpnToInterfacesContainsDpn(List<DpnToInterface> dpnToInterfaces, BigInteger dpId) {
+ if (dpnToInterfaces == null) {
+ return false;
+ }
+
+ return dpnToInterfaces.stream().filter(dpnToInterface -> dpnToInterface.getDpId().equals(dpId)).findFirst()
+ .isPresent();
+ }
+
+ public static boolean dpnToInterfacesContainsRemoteDpn(List<DpnToInterface> dpnToInterfaces, BigInteger dpId) {
+ if (dpnToInterfaces == null) {
+ return false;
+ }
+
+ return dpnToInterfaces.stream().filter(dpnToInterface -> dpnToInterfaceContainsRemoteDpn(dpnToInterface, dpId))
+ .findFirst().isPresent();
+ }
+
+ public static boolean dpnToInterfaceContainsRemoteDpn(DpnToInterface dpnToInterface, BigInteger dpId) {
+ List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
+ if (tunnelInterfaces == null) {
+ return false;
+ }
+
+ return tunnelInterfaces.stream().filter(tunnelInterface -> tunnelInterface.getRemoteDpId().equals(dpId))
+ .findFirst().isPresent();
+ }
+
public String getTunnelUnderlayNetwork(BigInteger dpId, IpAddress tunnelIp) {
Node ovsdbNode = bridgeManager.getBridgeNode(dpId);
if (ovsdbNode == null) {
public List<BigInteger> getUnderlayNetworkRemoteDpns(String underlayNetwork) {
return getRemoteDpnsFromDpnToInterfaces(getUnderlayNetworkDpnToInterfaces(underlayNetwork));
}
+
+
+ public Optional<Integer> getLogicalTunnelLportTag(BigInteger srcDpId, BigInteger dstDpId) {
+ Optional<String> logicalTunnelNameOpt = getLogicalTunnelName(srcDpId, dstDpId);
+ if (!logicalTunnelNameOpt.isPresent()) {
+ LOG.debug("Failed to get logical tunnel for source DPN {} dst DPN {}", srcDpId, dstDpId);
+ return Optional.absent();
+ }
+
+ String logicalTunnelName = logicalTunnelNameOpt.get();
+ InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(logicalTunnelName);
+ if (interfaceInfo == null) {
+ LOG.debug("Failed to get interface info for logical tunnel {}", logicalTunnelName);
+ return Optional.absent();
+ }
+
+ return Optional.of(interfaceInfo.getInterfaceTag());
+ }
+
+ public Optional<String> getLogicalTunnelName(BigInteger srcDpId, BigInteger dstDpId) {
+ Future<RpcResult<GetTunnelInterfaceNameOutput>> tunnelInterfaceOutput = itmRpcService
+ .getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId)
+ .setDestinationDpid(dstDpId).setTunnelType(TunnelTypeLogicalGroup.class).build());
+ try {
+ if (tunnelInterfaceOutput.get().isSuccessful()) {
+ return Optional.of(tunnelInterfaceOutput.get().getResult().getInterfaceName());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error in RPC call getTunnelInterfaceName {} for source DPN {} dst DPN {}", srcDpId, dstDpId);
+ }
+
+ return Optional.absent();
+ }
}
<reference id="iElanBridgeManager"
interface="org.opendaylight.netvirt.elanmanager.api.IElanBridgeManager" />
+ <odl:rpc-service id="itmRpcService"
+ interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService" />
<odl:rpc-service id="idManagerService"
interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService" />