c27a00f27d903f258b57ed4f14f50be157181297
[netvirt.git] / policyservice / impl / src / main / java / org / opendaylight / netvirt / policyservice / listeners / UnderlayNetworkDpnListener.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.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import javax.annotation.PostConstruct;
16 import javax.inject.Inject;
17 import javax.inject.Singleton;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.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.PolicyRouteFlowProgrammer;
24 import org.opendaylight.netvirt.policyservice.PolicyRouteGroupProgrammer;
25 import org.opendaylight.netvirt.policyservice.util.PolicyServiceUtil;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.UnderlayNetworks;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.PolicyAclRule;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.policy.profiles.policy.profile.policy.acl.rule.AceRule;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.UnderlayNetwork;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.DpnToInterface;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.PolicyProfile;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.policy.rev170207.underlay.networks.underlay.network.dpn.to._interface.TunnelInterface;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Listen on {@link DpnToInterface} operational updates for each underlay
40  * network. When new DPN is added/removed, all policy pipeline associated flows
41  * and groups will be populated to the new DPN.<br>
42  * When new tunnel interfaces are added/removed from underlay network, the
43  * corresponding policy classifier group buckets would be updated accordingly.
44  */
45 @Singleton
46 public class UnderlayNetworkDpnListener
47         extends AsyncDataTreeChangeListenerBase<DpnToInterface, UnderlayNetworkDpnListener> {
48     private static final Logger LOG = LoggerFactory.getLogger(UnderlayNetworkDpnListener.class);
49
50     private final DataBroker dataBroker;
51     private final PolicyServiceUtil policyServiceUtil;
52     private final PolicyAceFlowProgrammer aceFlowProgrammer;
53     private final PolicyRouteFlowProgrammer routeFlowProgrammer;
54     private final PolicyRouteGroupProgrammer routeGroupProgramer;
55
56     @Inject
57     public UnderlayNetworkDpnListener(final DataBroker dataBroker, final PolicyServiceUtil policyServiceUtil,
58             final PolicyAceFlowProgrammer aceFlowProgrammer, final PolicyRouteFlowProgrammer routeFlowProgrammer,
59             final PolicyRouteGroupProgrammer routeGroupProgramer) {
60         this.dataBroker = dataBroker;
61         this.policyServiceUtil = policyServiceUtil;
62         this.aceFlowProgrammer = aceFlowProgrammer;
63         this.routeFlowProgrammer = routeFlowProgrammer;
64         this.routeGroupProgramer = routeGroupProgramer;
65     }
66
67     @Override
68     @PostConstruct
69     public void init() {
70         LOG.info("init");
71         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
72     }
73
74     @Override
75     protected InstanceIdentifier<DpnToInterface> getWildCardPath() {
76         return InstanceIdentifier.create(UnderlayNetworks.class).child(UnderlayNetwork.class)
77                 .child(DpnToInterface.class);
78     }
79
80     @Override
81     protected UnderlayNetworkDpnListener getDataTreeChangeListener() {
82         return this;
83     }
84
85     @Override
86     protected void remove(InstanceIdentifier<DpnToInterface> key, DpnToInterface dpnToInterface) {
87         String underlayNetwork = key.firstKeyOf(UnderlayNetwork.class).getNetworkName();
88         BigInteger dpId = dpnToInterface.getDpId();
89         List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
90         LOG.info("DPN {} removed from underlay network {} with tunnels {}", dpId, underlayNetwork, tunnelInterfaces);
91         List<PolicyProfile> profiles = policyServiceUtil.getUnderlayNetworkPolicyProfiles(underlayNetwork);
92         if (profiles == null || profiles.isEmpty()) {
93             LOG.debug("No policy profiles found for underlay network {}", underlayNetwork);
94             return;
95         }
96
97         populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.DEL_FLOW);
98     }
99
100     @Override
101     protected void update(InstanceIdentifier<DpnToInterface> key, DpnToInterface origDpnToInterface,
102             DpnToInterface updatedDpnToInterface) {
103         String underlayNetwork = key.firstKeyOf(UnderlayNetwork.class).getNetworkName();
104         BigInteger dpId = updatedDpnToInterface.getDpId();
105         LOG.info("DPN {} updated to underlay network {} with tunnels {}", dpId, underlayNetwork,
106                 updatedDpnToInterface.getTunnelInterface());
107         List<PolicyProfile> profiles = policyServiceUtil.getUnderlayNetworkPolicyProfiles(underlayNetwork);
108         if (profiles == null || profiles.isEmpty()) {
109             LOG.debug("No policy profiles found for underlay network {}", underlayNetwork);
110             return;
111         }
112
113         List<TunnelInterface> origTunnelInterfaces = origDpnToInterface.getTunnelInterface();
114         if (origTunnelInterfaces == null) {
115             origTunnelInterfaces = Collections.emptyList();
116         }
117         List<TunnelInterface> updatedTunnelInterfaces = updatedDpnToInterface.getTunnelInterface();
118         if (updatedTunnelInterfaces == null) {
119             updatedTunnelInterfaces = Collections.emptyList();
120         }
121         List<TunnelInterface> removedTunnelInterfaces = new ArrayList<>(origTunnelInterfaces);
122         removedTunnelInterfaces.removeAll(updatedTunnelInterfaces);
123         List<TunnelInterface> addedTunnelInterfaces = new ArrayList<>(updatedTunnelInterfaces);
124         addedTunnelInterfaces.removeAll(origTunnelInterfaces);
125
126         populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, removedTunnelInterfaces, dpId, NwConstants.DEL_FLOW);
127         populatePolicyGroupsToDpn(profiles, addedTunnelInterfaces, dpId, NwConstants.ADD_FLOW);
128         populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, addedTunnelInterfaces, dpId, NwConstants.ADD_FLOW);
129     }
130
131     @Override
132     protected void add(InstanceIdentifier<DpnToInterface> key, DpnToInterface dpnToInterface) {
133         String underlayNetwork = key.firstKeyOf(UnderlayNetwork.class).getNetworkName();
134         BigInteger dpId = dpnToInterface.getDpId();
135         List<TunnelInterface> tunnelInterfaces = dpnToInterface.getTunnelInterface();
136         LOG.info("DPN {} added to underlay network {} with tunnels {}", dpId, underlayNetwork, tunnelInterfaces);
137         List<PolicyProfile> profiles = policyServiceUtil.getUnderlayNetworkPolicyProfiles(underlayNetwork);
138         if (profiles == null || profiles.isEmpty()) {
139             LOG.debug("No policy profiles found for underlay network {}", underlayNetwork);
140             return;
141         }
142
143         populatePolicyGroupsToDpn(profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
144         populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
145         populatePolicyAclRulesToDpn(dpId, profiles, NwConstants.ADD_FLOW);
146         populatePolicyRoutesToDpn(profiles, tunnelInterfaces, dpId, NwConstants.ADD_FLOW);
147     }
148
149     private void populatePolicyGroupsToDpn(List<PolicyProfile> profiles,
150             List<TunnelInterface> tunnelInterfaces, BigInteger dpId, int addOrRemove) {
151         profiles.forEach(profile -> {
152             String policyClassifier = profile.getPolicyClassifier();
153             routeGroupProgramer.programPolicyClassifierGroups(policyClassifier, dpId, tunnelInterfaces, addOrRemove);
154         });
155     }
156
157     private void populatePolicyGroupBucketsToDpn(String underlayNetwork, List<PolicyProfile> profiles,
158             List<TunnelInterface> tunnelInterfaces, BigInteger dpId, int addOrRemove) {
159         profiles.forEach(profile -> {
160             String policyClassifier = profile.getPolicyClassifier();
161             List<String> underlayNetworks =
162                     policyServiceUtil.getUnderlayNetworksForClassifier(policyClassifier);
163             if (underlayNetworks != null) {
164                 int bucketId = underlayNetworks.indexOf(underlayNetwork);
165                 if (bucketId != -1) {
166                     routeGroupProgramer.programPolicyClassifierGroupBuckets(policyClassifier, tunnelInterfaces,
167                             dpId, bucketId, addOrRemove);
168                 } else {
169                     LOG.warn("Policy classifier {} routes do not contain {}", policyClassifier,
170                             underlayNetwork);
171                 }
172             } else {
173                 LOG.warn("No underlay networks found for classifier {} while populating {} flows",
174                         policyClassifier, underlayNetwork);
175             }
176         });
177     }
178
179     private void populatePolicyAclRulesToDpn(BigInteger dpId, List<PolicyProfile> profiles,
180             int addOrRemove) {
181         profiles.forEach(profile -> {
182             String policyClassifier = profile.getPolicyClassifier();
183
184             List<PolicyAclRule> policyClassifierAclRules =
185                     policyServiceUtil.getPolicyClassifierAclRules(policyClassifier);
186             if (policyClassifierAclRules != null) {
187                 policyClassifierAclRules.forEach(aclRule -> {
188                     List<AceRule> aceRules = aclRule.getAceRule();
189                     if (aceRules != null) {
190                         aceRules.forEach(aceRule -> {
191                             com.google.common.base.Optional<Ace> policyAceOpt = policyServiceUtil
192                                     .getPolicyAce(aclRule.getAclName(), aceRule.getRuleName());
193                             if (policyAceOpt.isPresent()) {
194                                 aceFlowProgrammer.programAceFlows(policyAceOpt.get(), dpId, addOrRemove);
195                             } else {
196                                 LOG.warn("Failed to get ACL {} rule {}", aclRule.getAclName(), aceRule.getRuleName());
197                             }
198                         });
199                     } else {
200                         LOG.debug("No ACE rule found for policy ACL {}", aclRule.getAclName());
201                     }
202                 });
203             }
204         });
205     }
206
207     private void populatePolicyRoutesToDpn(List<PolicyProfile> profiles, List<TunnelInterface> tunnelInterfaces,
208             BigInteger dpId, int addOrRemove) {
209         if (tunnelInterfaces == null) {
210             LOG.debug("No tunnel interfaces found for DPN {}", dpId);
211             return;
212         }
213
214         profiles.forEach(policyProfile -> {
215             String policyClassifier = policyProfile.getPolicyClassifier();
216             tunnelInterfaces.forEach(tunnelInterface -> {
217                 BigInteger remoteDpId = tunnelInterface.getRemoteDpId();
218                 routeFlowProgrammer.programPolicyClassifierFlow(policyClassifier, dpId, remoteDpId, addOrRemove);
219             });
220         });
221     }
222 }