/* * 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 javax.inject.Inject; import javax.inject.Singleton; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.WriteTransaction; import org.opendaylight.infrautils.jobcoordinator.JobCoordinator; 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.DpnToInterface; 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.
* Group id is allocated for combination of policy classifier and DPN id.
* The group buckets are built based on the underlay networks defined for the * policy classifier.
* 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 JobCoordinator coordinator; @Inject public PolicyRouteGroupProgrammer(final DataBroker dataBroker, final PolicyIdManager policyIdManager, final PolicyServiceUtil policyServiceUtil, final PolicyServiceFlowUtil policyServiceFlowUtil, final JobCoordinator coordinator) { this.dataBroker = dataBroker; this.policyIdManager = policyIdManager; this.policyServiceUtil = policyServiceUtil; this.policyServiceFlowUtil = policyServiceFlowUtil; this.coordinator = coordinator; } public void programPolicyClassifierGroups(String policyClassifier, List localDpIds, List 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 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 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 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); List dpnToInterfaceList = policyServiceUtil.getUnderlayNetworkDpnToInterfaces(underlayNetwork); dpnToInterfaceList.forEach(dpnToInterface -> { BigInteger dpId = dpnToInterface.getDpId(); List tunnelInterfaces = dpnToInterface.getTunnelInterface(); programPolicyClassifierGroupBuckets(policyClassifier, tunnelInterfaces, dpId, bucketId, addOrRemove, tx); }); } return Collections.singletonList(tx.submit()); }); } public void programPolicyClassifierGroupBuckets(String policyClassifier, List 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 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); }); } }