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