2 * Copyright (c) 2017 Hewlett Packard Enterprise, Co. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.policyservice.listeners;
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;
18 import javax.annotation.PostConstruct;
19 import javax.inject.Inject;
20 import javax.inject.Singleton;
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;
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.
47 @SuppressWarnings("deprecation")
49 public class UnderlayNetworkDpnListener
50 extends AsyncDataTreeChangeListenerBase<DpnToInterface, UnderlayNetworkDpnListener> {
51 private static final Logger LOG = LoggerFactory.getLogger(UnderlayNetworkDpnListener.class);
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;
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;
74 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
78 protected InstanceIdentifier<DpnToInterface> getWildCardPath() {
79 return InstanceIdentifier.create(UnderlayNetworks.class).child(UnderlayNetwork.class)
80 .child(DpnToInterface.class);
84 protected UnderlayNetworkDpnListener getDataTreeChangeListener() {
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);
100 populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.DEL_FLOW);
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);
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);
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);
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);
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);
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);
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);
167 LOG.warn("Policy classifier {} routes do not contain {}", policyClassifier,
170 return underlayNetworks;
172 LOG.warn("No underlay networks found for classifier {} while populating {} flows",
173 policyClassifier, underlayNetwork);
179 private void populatePolicyAclRulesToDpn(String underlayNetwork, BigInteger dpId, List<PolicyProfile> profiles,
181 profiles.forEach(profile -> {
182 String policyClassifier = profile.getPolicyClassifier();
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);
193 LOG.warn("Failed to get ACL {} rule {}", aclRule.getAclName(), aceRule.getRuleName());
198 LOG.debug("No ACE rule found for policy ACL {}", aclRule.getAclName());
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);
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);