6945e60d6d9bc3a888161afa82b0a637c938b446
[netvirt.git] / policyservice / impl / src / main / java / org / opendaylight / netvirt / policyservice / PolicyRouteFlowProgrammer.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 com.google.common.base.Optional;
12 import java.math.BigInteger;
13 import java.util.Collections;
14 import java.util.List;
15 import javax.inject.Inject;
16 import javax.inject.Singleton;
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
19 import org.opendaylight.genius.mdsalutil.InstructionInfo;
20 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
21 import org.opendaylight.genius.mdsalutil.NwConstants;
22 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
23 import org.opendaylight.netvirt.policyservice.util.PolicyServiceFlowUtil;
24 import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29 /**
30  * Program POLICY_ROUTING_TABLE flows. Each flow is composed from<br>
31  * * OF matches - logical tunnel lport tag and policy classifier metadata
32  * bits<br>
33  * * OF actions - set policy classifier group id based on the remote DPN
34  * associated with the logical tunnel.
35  *
36  */
37 @Singleton
38 public class PolicyRouteFlowProgrammer {
39     private static final Logger LOG = LoggerFactory.getLogger(PolicyRouteFlowProgrammer.class);
40
41     private final DataBroker dataBroker;
42     private final PolicyIdManager policyIdManager;
43     private final PolicyServiceUtil policyServiceUtil;
44     private final PolicyServiceFlowUtil policyFlowUtil;
45     private final JobCoordinator coordinator;
46
47     @Inject
48     public PolicyRouteFlowProgrammer(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
49             final PolicyServiceUtil policyServiceUtil, final PolicyServiceFlowUtil policyFlowUtil,
50             final JobCoordinator coordinator) {
51         this.dataBroker = dataBroker;
52         this.policyIdManager = policyIdManager;
53         this.policyServiceUtil = policyServiceUtil;
54         this.policyFlowUtil = policyFlowUtil;
55         this.coordinator = coordinator;
56     }
57
58     public void programPolicyClassifierFlows(String policyClassifierName, List<BigInteger> localDpIds,
59             List<BigInteger> remoteDpIds, int addOrRemove) {
60         long policyClassifierId = policyIdManager.getPolicyClassifierId(policyClassifierName);
61         if (policyClassifierId == PolicyServiceConstants.INVALID_ID) {
62             LOG.error("Failed to get policy classifier id for classifier {}", policyClassifierName);
63             return;
64         }
65
66         coordinator.enqueueJob(policyClassifierName, () -> {
67             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
68             remoteDpIds.forEach(remoteDpId -> {
69                 long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifierName, remoteDpId);
70                 if (groupId != PolicyServiceConstants.INVALID_ID) {
71                     List<InstructionInfo> instructions = policyFlowUtil.getPolicyRouteInstructions(groupId);
72                     localDpIds.forEach(localDpId -> {
73                         if (!remoteDpId.equals(localDpId)) {
74                             programPolicyClassifierFlow(policyClassifierName, policyClassifierId, instructions,
75                                     localDpId, remoteDpId, tx, addOrRemove);
76                         }
77                     });
78                 } else {
79                     LOG.error("Failed to get group id for policy classifier {} DPN {}", policyClassifierName,
80                             remoteDpId);
81                 }
82             });
83             return Collections.singletonList(tx.submit());
84         });
85
86     }
87
88     public void programPolicyClassifierFlow(String policyClassifierName, BigInteger localDpId, BigInteger remoteDpId,
89             int addOrRemove) {
90         programPolicyClassifierFlow(policyClassifierName, localDpId, remoteDpId, addOrRemove, false);
91     }
92
93     public void programPolicyClassifierFlow(String policyClassifierName, BigInteger localDpId, BigInteger remoteDpId,
94             int addOrRemove, boolean createIfMissing) {
95         long policyClassifierId = policyIdManager.getPolicyClassifierId(policyClassifierName);
96         if (policyClassifierId == PolicyServiceConstants.INVALID_ID) {
97             LOG.error("Failed to get policy classifier id for classifier {}", policyClassifierName);
98             return;
99         }
100
101         long groupId = policyIdManager.getPolicyClassifierGroupId(policyClassifierName, remoteDpId);
102         if (groupId == PolicyServiceConstants.INVALID_ID) {
103             LOG.error("Failed to get group id for policy classifier {} DPN {}", policyClassifierName, remoteDpId);
104             return;
105         }
106
107         if (addOrRemove == NwConstants.ADD_FLOW && createIfMissing) {
108             addPolicyClassifierGroup(policyClassifierName, localDpId, remoteDpId, addOrRemove, groupId);
109         }
110
111         List<InstructionInfo> instructions = policyFlowUtil.getPolicyRouteInstructions(groupId);
112         coordinator.enqueueJob(policyClassifierName, () -> {
113             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
114             programPolicyClassifierFlow(policyClassifierName, policyClassifierId, instructions, localDpId, remoteDpId,
115                     tx, addOrRemove);
116             return Collections.singletonList(tx.submit());
117         });
118
119     }
120
121     private void programPolicyClassifierFlow(String policyClassifierName, long policyClassifierId,
122             List<InstructionInfo> instructions, BigInteger localDpId, BigInteger remoteDpId, WriteTransaction tx,
123             int addOrRemove) {
124         Optional<Integer> lportTagOpt = policyServiceUtil.getLogicalTunnelLportTag(localDpId, remoteDpId);
125         if (!lportTagOpt.isPresent()) {
126             LOG.debug("Missing lport-tag for policy classifier {} logical tunnel for source DPN {} dst DPN {}",
127                     policyClassifierName, localDpId, remoteDpId);
128             return;
129         }
130
131         List<MatchInfoBase> matches = policyFlowUtil.getPolicyRouteMatches(policyClassifierId, lportTagOpt.get());
132         LOG.debug("{} policy classifier {} route on source DPN {} dest DPN {}",
133                 addOrRemove == NwConstants.ADD_FLOW ? "Installing" : "Removing", policyClassifierName, localDpId,
134                 remoteDpId);
135         policyFlowUtil.updateFlowToTx(localDpId, NwConstants.EGRESS_POLICY_ROUTING_TABLE,
136                 PolicyIdManager.getPolicyClassifierGroupKey(policyClassifierName, remoteDpId),
137                 PolicyServiceConstants.POLICY_FLOW_PRIOPITY, NwConstants.EGRESS_POLICY_ROUTING_COOKIE, matches,
138                 instructions, addOrRemove, tx);
139     }
140
141     private void addPolicyClassifierGroup(String policyClassifierName, BigInteger localDpId, BigInteger remoteDpId,
142             int addOrRemove, long groupId) {
143         coordinator.enqueueJob(policyClassifierName, () -> {
144             WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
145             policyFlowUtil.updateGroupToTx(localDpId, groupId,
146                     PolicyIdManager.getPolicyClassifierGroupKey(policyClassifierName, remoteDpId), GroupTypes.GroupFf,
147                     addOrRemove, tx);
148             return Collections.singletonList(tx.submit());
149         });
150     }
151
152 }