blob: 01e07a767d93f9dcd3278b6288decb5031d1d74c [file] [log] [blame]
Pier1f87aca2018-03-14 16:47:32 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.segmentrouting;
18
19import org.onlab.graph.DefaultEdgeWeigher;
20import org.onlab.graph.ScalarWeight;
21import org.onlab.graph.Weight;
22import org.onosproject.net.DeviceId;
23import org.onosproject.net.Link;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.topology.LinkWeigher;
26import org.onosproject.net.topology.TopologyEdge;
27import org.onosproject.net.topology.TopologyVertex;
28import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
29
30import java.util.Set;
31
32/**
33 * Link weigher for multicast related path computations.
34 */
35public final class SRLinkWeigher
36 extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
37 implements LinkWeigher {
38
39 private final SegmentRoutingManager srManager;
40 private final DeviceId srcPath;
41 private final Set<Link> linksToEnforce;
42
43 // Weight for the link to avoids. The high level idea is to build
44 // a constrained shortest path computation. 100 should provide a good
45 // threshold
46 public static final ScalarWeight LINK_TO_AVOID_WEIGHT = new ScalarWeight(HOP_WEIGHT_VALUE + 100);
47
48 /**
49 * Creates a SRLinkWeigher object.
50 *
51 * @param srManager SegmentRoutingManager object
52 * @param srcPath the source of the paths
53 * @param linksToEnforce links to be enforced by the path computation
54 */
55 public SRLinkWeigher(SegmentRoutingManager srManager, DeviceId srcPath,
56 Set<Link> linksToEnforce) {
57 this.srManager = srManager;
58 this.srcPath = srcPath;
59 this.linksToEnforce = linksToEnforce;
60 }
61
62 @Override
63 public Weight weight(TopologyEdge edge) {
64 // 1) We need to avoid some particular paths like leaf-spine-leaf-*
65 // 2) Properly handle the pair links
66
67 // If the link is a pair link just return infinite value
68 if (isPairLink(edge.link())) {
69 return ScalarWeight.NON_VIABLE_WEIGHT;
70 }
71
72 // To avoid that the paths go through other leaves we need to influence
73 // the path computation to return infinite value for all other links having
74 // as a src a leaf different from the source we are passing to the weigher
75 DeviceId srcDeviceLink = edge.link().src().deviceId();
76 // Identify the link as leaf-spine link
77 boolean isLeafSpine;
78 try {
79 isLeafSpine = srManager.deviceConfiguration().isEdgeDevice(srcDeviceLink);
80 } catch (DeviceConfigNotFoundException e) {
81 isLeafSpine = false;
82 }
83 // If it is not the source just return infinite value
84 if (isLeafSpine && !srcDeviceLink.equals(srcPath)) {
85 return ScalarWeight.NON_VIABLE_WEIGHT;
86 }
87
88 // If the links are not in the list of the links to be enforce
89 if (!linksToEnforce.isEmpty() && !linksToEnforce.contains(edge.link())) {
90 // 100 should be a good confidence threshold
91 return LINK_TO_AVOID_WEIGHT;
92 }
93
94 // All other cases we return
95 return new ScalarWeight(HOP_WEIGHT_VALUE);
96 }
97
98 // Utility method to verify is a link is a pair-link
99 private boolean isPairLink(Link link) {
100 // Take src id, src port, dst id and dst port
101 final DeviceId srcId = link.src().deviceId();
102 final PortNumber srcPort = link.src().port();
103 final DeviceId dstId = link.dst().deviceId();
104 final PortNumber dstPort = link.dst().port();
105 // init as true
106 boolean isPairLink = true;
107 try {
108 // If one of this condition is not true; it is not a pair link
109 if (!(srManager.deviceConfiguration().isEdgeDevice(srcId) &&
110 srManager.deviceConfiguration().isEdgeDevice(dstId) &&
111 srManager.deviceConfiguration().getPairDeviceId(srcId).equals(dstId) &&
112 srManager.deviceConfiguration().getPairLocalPort(srcId).equals(srcPort) &&
113 srManager.deviceConfiguration().getPairLocalPort(dstId).equals(dstPort))) {
114 isPairLink = false;
115 }
116 } catch (DeviceConfigNotFoundException e) {
117 // Configuration not provided
118 isPairLink = false;
119 }
120 return isPairLink;
121 }
122
123}