NETVIRT-1630 migrate to md-sal APIs
[netvirt.git] / policyservice / impl / src / main / java / org / opendaylight / netvirt / policyservice / listeners / PolicyProfileChangeListener.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.listeners;
10
11 import java.util.Optional;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import javax.annotation.PostConstruct;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.mdsal.binding.api.DataBroker;
19 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
20 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
21 import org.opendaylight.genius.mdsalutil.NwConstants;
22 import org.opendaylight.netvirt.policyservice.PolicyAceFlowProgrammer;
23 import org.opendaylight.netvirt.policyservice.PolicyIdManager;
24 import org.opendaylight.netvirt.policyservice.PolicyRouteFlowProgrammer;
25 import org.opendaylight.netvirt.policyservice.PolicyRouteGroupProgrammer;
26 import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.PolicyProfiles;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.PolicyProfile;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.PolicyAclRule;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.policy.acl.rule.AceRule;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Listen on {@link PolicyProfile} config changes and update the policy pipeline
38  * whenever the association between policy classifier and underlay networks
39  * changes.<br>
40  * This listener will update the following flows/groups:<br>
41  * * POLICY_CLASSIFER_TABLE policy ACL flows when policy classifier
42  * added/removed<br>
43  * * POLICY_ROUTING_TABLE flows when policy classifier added/removed<br>
44  * * Policy classifier groups for each remote DPN is updated when policy
45  * classifier added/removed or when the list of associated underlay networks is
46  * updated
47  */
48 @Singleton
49 public class PolicyProfileChangeListener
50         extends AsyncDataTreeChangeListenerBase<PolicyProfile, PolicyProfileChangeListener> {
51     private static final Logger LOG = LoggerFactory.getLogger(PolicyProfileChangeListener.class);
52
53     private final DataBroker dataBroker;
54     private final PolicyIdManager policyIdManager;
55     private final PolicyServiceUtil policyServiceUtil;
56     private final PolicyAceFlowProgrammer aceFlowProgrammer;
57     private final PolicyRouteFlowProgrammer routeFlowProgrammer;
58     private final PolicyRouteGroupProgrammer routeGroupProgramer;
59
60     @Inject
61     public PolicyProfileChangeListener(final DataBroker dataBroker, final PolicyIdManager policyIdManager,
62             final PolicyServiceUtil policyServiceUtil, final PolicyAceFlowProgrammer aceFlowProgrammer,
63             final PolicyRouteFlowProgrammer routeFlowProgrammer, final PolicyRouteGroupProgrammer routeGroupProgramer) {
64         this.dataBroker = dataBroker;
65         this.policyIdManager = policyIdManager;
66         this.policyServiceUtil = policyServiceUtil;
67         this.aceFlowProgrammer = aceFlowProgrammer;
68         this.routeFlowProgrammer = routeFlowProgrammer;
69         this.routeGroupProgramer = routeGroupProgramer;
70     }
71
72     @Override
73     @PostConstruct
74     public void init() {
75         LOG.info("init");
76         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
77     }
78
79     @Override
80     protected InstanceIdentifier<PolicyProfile> getWildCardPath() {
81         return InstanceIdentifier.create(PolicyProfiles.class).child(PolicyProfile.class);
82     }
83
84     @Override
85     protected PolicyProfileChangeListener getDataTreeChangeListener() {
86         return this;
87     }
88
89     @Override
90     protected void remove(InstanceIdentifier<PolicyProfile> key, PolicyProfile policyProfile) {
91         String policyClassifier = policyProfile.getPolicyClassifier();
92         LOG.info("Policy profile {} removed", policyClassifier);
93         List<String> underlayNetworks = PolicyServiceUtil
94                 .getUnderlayNetworksFromPolicyRoutes(policyProfile.getPolicyRoute());
95         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(underlayNetworks, policyClassifier, false);
96         List<BigInteger> dpnIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
97         List<BigInteger> remoteDpIds = policyServiceUtil.getUnderlayNetworksRemoteDpns(underlayNetworks);
98         routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpnIds, remoteDpIds, NwConstants.DEL_FLOW);
99         updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.DEL_FLOW);
100         routeFlowProgrammer.programPolicyClassifierFlows(policyClassifier, dpnIds, remoteDpIds, NwConstants.DEL_FLOW);
101         policyIdManager.releasePolicyClassifierId(policyClassifier);
102         releasePolicyClassifierGroupIds(policyClassifier, dpnIds);
103     }
104
105     @Override
106     protected void update(InstanceIdentifier<PolicyProfile> key, PolicyProfile origPolicyProfile,
107             PolicyProfile updatedPolicyProfile) {
108         List<String> origUnderlayNetworks = PolicyServiceUtil
109                 .getUnderlayNetworksFromPolicyRoutes(origPolicyProfile.getPolicyRoute());
110         List<String> updatedUnderlayNetworks = PolicyServiceUtil
111                 .getUnderlayNetworksFromPolicyRoutes(updatedPolicyProfile.getPolicyRoute());
112         List<String> removedUnderlayNetworks = new ArrayList<>(origUnderlayNetworks);
113         removedUnderlayNetworks.removeAll(updatedUnderlayNetworks);
114         List<String> addedUnderlayNetworks = new ArrayList<>(updatedUnderlayNetworks);
115         addedUnderlayNetworks.removeAll(origUnderlayNetworks);
116
117         String policyClassifier = updatedPolicyProfile.getPolicyClassifier();
118         LOG.info("Policy profile {} updated", policyClassifier);
119         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(removedUnderlayNetworks, policyClassifier, false);
120         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(addedUnderlayNetworks, policyClassifier, true);
121
122         // rewrite all group buckets
123         routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, origUnderlayNetworks,
124                 NwConstants.DEL_FLOW);
125         routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, updatedUnderlayNetworks,
126                 NwConstants.ADD_FLOW);
127
128         updatedUnderlayNetworks.removeAll(origUnderlayNetworks);
129         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(updatedUnderlayNetworks,
130                 updatedPolicyProfile.getPolicyClassifier(), true);
131         updatePolicyAclRules(policyClassifier, updatedUnderlayNetworks, NwConstants.ADD_FLOW);
132     }
133
134     @Override
135     protected void add(InstanceIdentifier<PolicyProfile> key, PolicyProfile policyProfile) {
136         String policyClassifier = policyProfile.getPolicyClassifier();
137         LOG.info("Policy profile {} added", policyClassifier);
138         List<String> underlayNetworks = PolicyServiceUtil
139                 .getUnderlayNetworksFromPolicyRoutes(policyProfile.getPolicyRoute());
140         policyServiceUtil.updatePolicyClassifierForUnderlayNetworks(underlayNetworks, policyClassifier, true);
141         List<BigInteger> dpnIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
142         List<BigInteger> remoteDpIds = policyServiceUtil.getUnderlayNetworksRemoteDpns(underlayNetworks);
143         routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpnIds, remoteDpIds, NwConstants.ADD_FLOW);
144         routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, underlayNetworks,
145                 NwConstants.ADD_FLOW);
146         updatePolicyAclRules(policyClassifier, underlayNetworks, NwConstants.ADD_FLOW);
147         routeFlowProgrammer.programPolicyClassifierFlows(policyClassifier, dpnIds, remoteDpIds, NwConstants.ADD_FLOW);
148     }
149
150     private void updatePolicyAclRules(String policyClassifier, List<String> underlayNetworks, int addOrRemove) {
151         List<PolicyAclRule> aclRules = policyServiceUtil.getPolicyClassifierAclRules(policyClassifier);
152         if (aclRules == null || aclRules.isEmpty()) {
153             LOG.debug("No policy ACE rules found for policy classifier {}", policyClassifier);
154             return;
155         }
156
157         List<BigInteger> dpIds = policyServiceUtil.getUnderlayNetworksDpns(underlayNetworks);
158         if (dpIds == null || dpIds.isEmpty()) {
159             LOG.debug("No DPNs found for installation of underlay networks {}", underlayNetworks);
160             return;
161         }
162
163         aclRules.forEach(aclRule -> {
164             List<AceRule> aceRules = aclRule.getAceRule();
165             if (aceRules != null) {
166                 aceRules.forEach(aceRule -> {
167                     Optional<Ace> policyAceOpt =
168                             policyServiceUtil.getPolicyAce(aclRule.getAclName(), aceRule.getRuleName());
169                     if (policyAceOpt.isPresent()) {
170                         aceFlowProgrammer.programAceFlows(policyAceOpt.get(), policyClassifier, dpIds,
171                                 addOrRemove);
172                     }
173                 });
174             } else {
175                 LOG.debug("No ACE rules found for ACL {}", aclRule.getAclName());
176             }
177         });
178     }
179
180     private void releasePolicyClassifierGroupIds(String policyClassifier, List<BigInteger> dpnIds) {
181         dpnIds.forEach(dpnId -> policyIdManager.releasePolicyClassifierGroupId(policyClassifier, dpnId));
182     }
183 }