6b56bce8f55604262c502cd63ada2636e6e78fd3
[netvirt.git] / policyservice / impl / src / main / java / org / opendaylight / netvirt / policyservice / PolicyRouteGroupProgrammer.java
1 /*
2  * Copyright (c) 2017 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netvirt.policyservice;
10
11 import java.math.BigInteger;
12 import java.util.Collections;
13 import java.util.List;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
18 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
19 import org.opendaylight.netvirt.policyservice.util.PolicyServiceFlowUtil;
20 import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterface;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterface;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * Program policy classifier fast-failover groups per remote DPN.<br>
29  * Group id is allocated for combination of policy classifier and DPN id.<br>
30  * The group buckets are built based on the underlay networks defined for the
31  * policy classifier.<br>
32  * Each bucket in the group contains the tunnel egress actions for the actual
33  * tunnel interface associated with the underlay network.
34  *
35  */
36 @Singleton
37 public class PolicyRouteGroupProgrammer {
38     private static final Logger LOG = LoggerFactory.getLogger(PolicyRouteGroupProgrammer.class);
39
40     private final DataBroker dataBroker;
41     private final PolicyIdManager policyIdManager;
42     private final PolicyServiceUtil policyServiceUtil;
43     private final PolicyServiceFlowUtil policyServiceFlowUtil;
44     private final JobCoordinator coordinator;
45
46     @Inject
47     public PolicyRouteGroupProgrammer(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
48             final PolicyServiceUtil policyServiceUtil, final PolicyServiceFlowUtil policyServiceFlowUtil,
49             final JobCoordinator coordinator) {
50         this.dataBroker = dataBroker;
51         this.policyIdManager = policyIdManager;
52         this.policyServiceUtil = policyServiceUtil;
53         this.policyServiceFlowUtil = policyServiceFlowUtil;
54         this.coordinator = coordinator;
55     }
56
57     public void programPolicyClassifierGroups(String policyClassifier, List<BigInteger> localDpIds,
58             List<BigInteger> remoteDpIds, int addOrRemove) {
59         if (remoteDpIds == null || remoteDpIds.isEmpty()) {
60             LOG.debug("No remote DPNs found for policy classifier {}", policyClassifier);
61             return;
62         }
63
64         coordinator.enqueueJob(policyClassifier, () -> {
65             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
66             remoteDpIds.forEach(
67                 remoteDpId -> programPolicyClassifierGroups(policyClassifier, localDpIds, remoteDpId, tx,
68                             addOrRemove));
69             return Collections.singletonList(tx.submit());
70         });
71     }
72
73     public void programPolicyClassifierGroups(String policyClassifier, BigInteger dpId,
74             List<TunnelInterface> tunnelInterfaces, int addOrRemove) {
75         if (tunnelInterfaces == null) {
76             LOG.debug("No tunnel interfaces found for policy classifier {} DPN {}", policyClassifier, dpId);
77             return;
78
79         }
80         coordinator.enqueueJob(policyClassifier, () -> {
81             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
82             tunnelInterfaces.forEach(tunnelInterface -> {
83                 BigInteger remoteDpId = tunnelInterface.getRemoteDpId();
84                 programPolicyClassifierGroups(policyClassifier, Collections.singletonList(dpId), remoteDpId, tx,
85                         addOrRemove);
86             });
87             return Collections.singletonList(tx.submit());
88         });
89     }
90
91     private void programPolicyClassifierGroups(String policyClassifier, List<BigInteger> localDpIds,
92             BigInteger remoteDpId, WriteTransaction tx, int addOrRemove) {
93         long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifier, remoteDpId);
94         if (groupId == PolicyServiceConstants.INVALID_ID) {
95             LOG.error("Failed to get group id for policy classifier {}", policyClassifier);
96             return;
97         }
98
99         if (localDpIds == null || localDpIds.isEmpty()) {
100             LOG.debug("No DPNs found for policy classifier {}", policyClassifier);
101             return;
102         }
103
104         String groupName = PolicyIdManager.getPolicyClassifierGroupKey(policyClassifier, remoteDpId);
105         localDpIds.forEach(srcDpId -> {
106             if (!remoteDpId.equals(srcDpId)) {
107                 policyServiceFlowUtil.updateGroupToTx(srcDpId, groupId, groupName, GroupTypes.GroupFf, addOrRemove, tx);
108             }
109         });
110     }
111
112     public void programPolicyClassifierGroupBuckets(String policyClassifier, List<String> underlayNetworks,
113             int addOrRemove) {
114         if (underlayNetworks == null) {
115             return;
116         }
117
118         coordinator.enqueueJob(policyClassifier, () -> {
119             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
120
121             for (int idx = 0; idx < underlayNetworks.size(); idx++) {
122                 final int bucketId = idx;
123                 String underlayNetwork = underlayNetworks.get(idx);
124                 List<DpnToInterface> dpnToInterfaceList =
125                         policyServiceUtil.getUnderlayNetworkDpnToInterfaces(underlayNetwork);
126                 dpnToInterfaceList.forEach(dpnToInterface -> {
127                     BigInteger dpId = dpnToInterface.getDpId();
128                     List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
129                     programPolicyClassifierGroupBuckets(policyClassifier, tunnelInterfaces, dpId, bucketId,
130                             addOrRemove, tx);
131                 });
132             }
133             return Collections.singletonList(tx.submit());
134         });
135     }
136
137     public void programPolicyClassifierGroupBuckets(String policyClassifier, List<TunnelInterface> tunnelInterfaces,
138             BigInteger dpId, int bucketId, int addOrRemove) {
139         coordinator.enqueueJob(policyClassifier, () -> {
140             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
141             programPolicyClassifierGroupBuckets(policyClassifier, tunnelInterfaces, dpId, bucketId, addOrRemove, tx);
142             return Collections.singletonList(tx.submit());
143         });
144     }
145
146     private void programPolicyClassifierGroupBuckets(String policyClassifier, List<TunnelInterface> tunnelInterfaces,
147             BigInteger dpId, int bucketId, int addOrRemove, WriteTransaction tx) {
148         if (tunnelInterfaces == null) {
149             LOG.debug("No tunnel interfaces found for policy classifier {} DPN {}", policyClassifier, dpId);
150             return;
151         }
152
153         tunnelInterfaces.forEach(tunnelInterface -> {
154             String interfaceName = tunnelInterface.getInterfaceName();
155             BigInteger remoteDpId = tunnelInterface.getRemoteDpId();
156             long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifier, remoteDpId);
157             policyServiceFlowUtil.updateInterfaceBucketToTx(dpId, groupId, bucketId, interfaceName, addOrRemove, tx);
158         });
159     }
160 }