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;
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;
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.
46 public class UnderlayNetworkDpnListener
47 extends AsyncDataTreeChangeListenerBase<DpnToInterface, UnderlayNetworkDpnListener> {
48 private static final Logger LOG = LoggerFactory.getLogger(UnderlayNetworkDpnListener.class);
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;
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;
71 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
75 protected InstanceIdentifier<DpnToInterface> getWildCardPath() {
76 return InstanceIdentifier.create(UnderlayNetworks.class).child(UnderlayNetwork.class)
77 .child(DpnToInterface.class);
81 protected UnderlayNetworkDpnListener getDataTreeChangeListener() {
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);
97 populatePolicyGroupBucketsToDpn(underlayNetwork, profiles, tunnelInterfaces, dpId, NwConstants.DEL_FLOW);
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);
113 List<TunnelInterface> origTunnelInterfaces = origDpnToInterface.getTunnelInterface();
114 if (origTunnelInterfaces == null) {
115 origTunnelInterfaces = Collections.emptyList();
117 List<TunnelInterface> updatedTunnelInterfaces = updatedDpnToInterface.getTunnelInterface();
118 if (updatedTunnelInterfaces == null) {
119 updatedTunnelInterfaces = Collections.emptyList();
121 List<TunnelInterface> removedTunnelInterfaces = new ArrayList<>(origTunnelInterfaces);
122 removedTunnelInterfaces.removeAll(updatedTunnelInterfaces);
123 List<TunnelInterface> addedTunnelInterfaces = new ArrayList<>(updatedTunnelInterfaces);
124 addedTunnelInterfaces.removeAll(origTunnelInterfaces);
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);
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);
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);
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);
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);
169 LOG.warn("Policy classifier {} routes do not contain {}", policyClassifier,
173 LOG.warn("No underlay networks found for classifier {} while populating {} flows",
174 policyClassifier, underlayNetwork);
179 private void populatePolicyAclRulesToDpn(BigInteger dpId, List<PolicyProfile> profiles,
181 profiles.forEach(profile -> {
182 String policyClassifier = profile.getPolicyClassifier();
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);
196 LOG.warn("Failed to get ACL {} rule {}", aclRule.getAclName(), aceRule.getRuleName());
200 LOG.debug("No ACE rule found for policy ACL {}", aclRule.getAclName());
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);
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);