2 * Copyright (c) 2015 NEC Corporation. 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.vtn.manager.internal.routing;
11 import java.util.List;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
16 import org.apache.commons.collections15.Transformer;
18 import org.opendaylight.vtn.manager.PathPolicy;
19 import org.opendaylight.vtn.manager.VTNException;
21 import org.opendaylight.vtn.manager.internal.util.DataStoreUtils;
22 import org.opendaylight.vtn.manager.internal.util.inventory.InventoryReader;
23 import org.opendaylight.vtn.manager.internal.util.inventory.LinkEdge;
24 import org.opendaylight.vtn.manager.internal.util.inventory.NodeUtils;
25 import org.opendaylight.vtn.manager.internal.util.inventory.SalPort;
26 import org.opendaylight.vtn.manager.internal.util.pathpolicy.PathPolicyUtils;
28 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
29 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
30 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
31 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev150209.vtn.node.info.VtnPort;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.pathpolicy.rev150209.VtnPathPolicies;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.pathpolicy.rev150209.vtn.path.policies.VtnPathPolicy;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.pathpolicy.rev150209.vtn.path.policies.VtnPathPolicyKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.pathpolicy.rev150209.vtn.path.policy.config.VtnPathCost;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.pathpolicy.rev150209.vtn.path.policy.config.VtnPathCostKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnPortDesc;
44 * An implementation of {@link Transformer} that transforms link edge into
45 * the cost of the link.
48 * Note that this class is not synchronized.
51 final class PathPolicyTransformer implements Transformer<LinkEdge, Long> {
55 private static final Logger LOG =
56 LoggerFactory.getLogger(PathPolicyTransformer.class);
59 * A data broker service.
61 private final DataBroker dataBroker;
64 * The index of the path policy.
66 private final int policyId;
69 * VTN inventory reader.
71 private InventoryReader reader;
74 * A class which holds inventory reader and local DS transaction.
76 private final class InventoryReaderHolder {
78 * An inventory reader.
80 private final InventoryReader localReader;
83 * A read-only MD-SAL DS transaction.
85 private final ReadOnlyTransaction localTx;
88 * Construct a new instance.
90 private InventoryReaderHolder() {
91 InventoryReader rdr = reader;
93 // Create a new reader using local transaction.
94 localTx = dataBroker.newReadOnlyTransaction();
95 rdr = new InventoryReader(localTx);
104 * Return an inventory reader.
106 * @return A {@link InventoryReader} instance.
108 private InventoryReader getReader() {
113 * Close the MD-SAL DS transaction.
115 private void close() {
116 if (localTx != null) {
123 * Construct a new instance.
125 * @param broker A {@link DataBroker} service.
126 * @param id The index of the path policy associated with this
129 PathPolicyTransformer(DataBroker broker, int id) {
135 * Set inventory reader that contains active transaction for the MD-SAL
138 * @param rdr An {@link InventoryReader} instance.
139 * @return An {@link InventoryReader} currently configured is returned.
141 InventoryReader setReader(InventoryReader rdr) {
142 InventoryReader old = reader;
148 * Return the path cost associated with the given switch port.
150 * @param rdr A {@link InventoryReader} instance.
151 * @param sport A {@link SalPort} instance.
152 * @return A {@link Long} instance which represents the cost.
153 * {@code null} is returned if the default cost should be used.
154 * @throws VTNException An error occurred.
156 private Long getCost(InventoryReader rdr, SalPort sport)
157 throws VTNException {
158 VtnPort vport = rdr.get(sport);
160 // This should never happen.
161 LOG.warn("{}: Unknown port: {}", policyId, sport);
162 return Long.valueOf(Long.MAX_VALUE);
165 // Read path policy configuration.
166 VtnPathPolicyKey key = new VtnPathPolicyKey(Integer.valueOf(policyId));
167 InstanceIdentifier<VtnPathPolicy> path = InstanceIdentifier.
168 builder(VtnPathPolicies.class).
169 child(VtnPathPolicy.class, key).build();
170 LogicalDatastoreType oper = LogicalDatastoreType.OPERATIONAL;
171 ReadTransaction rtx = rdr.getReadTransaction();
172 VtnPathPolicy vpp = DataStoreUtils.read(rtx, oper, path).orNull();
174 LOG.debug("{}: Path policy not found: port={}", policyId, sport);
178 List<VtnPathCost> vcosts = vpp.getVtnPathCost();
179 if (vcosts != null && !vcosts.isEmpty()) {
180 VtnPortDesc[] descriptors =
181 NodeUtils.createPortDescArray(sport, vport);
182 for (VtnPortDesc vpdesc: descriptors) {
183 VtnPathCostKey ckey = new VtnPathCostKey(vpdesc);
184 InstanceIdentifier<VtnPathCost> cpath = InstanceIdentifier.
185 builder(VtnPathPolicies.class).
186 child(VtnPathPolicy.class, key).
187 child(VtnPathCost.class, ckey).build();
188 VtnPathCost vpc = DataStoreUtils.read(rtx, oper, cpath).
191 Long cost = vpc.getCost();
192 LOG.trace("{}: Path cost was found: port={}, desc={}, " +
193 "cost={}", policyId, sport, vpdesc.getValue(),
201 return getDefaultCost(vpp, sport, vport);
205 * Return the default path cost.
207 * @param vpp A {@link VtnPathPolicy} instance.
208 * @param sport A {@link SalPort} instance.
209 * @param vport A {@link VtnPort} instance.
210 * @return A {@link Long} instance which represents the cost.
211 * {@code null} is returned if the default cost should be used.
213 private Long getDefaultCost(VtnPathPolicy vpp, SalPort sport,
215 Long cost = vpp.getDefaultCost();
216 if (cost == null || cost.longValue() == PathPolicy.COST_UNDEF) {
217 cost = vport.getCost();
218 LOG.trace("{}: Use link cost in VTN port: port={}, cost={}",
219 policyId, sport, cost);
221 LOG.trace("{}: Use default cost: port={}, cost={}", policyId,
231 * Return the cost associated with the given link edge.
233 * @param le A {@link LinkEdge} instance.
234 * @return A {@link Long} instance which represents the cost.
237 public Long transform(LinkEdge le) {
239 LOG.warn("{}: Link edge is null.", policyId);
240 return Long.valueOf(Long.MAX_VALUE);
243 SalPort sport = le.getSourcePort();
245 LOG.warn("{}: Switch port is null: {}", policyId, le);
246 return Long.valueOf(Long.MAX_VALUE);
249 // Prepare MD-SAL datastore transaction.
250 InventoryReaderHolder holder = new InventoryReaderHolder();
253 cost = getCost(holder.getReader(), sport);
255 cost = PathPolicyUtils.DEFAULT_LINK_COST;
257 } catch (Exception e) {
258 StringBuilder builder = new StringBuilder();
259 builder.append(policyId).
260 append(": Failed to determine path cost for ").
261 append(le).append('.');
262 LOG.warn(builder.toString(), e);
263 cost = Long.valueOf(Long.MAX_VALUE);