Fix For NETVIRT-1389
[netvirt.git] / sfc / classifier / impl / src / main / java / org / opendaylight / netvirt / sfc / classifier / service / domain / impl / OpenflowRenderer.java
1 /*
2  * Copyright (c) 2017 Ericsson Inc. 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.sfc.classifier.service.domain.impl;
10
11 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
18 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
19 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
20 import org.opendaylight.netvirt.sfc.classifier.providers.GeniusProvider;
21 import org.opendaylight.netvirt.sfc.classifier.providers.OpenFlow13Provider;
22 import org.opendaylight.netvirt.sfc.classifier.service.domain.api.ClassifierEntryRenderer;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 public class OpenflowRenderer implements ClassifierEntryRenderer {
32
33     private static final Logger LOG = LoggerFactory.getLogger(OpenflowRenderer.class);
34
35     private final OpenFlow13Provider openFlow13Provider;
36     private final GeniusProvider geniusProvider;
37     private final ManagedNewTransactionRunner txRunner;
38
39     public OpenflowRenderer(OpenFlow13Provider openFlow13Provider, GeniusProvider geniusProvider,
40         DataBroker dataBroker) {
41         this.openFlow13Provider = openFlow13Provider;
42         this.geniusProvider = geniusProvider;
43         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
44     }
45
46     @Override
47     public void renderIngress(InterfaceKey interfaceKey) {
48         // noop
49     }
50
51     @Override
52     // FindBugs reports "Useless object stored in variable flows" however it doesn't recognize the usage of forEach.
53     @SuppressFBWarnings("UC_USELESS_OBJECT")
54     public void renderNode(NodeId nodeId) {
55         List<Flow> flows = new ArrayList<>();
56         flows.add(this.openFlow13Provider.createIngressClassifierFilterTunnelNshFlow(nodeId));
57         flows.add(this.openFlow13Provider.createIngressClassifierFilterEthNshFlow(nodeId));
58         flows.add(this.openFlow13Provider.createIngressClassifierFilterNshFlow(nodeId));
59         flows.add(this.openFlow13Provider.createIngressClassifierFilterNoNshFlow(nodeId));
60         flows.add(this.openFlow13Provider.createIngressClassifierAclNoMatchFlow(nodeId));
61
62         flows.add(this.openFlow13Provider.createIngressClassifierTunnelEthNshTrafficCaptureFlow(nodeId));
63         flows.add(this.openFlow13Provider.createIngressClassifierTunnelNshTrafficCaptureFlow(nodeId));
64
65         flows.add(this.openFlow13Provider.createEgressClassifierFilterNoNshFlow(nodeId));
66         flows.add(this.openFlow13Provider.createEgressClassifierFilterNshFlow(nodeId));
67
68         flows.add(this.openFlow13Provider.createEgressClassifierNextHopFlow(nodeId));
69
70         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
71             tx -> flows.forEach(flow -> this.openFlow13Provider.appendFlowForCreate(nodeId, flow, tx))), LOG,
72             "Error rendering node");
73     }
74
75     @Override
76     // FindBugs reports "Useless object stored in variable flows" however it doesn't recognize the usage of forEach.
77     @SuppressFBWarnings("UC_USELESS_OBJECT")
78     public void renderPath(NodeId nodeId, Long nsp, short nsi, short nsl, String firstHopIp) {
79
80         List<Flow> flows = new ArrayList<>();
81         if (firstHopIp != null) {
82             Long port = geniusProvider.getEgressVxlanPortForNode(OpenFlow13Provider.getDpnIdFromNodeId(nodeId))
83                     .orElse(null);
84             if (port == null) {
85                 LOG.error("OpenflowRenderer: cant get egressPort for nodeId [{}]", nodeId.getValue());
86                 return;
87             }
88             Flow flow;
89             flow = openFlow13Provider.createEgressClassifierTransportEgressRemoteEthNshFlow(
90                     nodeId, nsp, port, firstHopIp);
91             flows.add(flow);
92         } else {
93             Flow flow;
94             flow = openFlow13Provider.createEgressClassifierTransportEgressLocalFlow(nodeId, nsp);
95             flows.add(flow);
96         }
97         short egressNsi = (short) (nsi - nsl);
98         flows.add(openFlow13Provider.createIngressClassifierFilterChainEgressFlow(nodeId, nsp, egressNsi));
99         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
100             tx -> flows.forEach(flow -> this.openFlow13Provider.appendFlowForCreate(nodeId, flow, tx))), LOG,
101             "Error rendering a path");
102     }
103
104     @Override
105     public void renderMatch(NodeId nodeId, String connector, Matches matches, Long nsp, Short nsi) {
106         Long port = OpenFlow13Provider.getPortNoFromNodeConnector(connector);
107         List<MatchBuilder> matchBuilds = this.openFlow13Provider.getMatchBuilderFromAceMatches(matches);
108         for (MatchBuilder match : matchBuilds) {
109             Flow flow = this.openFlow13Provider.createIngressClassifierAclFlow(nodeId, match, port, nsp, nsi);
110             ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
111                 tx -> this.openFlow13Provider.appendFlowForCreate(nodeId, flow, tx)), LOG, "Error rendering a match");
112         }
113     }
114
115     @Override
116     public void renderEgress(InterfaceKey interfaceKey, String destinationIp) {
117         // noop
118     }
119
120     @Override
121     public void suppressIngress(InterfaceKey interfaceKey) {
122         // noop
123     }
124
125     @Override
126     // FindBugs reports "Useless object stored in variable flows" however it doesn't recognize the usage of forEach.
127     @SuppressFBWarnings("UC_USELESS_OBJECT")
128     public void suppressNode(NodeId nodeId) {
129         List<Flow> flows = new ArrayList<>();
130         flows.add(this.openFlow13Provider.createIngressClassifierFilterTunnelNshFlow(nodeId));
131         flows.add(this.openFlow13Provider.createIngressClassifierFilterEthNshFlow(nodeId));
132         flows.add(this.openFlow13Provider.createIngressClassifierFilterNshFlow(nodeId));
133         flows.add(this.openFlow13Provider.createIngressClassifierFilterNoNshFlow(nodeId));
134         flows.add(this.openFlow13Provider.createIngressClassifierAclNoMatchFlow(nodeId));
135
136         flows.add(this.openFlow13Provider.createIngressClassifierTunnelEthNshTrafficCaptureFlow(nodeId));
137         flows.add(this.openFlow13Provider.createIngressClassifierTunnelNshTrafficCaptureFlow(nodeId));
138
139         flows.add(this.openFlow13Provider.createEgressClassifierFilterNoNshFlow(nodeId));
140         flows.add(this.openFlow13Provider.createEgressClassifierFilterNshFlow(nodeId));
141
142         flows.add(this.openFlow13Provider.createEgressClassifierNextHopFlow(nodeId));
143
144         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
145             tx -> flows.forEach(flow -> this.openFlow13Provider.appendFlowForDelete(nodeId, flow, tx))), LOG,
146             "Error deleting a node");
147     }
148
149     @Override
150     // FindBugs reports "Useless object stored in variable flows" however it doesn't recognize the usage of forEach.
151     @SuppressFBWarnings("UC_USELESS_OBJECT")
152     public void suppressPath(NodeId nodeId, Long nsp, short nsi, short nsl, String firstHopIp) {
153         List<Flow> flows = new ArrayList<>();
154         if (firstHopIp != null) {
155             Long port = geniusProvider.getEgressVxlanPortForNode(OpenFlow13Provider.getDpnIdFromNodeId(nodeId))
156                     .orElse(null);
157             if (port == null) {
158                 LOG.error("OpenflowRenderer: cant get egressPort for nodeId [{}]", nodeId.getValue());
159                 return;
160             }
161             Flow flow;
162             flow = openFlow13Provider.createEgressClassifierTransportEgressRemoteEthNshFlow(
163                     nodeId, nsp, port, firstHopIp);
164             flows.add(flow);
165         } else {
166             Flow flow;
167             flow = openFlow13Provider.createEgressClassifierTransportEgressLocalFlow(nodeId, nsp);
168             flows.add(flow);
169         }
170         short egressNsi = (short) (nsi - nsl);
171         flows.add(openFlow13Provider.createIngressClassifierFilterChainEgressFlow(nodeId, nsp, egressNsi));
172         ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
173             tx -> flows.forEach(flow -> this.openFlow13Provider.appendFlowForDelete(nodeId, flow, tx))), LOG,
174             "Error deleting a path");
175     }
176
177     @Override
178     public void suppressMatch(NodeId nodeId, String connector, Matches matches, Long nsp, Short nsi) {
179         Long port = OpenFlow13Provider.getPortNoFromNodeConnector(connector);
180         List<MatchBuilder> matchBuilds = this.openFlow13Provider.getMatchBuilderFromAceMatches(matches);
181         for (MatchBuilder match : matchBuilds) {
182             Flow flow = this.openFlow13Provider.createIngressClassifierAclFlow(nodeId, match, port, nsp, nsi);
183             ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
184                 tx -> this.openFlow13Provider.appendFlowForDelete(nodeId, flow, tx)), LOG, "Error deleting a match");
185         }
186     }
187
188     @Override
189     public void suppressEgress(InterfaceKey interfaceKey, String destinationIp) {
190         // noop
191     }
192 }