NETVIRT-1637 CSIT failure
[netvirt.git] / sfc / classifier / impl / src / main / java / org / opendaylight / netvirt / sfc / classifier / providers / SfcProvider.java
1 /*
2  * Copyright © 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.providers;
10
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.Objects;
14 import java.util.Optional;
15 import java.util.stream.Collectors;
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.mdsalutil.MDSALUtil;
21 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
22 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfName;
23 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffDataPlaneLocatorName;
24 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
25 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfpName;
26 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.RenderedServicePaths;
27 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
28 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathKey;
29 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
30 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarderBase;
31 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.ServiceFunctionForwarders;
32 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
33 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
34 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderKey;
35 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.ServiceFunctionDictionary;
36 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.service.function.forwarder.service.function.dictionary.SffSfDataPlaneLocator;
37 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsState;
38 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.state.ServiceFunctionPathState;
39 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.state.ServiceFunctionPathStateKey;
40 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.logical.rev160620.LogicalInterfaceLocator;
41 import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.sfc.sff.logical.rev160620.service.function.forwarders.service.function.forwarder.sff.data.plane.locator.data.plane.locator.locator.type.LogicalInterface;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 @Singleton
47 public class SfcProvider {
48
49     private static final Logger LOG = LoggerFactory.getLogger(SfcProvider.class);
50     private final DataBroker dataBroker;
51
52     @Inject
53     public SfcProvider(final DataBroker dataBroker) {
54         this.dataBroker = dataBroker;
55     }
56
57     public Optional<RenderedServicePath> getRenderedServicePath(String rspName) {
58         RenderedServicePathKey renderedServicePathKey = new RenderedServicePathKey(new RspName(rspName));
59         InstanceIdentifier<RenderedServicePath> rspIid = InstanceIdentifier.builder(RenderedServicePaths.class)
60                 .child(RenderedServicePath.class, renderedServicePathKey).build();
61
62
63         return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, rspIid).toJavaUtil();
64     }
65
66     public Optional<RenderedServicePath> getRenderedServicePathFromSfc(String sfcName) {
67         Optional<RenderedServicePath> rsp = Optional.empty();
68
69         // TODO need to finish this
70
71         return rsp;
72     }
73
74     public Optional<List<String>> readServicePathState(String sfpName) {
75         ServiceFunctionPathStateKey serviceFunctionPathStateKey = new ServiceFunctionPathStateKey(new SfpName(sfpName));
76         InstanceIdentifier<ServiceFunctionPathState> sfpIiD;
77         sfpIiD = InstanceIdentifier.builder(ServiceFunctionPathsState.class)
78                 .child(ServiceFunctionPathState.class, serviceFunctionPathStateKey)
79                 .build();
80         return MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, sfpIiD)
81                 .toJavaUtil()
82                 .map(ServiceFunctionPathState::getSfpRenderedServicePath)
83                 .map(sfpRenderedServicePaths -> sfpRenderedServicePaths.stream()
84                         .map(sfpRenderedServicePath -> sfpRenderedServicePath.getName().getValue())
85                         .collect(Collectors.toList()));
86     }
87
88     public Optional<String> getFirstHopIngressInterfaceFromRsp(RenderedServicePath rsp) {
89         // The ingres interface on the first hop is specified in the forward DPL
90         // in a forward path or the reverse DPL otherwise
91         boolean useForwardDpl = !rsp.isReversePath();
92         return getRspFirstHop(rsp).flatMap(rspHop -> getHopSfInterface(rspHop, useForwardDpl));
93     }
94
95     public Optional<String> getLastHopEgressInterfaceFromRsp(RenderedServicePath rsp) {
96         // The egress interface on the first hop is specified in the forward DPL
97         // in a forward path or the reverse DPL otherwise
98         boolean useForwardDpl = rsp.isReversePath();
99         return getRspLastHop(rsp).flatMap(rspHop -> getHopSfInterface(rspHop, useForwardDpl));
100     }
101
102     private Optional<String> getHopSfInterface(RenderedServicePathHop hop, boolean useForwardDpl) {
103
104         LOG.trace("getHopSfInterface of hop {}", hop);
105
106         SfName sfName = hop.getServiceFunctionName();
107         if (sfName == null) {
108             LOG.warn("getHopSfInterface hop has no SF");
109             return Optional.empty();
110         }
111
112         SffName sffName = hop.getServiceFunctionForwarder();
113         if (sffName == null) {
114             LOG.warn("getHopSfInterface hop has no SFF");
115             return Optional.empty();
116         }
117
118         Optional<ServiceFunctionForwarder> sff = getServiceFunctionForwarder(sffName);
119         if (!sff.isPresent()) {
120             LOG.warn("getHopSfInterface SFF [{}] does not exist", sffName.getValue());
121             return Optional.empty();
122         }
123
124         // Find the SFF-SF data plane locator for the SF pair
125         SffSfDataPlaneLocator sffSfDataPlaneLocator = sff.map(ServiceFunctionForwarder::getServiceFunctionDictionary)
126                 .orElse(Collections.emptyList())
127                 .stream()
128                 .filter(serviceFunctionDictionary -> Objects.equals(serviceFunctionDictionary.getName(), sfName))
129                 .findAny()
130                 .map(ServiceFunctionDictionary::getSffSfDataPlaneLocator)
131                 .orElse(null);
132
133         if (sffSfDataPlaneLocator == null) {
134             LOG.warn("getHopSfInterface SFF [{}] has not dictionary for SF [{}]",
135                     sffName.getValue(),
136                     sffName.getValue());
137             return Optional.empty();
138         }
139
140         // Get the forward or reverse locator name as appropriate if any,
141         // otherwise default to non directional locator
142         SffDataPlaneLocatorName sffDataPlaneLocatorName = null;
143         if (useForwardDpl) {
144             sffDataPlaneLocatorName = sffSfDataPlaneLocator.getSffForwardDplName();
145         } else {
146             sffDataPlaneLocatorName = sffSfDataPlaneLocator.getSffReverseDplName();
147         }
148         if (sffDataPlaneLocatorName == null) {
149             sffDataPlaneLocatorName = sffSfDataPlaneLocator.getSffDplName();
150         }
151
152         // Get the interface name value of the locator with such name
153         SffDataPlaneLocatorName locatorName = sffDataPlaneLocatorName;
154         Optional<String> interfaceName = sff.map(ServiceFunctionForwarderBase::getSffDataPlaneLocator)
155                 .orElse(Collections.emptyList())
156                 .stream()
157                 .filter(sffDataPlaneLocator -> Objects.equals(sffDataPlaneLocator.getName(), locatorName))
158                 .findAny()
159                 .map(SffDataPlaneLocator::getDataPlaneLocator)
160                 .filter(dataPlaneLocator -> dataPlaneLocator.getLocatorType() instanceof LogicalInterface)
161                 .map(dataPlaneLocator -> (LogicalInterfaceLocator) dataPlaneLocator.getLocatorType())
162                 .map(LogicalInterfaceLocator::getInterfaceName);
163
164         return interfaceName;
165     }
166
167     private Optional<ServiceFunctionForwarder> getServiceFunctionForwarder(SffName name) {
168         ServiceFunctionForwarderKey serviceFunctionForwarderKey = new ServiceFunctionForwarderKey(name);
169         InstanceIdentifier<ServiceFunctionForwarder> sffIid;
170         sffIid = InstanceIdentifier.builder(ServiceFunctionForwarders.class)
171                 .child(ServiceFunctionForwarder.class, serviceFunctionForwarderKey)
172                 .build();
173
174         return MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, sffIid).toJavaUtil();
175     }
176
177     private Optional<RenderedServicePathHop> getRspFirstHop(RenderedServicePath rsp) {
178         List<RenderedServicePathHop> hops = rsp.getRenderedServicePathHop();
179         if (hops == null || hops.isEmpty()) {
180             LOG.warn("getRspFirstHop RSP [{}] has no hops list", rsp.getName().getValue());
181             return Optional.empty();
182         }
183
184         return Optional.ofNullable(hops.get(0));
185     }
186
187     private Optional<RenderedServicePathHop> getRspLastHop(RenderedServicePath rsp) {
188         List<RenderedServicePathHop> hops = rsp.getRenderedServicePathHop();
189         if (hops == null || hops.isEmpty()) {
190             LOG.warn("getRspLastHop RSP [{}] has no hops list", rsp.getName().getValue());
191             return Optional.empty();
192         }
193
194         return Optional.ofNullable(hops.get(hops.size() - 1));
195     }
196 }