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