256b5fc900a11f522a8a798b9229d1cad946d39d
[sfc.git] /
1 /*
2  * Copyright (c) 2014, 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.sfc.ofrenderer.processors;
10
11 import java.util.Iterator;
12
13 import org.opendaylight.sfc.ofrenderer.processors.SffGraph.SffGraphEntry;
14 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.function.base.SfDataPlaneLocator;
15 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sf.rev140701.service.functions.ServiceFunction;
16 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
17 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.sff.data.plane.locator.DataPlaneLocatorBuilder;
18 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.DataPlaneLocator;
19 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.MacAddressLocator;
20 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.MacBuilder;
21
22 public class SfcRspProcessorVlan extends SfcRspTransportProcessorBase {
23     private static final int VLAN_ID_INCR_HOP = 1;
24     private static final int VLAN_ID_INCR_RSP = 100;
25     private static int lastVlanId = 0;
26
27     /**
28      * Set the RSP path egress DPL and SFF Hop Ingress DPLs for the VLAN
29      * transport type.
30      */
31     @Override
32     public void setRspTransports() {
33         int hopIncrement = VLAN_ID_INCR_HOP;
34         int transportData = lastVlanId + VLAN_ID_INCR_RSP;
35         lastVlanId = transportData;
36
37         Iterator<SffGraph.SffGraphEntry> sffGraphIter = sffGraph.getGraphEntryIterator();
38         while (sffGraphIter.hasNext()) {
39             SffGraph.SffGraphEntry entry = sffGraphIter.next();
40             LOG.debug("RspTransport entry: {}", entry);
41
42             if (entry.getSrcSff().equals(entry.getDstSff())) {
43                 // It may be that multiple SFs are on the same SFF
44                 // If so, we dont need to set the transports again
45                 // Otherwise the SFF ingress DPL will be overwritten
46                 continue;
47             }
48
49             DataPlaneLocatorBuilder dpl = new DataPlaneLocatorBuilder();
50             dpl.setTransport(rsp.getTransportType());
51             MacBuilder macBuilder = new MacBuilder();
52             macBuilder.setVlanId(transportData);
53             dpl.setLocatorType(macBuilder.build());
54
55             if (entry.getDstSff().equals(SffGraph.EGRESS)) {
56                 sffGraph.setPathEgressDpl(entry.getPathId(), dpl.build());
57             } else {
58                 sffGraph.setHopIngressDpl(entry.getDstSff(), entry.getPathId(), dpl.build());
59             }
60             transportData += hopIncrement;
61         }
62     }
63
64     //
65     // TransportIngress methods
66     //
67
68     /**
69      * Configure the Transport Ingress flow for SFs.
70      *
71      * @param entry
72      *            - RSP hop info used to create the flow
73      */
74     @Override
75     public void configureSfTransportIngressFlow(SffGraphEntry entry, SfDataPlaneLocator sfDpl) {
76         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getDstSff(), entry.getPathId());
77         this.sfcFlowProgrammer.configureVlanTransportIngressFlow(sffNodeName);
78     }
79
80     /**
81      * Configure the Transport Ingress flow for SFFs.
82      *
83      * @param entry
84      *            - RSP hop info used to create the flow
85      */
86     @Override
87     public void configureSffTransportIngressFlow(SffGraphEntry entry, SffDataPlaneLocator dstSffDpl) {
88         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getDstSff(), entry.getPathId());
89         this.sfcFlowProgrammer.configureVlanTransportIngressFlow(sffNodeName);
90     }
91
92     //
93     // PathMapper methods
94     //
95
96     /**
97      * Configure the Path Mapper flow for SFs.
98      *
99      * @param entry
100      *            - RSP hop info used to create the flow
101      * @param sfDpl
102      *            - the particular SF DPL used to create the flow
103      */
104     @Override
105     public void configureSfPathMapperFlow(SffGraph.SffGraphEntry entry, SfDataPlaneLocator sfDpl) {
106         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getDstSff(), entry.getPathId());
107         Integer vlanTag = ((MacAddressLocator) sfDpl.getLocatorType()).getVlanId();
108         if (vlanTag != null) {
109             this.sfcFlowProgrammer.configureVlanPathMapperFlow(sffNodeName, vlanTag, entry.getPathId(), true);
110         }
111     }
112
113     /**
114      * Configure the Path Mapper flow for SFFs.
115      *
116      * @param entry
117      *            - RSP hop info used to create the flow
118      * @param hopDpl
119      *            - the particular SFF Hop DPL used to create the flow
120      */
121     @Override
122     public void configureSffPathMapperFlow(SffGraph.SffGraphEntry entry, DataPlaneLocator hopDpl) {
123         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getDstSff(), entry.getPathId());
124         Integer vlanTag = ((MacAddressLocator) hopDpl.getLocatorType()).getVlanId();
125         if (vlanTag != null) {
126             this.sfcFlowProgrammer.configureVlanPathMapperFlow(sffNodeName, vlanTag, entry.getPathId(), false);
127         }
128     }
129
130     //
131     // NextHop methods
132     //
133
134     /**
135      * Configure the Next Hop flow from an SFF to an SF.
136      *
137      * @param entry
138      *            - RSP hop info used to create the flow
139      * @param srcSffDpl
140      *            - the particular SFF DPL used to create the flow
141      * @param dstSfDpl
142      *            - the particular SF DPL used to create the flow
143      */
144     @Override
145     public void configureNextHopFlow(SffGraph.SffGraphEntry entry, SffDataPlaneLocator srcSffDpl,
146             SfDataPlaneLocator dstSfDpl) {
147         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getDstSff(), entry.getPathId());
148         String srcMac = sfcProviderUtils.getDplPortInfoMac(srcSffDpl);
149         String dstMac = sfcProviderUtils.getSfDplMac(dstSfDpl);
150         this.sfcFlowProgrammer.configureMacNextHopFlow(sffNodeName, entry.getPathId(), srcMac, dstMac);
151     }
152
153     /**
154      * Configure the Next Hop flow from an SF to an SFF.
155      *
156      * @param entry
157      *            - RSP hop info used to create the flow
158      * @param srcSfDpl
159      *            - the particular SF DPL used to create the flow
160      * @param dstSffDpl
161      *            - the particular SFF DPL used to create the flow
162      */
163     @Override
164     public void configureNextHopFlow(SffGraph.SffGraphEntry entry, SfDataPlaneLocator srcSfDpl,
165             SffDataPlaneLocator dstSffDpl) {
166         // in this case, we use the SrcSff instead of the typical DstSff
167         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getSrcSff(), entry.getPathId());
168         String srcMac = sfcProviderUtils.getSfDplMac(srcSfDpl);
169         String dstMac = sfcProviderUtils.getDplPortInfoMac(dstSffDpl);
170         this.sfcFlowProgrammer.configureMacNextHopFlow(sffNodeName, entry.getPathId(), srcMac, dstMac);
171     }
172
173     /**
174      * Configure the Next Hop flow from an SF to an SF.
175      *
176      * @param entry
177      *            - RSP hop info used to create the flow
178      * @param srcSfDpl
179      *            - the particular SF DPL used to create the flow
180      * @param dstSfDpl
181      *            - the particular SF DPL used to create the flow
182      */
183     @Override
184     public void configureNextHopFlow(SffGraph.SffGraphEntry entry, SfDataPlaneLocator srcSfDpl,
185             SfDataPlaneLocator dstSfDpl) {
186         // in this case, we use the SrcSff instead of the typical DstSff
187         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getSrcSff(), entry.getPathId());
188         String srcMac = sfcProviderUtils.getSfDplMac(srcSfDpl);
189         String dstMac = sfcProviderUtils.getSfDplMac(dstSfDpl);
190         this.sfcFlowProgrammer.configureMacNextHopFlow(sffNodeName, entry.getPathId(), srcMac, dstMac);
191     }
192
193     /**
194      * Configure the Next Hop flow from an SFF to an SFF.
195      *
196      * @param entry
197      *            - RSP hop info used to create the flow
198      * @param srcSffDpl
199      *            - the particular SFF DPL used to create the flow
200      * @param dstSffDpl
201      *            - the particular SFF DPL used to create the flow
202      */
203     @Override
204     public void configureNextHopFlow(SffGraph.SffGraphEntry entry, SffDataPlaneLocator srcSffDpl,
205             SffDataPlaneLocator dstSffDpl) {
206         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getDstSff(), entry.getPathId());
207         String srcMac = sfcProviderUtils.getDplPortInfoMac(srcSffDpl);
208         String dstMac = sfcProviderUtils.getDplPortInfoMac(dstSffDpl);
209         this.sfcFlowProgrammer.configureMacNextHopFlow(sffNodeName, entry.getPathId(), srcMac, dstMac);
210     }
211
212     //
213     // TransportEgress methods
214     //
215
216     /**
217      * Configure the Transport Egress flow from an SFF to an SF.
218      *
219      * @param entry
220      *            - RSP hop info used to create the flow
221      * @param srcSffDpl
222      *            - the particular SFF DPL used to create the flow
223      * @param dstSfDpl
224      *            - the particular SF DPL used to create the flow
225      * @param hopDpl
226      *            - Hop DPL used to create the flow
227      */
228     @Override
229     public void configureSfTransportEgressFlow(SffGraph.SffGraphEntry entry, SffDataPlaneLocator srcSffDpl,
230             SfDataPlaneLocator dstSfDpl, DataPlaneLocator hopDpl) {
231         Integer vlanTag = ((MacAddressLocator) hopDpl.getLocatorType()).getVlanId();
232         if (vlanTag == null) {
233             return;
234         }
235
236         String srcOfsPortStr = sfcProviderUtils.getDplPortInfoPort(srcSffDpl);
237         if (srcOfsPortStr == null) {
238             throw new SfcRenderingException("configureSffTransportEgressFlow OFS port not avail for SFF ["
239                     + entry.getDstSff() + "] sffDpl [" + srcSffDpl.getName().getValue() + "]");
240         }
241
242         // For the SF transport Egress flow, we'll write to the Dst SFF as
243         // opposed to typically writing to the Src SFF
244         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getDstSff(), entry.getPathId());
245         String srcMac = sfcProviderUtils.getDplPortInfoMac(srcSffDpl);
246         String dstMac = sfcProviderUtils.getSfDplMac(dstSfDpl);
247
248         boolean doPktIn = false;
249         ServiceFunction sf = sfcProviderUtils.getServiceFunction(entry.getSf(), entry.getPathId());
250         // FIXME: I would caution against this approach. Instead you may want to
251         // see if
252         // ServiceFunctionType has "bidirectional" = True in future.
253         if (sf.getType().getValue().equals("tcp-proxy")) {
254             LOG.info("SfcRspProcessorVlan::configureSfTransportEgressFlow TCP PROXY");
255             // If the SF is a TCP Proxy, we need this additional flow for the
256             // SF:
257             // - a flow that will also check for TCP Syn and do a PktIn
258             this.sfcFlowProgrammer.configureArpTransportIngressFlow(sffNodeName, srcMac);
259             doPktIn = true;
260         }
261
262         this.sfcFlowProgrammer.configureVlanSfTransportEgressFlow(sffNodeName, srcMac, dstMac, vlanTag, srcOfsPortStr,
263                 entry.getPathId(), doPktIn);
264     }
265
266     /**
267      * Configure the Transport Egress flow from an SFF to an SFF.
268      *
269      * @param entry
270      *            - RSP hop info used to create the flow
271      * @param srcSffDpl
272      *            - the particular SFF DPL used to create the flow
273      * @param dstSffDpl
274      *            - the particular SFF DPL used to create the flow
275      * @param hopDpl
276      *            - Hop DPL used to create the flow
277      */
278     @Override
279     public void configureSffTransportEgressFlow(SffGraph.SffGraphEntry entry, SffDataPlaneLocator srcSffDpl,
280             SffDataPlaneLocator dstSffDpl, DataPlaneLocator hopDpl) {
281         Integer vlanTag = ((MacAddressLocator) hopDpl.getLocatorType()).getVlanId();
282         if (vlanTag == null) {
283             return;
284         }
285
286         String srcOfsPortStr = sfcProviderUtils.getDplPortInfoPort(srcSffDpl);
287         if (srcOfsPortStr == null) {
288             throw new SfcRenderingException("configureSffTransportEgressFlow OFS port not avail for SFF ["
289                     + entry.getDstSff() + "] sffDpl [" + srcSffDpl.getName().getValue() + "]");
290         }
291
292         String sffNodeName = sfcProviderUtils.getSffOpenFlowNodeName(entry.getSrcSff(), entry.getPathId());
293         String srcMac = sfcProviderUtils.getDplPortInfoMac(srcSffDpl);
294         String dstMac = sfcProviderUtils.getDplPortInfoMac(dstSffDpl);
295         if (entry.getDstSff().equals(SffGraph.EGRESS)) {
296             this.sfcFlowProgrammer.configureVlanLastHopTransportEgressFlow(sffNodeName, srcMac, dstMac, vlanTag,
297                     srcOfsPortStr, entry.getPathId());
298         } else {
299             this.sfcFlowProgrammer.configureVlanTransportEgressFlow(sffNodeName, srcMac, dstMac, vlanTag, srcOfsPortStr,
300                     entry.getPathId());
301         }
302     }
303 }