Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
61 changed files
with
1417 additions
and
258 deletions
... | @@ -15,18 +15,29 @@ | ... | @@ -15,18 +15,29 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.calendar; | 16 | package org.onlab.onos.calendar; |
17 | 17 | ||
18 | -import org.onlab.onos.net.ConnectPoint; | 18 | +import java.net.URI; |
19 | -import org.onlab.onos.net.DeviceId; | ||
20 | -import org.onlab.onos.net.intent.IntentService; | ||
21 | -import org.onlab.rest.BaseResource; | ||
22 | 19 | ||
23 | import javax.ws.rs.POST; | 20 | import javax.ws.rs.POST; |
24 | import javax.ws.rs.Path; | 21 | import javax.ws.rs.Path; |
25 | import javax.ws.rs.PathParam; | 22 | import javax.ws.rs.PathParam; |
26 | import javax.ws.rs.core.Response; | 23 | import javax.ws.rs.core.Response; |
27 | -import java.net.URI; | 24 | + |
25 | +import org.onlab.onos.core.ApplicationId; | ||
26 | +import org.onlab.onos.core.CoreService; | ||
27 | +import org.onlab.onos.net.ConnectPoint; | ||
28 | +import org.onlab.onos.net.DeviceId; | ||
29 | +import org.onlab.onos.net.flow.DefaultTrafficSelector; | ||
30 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
31 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
32 | +import org.onlab.onos.net.intent.Intent; | ||
33 | +import org.onlab.onos.net.intent.IntentService; | ||
34 | +import org.onlab.onos.net.intent.PointToPointIntentWithBandwidthConstraint; | ||
35 | +import org.onlab.onos.net.resource.BandwidthResourceRequest; | ||
36 | +import org.onlab.packet.Ethernet; | ||
37 | +import org.onlab.rest.BaseResource; | ||
28 | 38 | ||
29 | import static org.onlab.onos.net.PortNumber.portNumber; | 39 | import static org.onlab.onos.net.PortNumber.portNumber; |
40 | +import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; | ||
30 | 41 | ||
31 | /** | 42 | /** |
32 | * Web resource for triggering calendared intents. | 43 | * Web resource for triggering calendared intents. |
... | @@ -47,12 +58,33 @@ public class BandwidthCalendarResource extends BaseResource { | ... | @@ -47,12 +58,33 @@ public class BandwidthCalendarResource extends BaseResource { |
47 | ConnectPoint srcPoint = new ConnectPoint(deviceId(src), portNumber(srcPort)); | 58 | ConnectPoint srcPoint = new ConnectPoint(deviceId(src), portNumber(srcPort)); |
48 | ConnectPoint dstPoint = new ConnectPoint(deviceId(dst), portNumber(dstPort)); | 59 | ConnectPoint dstPoint = new ConnectPoint(deviceId(dst), portNumber(dstPort)); |
49 | 60 | ||
61 | + TrafficSelector selector = buildTrafficSelector(); | ||
62 | + TrafficTreatment treatment = builder().build(); | ||
63 | + | ||
64 | + Intent intent = new PointToPointIntentWithBandwidthConstraint( | ||
65 | + appId(), selector, treatment, | ||
66 | + srcPoint, dstPoint, new BandwidthResourceRequest(Double.parseDouble(bandwidth))); | ||
67 | + service.submit(intent); | ||
68 | + | ||
50 | return Response.ok("Yo! We got src=" + srcPoint + "; dst=" + dstPoint + | 69 | return Response.ok("Yo! We got src=" + srcPoint + "; dst=" + dstPoint + |
51 | "; bw=" + bandwidth + "; intent service " + service).build(); | 70 | "; bw=" + bandwidth + "; intent service " + service).build(); |
52 | } | 71 | } |
53 | 72 | ||
73 | + private TrafficSelector buildTrafficSelector() { | ||
74 | + TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); | ||
75 | + Short ethType = Ethernet.TYPE_IPV4; | ||
76 | + | ||
77 | + selectorBuilder.matchEthType(ethType); | ||
78 | + | ||
79 | + return selectorBuilder.build(); | ||
80 | + } | ||
81 | + | ||
54 | private DeviceId deviceId(String dpid) { | 82 | private DeviceId deviceId(String dpid) { |
55 | return DeviceId.deviceId(URI.create("of:" + dpid)); | 83 | return DeviceId.deviceId(URI.create("of:" + dpid)); |
56 | } | 84 | } |
57 | 85 | ||
86 | + protected ApplicationId appId() { | ||
87 | + return get(CoreService.class).registerApplication("org.onlab.onos.calendar"); | ||
88 | + } | ||
89 | + | ||
58 | } | 90 | } | ... | ... |
... | @@ -76,7 +76,7 @@ | ... | @@ -76,7 +76,7 @@ |
76 | "nodeName1": "ROUTER1", | 76 | "nodeName1": "ROUTER1", |
77 | "nodeName2": "ROADM1", | 77 | "nodeName2": "ROADM1", |
78 | "bandWidth": 100000, | 78 | "bandWidth": 100000, |
79 | - "port1": 1, | 79 | + "port1": 2, |
80 | "port2": 10 | 80 | "port2": 10 |
81 | }, | 81 | }, |
82 | "type": "pktOptLink" | 82 | "type": "pktOptLink" |
... | @@ -90,7 +90,7 @@ | ... | @@ -90,7 +90,7 @@ |
90 | "nodeName1": "ROUTER2", | 90 | "nodeName1": "ROUTER2", |
91 | "nodeName2": "ROADM2", | 91 | "nodeName2": "ROADM2", |
92 | "bandWidth": 100000, | 92 | "bandWidth": 100000, |
93 | - "port1": 1, | 93 | + "port1": 2, |
94 | "port2": 11 | 94 | "port2": 11 |
95 | }, | 95 | }, |
96 | "type": "pktOptLink" | 96 | "type": "pktOptLink" | ... | ... |
cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentWithBandwidthConstraintCommand.java
0 → 100644
1 | +/* | ||
2 | + * Licensed to the Apache Software Foundation (ASF) under one | ||
3 | + * or more contributor license agreements. See the NOTICE file | ||
4 | + * distributed with this work for additional information | ||
5 | + * regarding copyright ownership. The ASF licenses this file | ||
6 | + * to you under the Apache License, Version 2.0 (the | ||
7 | + * "License"); you may not use this file except in compliance | ||
8 | + * with the License. You may obtain a copy of the License at | ||
9 | + * | ||
10 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + * | ||
12 | + * Unless required by applicable law or agreed to in writing, | ||
13 | + * software distributed under the License is distributed on an | ||
14 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
15 | + * KIND, either express or implied. See the License for the | ||
16 | + * specific language governing permissions and limitations | ||
17 | + * under the License. | ||
18 | + */ | ||
19 | +package org.onlab.onos.cli.net; | ||
20 | + | ||
21 | +import org.apache.karaf.shell.commands.Argument; | ||
22 | +import org.apache.karaf.shell.commands.Command; | ||
23 | +import org.onlab.onos.net.ConnectPoint; | ||
24 | +import org.onlab.onos.net.DeviceId; | ||
25 | +import org.onlab.onos.net.PortNumber; | ||
26 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
27 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
28 | +import org.onlab.onos.net.intent.Intent; | ||
29 | +import org.onlab.onos.net.intent.IntentService; | ||
30 | +import org.onlab.onos.net.intent.PointToPointIntentWithBandwidthConstraint; | ||
31 | +import org.onlab.onos.net.resource.BandwidthResourceRequest; | ||
32 | + | ||
33 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
34 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
35 | +import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; | ||
36 | + | ||
37 | +/** | ||
38 | + * Installs point-to-point connectivity intents. | ||
39 | + */ | ||
40 | +@Command(scope = "onos", name = "add-point-intent-bw", | ||
41 | + description = "Installs point-to-point connectivity intent with bandwidth constraint") | ||
42 | +public class AddPointToPointIntentWithBandwidthConstraintCommand extends ConnectivityIntentCommand { | ||
43 | + | ||
44 | + @Argument(index = 0, name = "ingressDevice", | ||
45 | + description = "Ingress Device/Port Description", | ||
46 | + required = true, multiValued = false) | ||
47 | + String ingressDeviceString = null; | ||
48 | + | ||
49 | + @Argument(index = 1, name = "egressDevice", | ||
50 | + description = "Egress Device/Port Description", | ||
51 | + required = true, multiValued = false) | ||
52 | + String egressDeviceString = null; | ||
53 | + | ||
54 | + @Argument(index = 2, name = "bandwidth", | ||
55 | + description = "Bandwidth", | ||
56 | + required = true, multiValued = false) | ||
57 | + String bandwidthString = null; | ||
58 | + | ||
59 | + @Override | ||
60 | + protected void execute() { | ||
61 | + IntentService service = get(IntentService.class); | ||
62 | + | ||
63 | + DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString)); | ||
64 | + PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString)); | ||
65 | + ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber); | ||
66 | + | ||
67 | + DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString)); | ||
68 | + PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString)); | ||
69 | + ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber); | ||
70 | + | ||
71 | + long bandwidth = Long.parseLong(bandwidthString); | ||
72 | + | ||
73 | + TrafficSelector selector = buildTrafficSelector(); | ||
74 | + TrafficTreatment treatment = builder().build(); | ||
75 | + | ||
76 | + Intent intent = new PointToPointIntentWithBandwidthConstraint( | ||
77 | + appId(), selector, treatment, | ||
78 | + ingress, egress, new BandwidthResourceRequest(bandwidth)); | ||
79 | + service.submit(intent); | ||
80 | + } | ||
81 | + | ||
82 | + /** | ||
83 | + * Extracts the port number portion of the ConnectPoint. | ||
84 | + * | ||
85 | + * @param deviceString string representing the device/port | ||
86 | + * @return port number as a string, empty string if the port is not found | ||
87 | + */ | ||
88 | + private String getPortNumber(String deviceString) { | ||
89 | + int slash = deviceString.indexOf('/'); | ||
90 | + if (slash <= 0) { | ||
91 | + return ""; | ||
92 | + } | ||
93 | + return deviceString.substring(slash + 1, deviceString.length()); | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * Extracts the device ID portion of the ConnectPoint. | ||
98 | + * | ||
99 | + * @param deviceString string representing the device/port | ||
100 | + * @return device ID string | ||
101 | + */ | ||
102 | + private String getDeviceId(String deviceString) { | ||
103 | + int slash = deviceString.indexOf('/'); | ||
104 | + if (slash <= 0) { | ||
105 | + return ""; | ||
106 | + } | ||
107 | + return deviceString.substring(0, slash); | ||
108 | + } | ||
109 | +} |
... | @@ -47,8 +47,8 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { | ... | @@ -47,8 +47,8 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { |
47 | */ | 47 | */ |
48 | protected TrafficSelector buildTrafficSelector() { | 48 | protected TrafficSelector buildTrafficSelector() { |
49 | TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); | 49 | TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(); |
50 | - | ||
51 | Short ethType = Ethernet.TYPE_IPV4; | 50 | Short ethType = Ethernet.TYPE_IPV4; |
51 | + | ||
52 | if (!Strings.isNullOrEmpty(ethTypeString)) { | 52 | if (!Strings.isNullOrEmpty(ethTypeString)) { |
53 | EthType ethTypeParameter = EthType.valueOf(ethTypeString); | 53 | EthType ethTypeParameter = EthType.valueOf(ethTypeString); |
54 | ethType = ethTypeParameter.value(); | 54 | ethType = ethTypeParameter.value(); | ... | ... |
... | @@ -40,7 +40,7 @@ import static org.onlab.onos.net.DeviceId.deviceId; | ... | @@ -40,7 +40,7 @@ import static org.onlab.onos.net.DeviceId.deviceId; |
40 | description = "Lists all ports or all ports of a device") | 40 | description = "Lists all ports or all ports of a device") |
41 | public class DevicePortsListCommand extends DevicesListCommand { | 41 | public class DevicePortsListCommand extends DevicesListCommand { |
42 | 42 | ||
43 | - private static final String FMT = " port=%s, state=%s%s"; | 43 | + private static final String FMT = " port=%s, state=%s, type=%s, speed=%s%s"; |
44 | 44 | ||
45 | @Option(name = "-e", aliases = "--enabled", description = "Show only enabled ports", | 45 | @Option(name = "-e", aliases = "--enabled", description = "Show only enabled ports", |
46 | required = false, multiValued = false) | 46 | required = false, multiValued = false) |
... | @@ -110,10 +110,14 @@ public class DevicePortsListCommand extends DevicesListCommand { | ... | @@ -110,10 +110,14 @@ public class DevicePortsListCommand extends DevicesListCommand { |
110 | ports.add(mapper.createObjectNode() | 110 | ports.add(mapper.createObjectNode() |
111 | .put("port", port.number().toString()) | 111 | .put("port", port.number().toString()) |
112 | .put("isEnabled", port.isEnabled()) | 112 | .put("isEnabled", port.isEnabled()) |
113 | + .put("type", port.type().toString().toLowerCase()) | ||
114 | + .put("portSpeed", port.portSpeed()) | ||
113 | .set("annotations", annotations(mapper, port.annotations()))); | 115 | .set("annotations", annotations(mapper, port.annotations()))); |
114 | } | 116 | } |
115 | } | 117 | } |
116 | - return result.put("device", device.id().toString()).set("ports", ports); | 118 | + result.set("device", json(service, mapper, device)); |
119 | + result.set("ports", ports); | ||
120 | + return result; | ||
117 | } | 121 | } |
118 | 122 | ||
119 | // Determines if a port should be included in output. | 123 | // Determines if a port should be included in output. |
... | @@ -130,6 +134,7 @@ public class DevicePortsListCommand extends DevicesListCommand { | ... | @@ -130,6 +134,7 @@ public class DevicePortsListCommand extends DevicesListCommand { |
130 | for (Port port : ports) { | 134 | for (Port port : ports) { |
131 | if (isIncluded(port)) { | 135 | if (isIncluded(port)) { |
132 | print(FMT, port.number(), port.isEnabled() ? "enabled" : "disabled", | 136 | print(FMT, port.number(), port.isEnabled() ? "enabled" : "disabled", |
137 | + port.type().toString().toLowerCase(), port.portSpeed(), | ||
133 | annotations(port.annotations())); | 138 | annotations(port.annotations())); |
134 | } | 139 | } |
135 | } | 140 | } | ... | ... |
... | @@ -116,6 +116,17 @@ | ... | @@ -116,6 +116,17 @@ |
116 | </optional-completers> | 116 | </optional-completers> |
117 | </command> | 117 | </command> |
118 | <command> | 118 | <command> |
119 | + <action class="org.onlab.onos.cli.net.AddPointToPointIntentWithBandwidthConstraintCommand"/> | ||
120 | + <completers> | ||
121 | + <ref component-id="connectPointCompleter"/> | ||
122 | + <ref component-id="connectPointCompleter"/> | ||
123 | + <null/> | ||
124 | + </completers> | ||
125 | + <optional-completers> | ||
126 | + <entry key="-t" value-ref="ethTypeCompleter"/> | ||
127 | + </optional-completers> | ||
128 | + </command> | ||
129 | + <command> | ||
119 | <action class="org.onlab.onos.cli.net.AddOpticalIntentCommand"/> | 130 | <action class="org.onlab.onos.cli.net.AddOpticalIntentCommand"/> |
120 | <completers> | 131 | <completers> |
121 | <ref component-id="connectPointCompleter"/> | 132 | <ref component-id="connectPointCompleter"/> | ... | ... |
... | @@ -35,6 +35,11 @@ public class RoleInfo { | ... | @@ -35,6 +35,11 @@ public class RoleInfo { |
35 | this.backups = ImmutableList.copyOf(backups); | 35 | this.backups = ImmutableList.copyOf(backups); |
36 | } | 36 | } |
37 | 37 | ||
38 | + public RoleInfo() { | ||
39 | + this.master = null; | ||
40 | + this.backups = ImmutableList.of(); | ||
41 | + } | ||
42 | + | ||
38 | public NodeId master() { | 43 | public NodeId master() { |
39 | return master; | 44 | return master; |
40 | } | 45 | } |
... | @@ -63,7 +68,7 @@ public class RoleInfo { | ... | @@ -63,7 +68,7 @@ public class RoleInfo { |
63 | 68 | ||
64 | @Override | 69 | @Override |
65 | public int hashCode() { | 70 | public int hashCode() { |
66 | - return Objects.hash(master, backups.hashCode()); | 71 | + return Objects.hash(master, backups); |
67 | } | 72 | } |
68 | 73 | ||
69 | @Override | 74 | @Override | ... | ... |
... | @@ -24,9 +24,27 @@ import static com.google.common.base.MoreObjects.toStringHelper; | ... | @@ -24,9 +24,27 @@ import static com.google.common.base.MoreObjects.toStringHelper; |
24 | */ | 24 | */ |
25 | public class DefaultPort extends AbstractAnnotated implements Port { | 25 | public class DefaultPort extends AbstractAnnotated implements Port { |
26 | 26 | ||
27 | + /** Default port speed in Mbps. */ | ||
28 | + public static final long DEFAULT_SPEED = 1_000; | ||
29 | + | ||
27 | private final Element element; | 30 | private final Element element; |
28 | private final PortNumber number; | 31 | private final PortNumber number; |
29 | private final boolean isEnabled; | 32 | private final boolean isEnabled; |
33 | + private final Type type; | ||
34 | + private final long portSpeed; | ||
35 | + | ||
36 | + /** | ||
37 | + * Creates a network element attributed to the specified provider. | ||
38 | + * | ||
39 | + * @param element parent network element | ||
40 | + * @param number port number | ||
41 | + * @param isEnabled indicator whether the port is up and active | ||
42 | + * @param annotations optional key/value annotations | ||
43 | + */ | ||
44 | + public DefaultPort(Element element, PortNumber number, boolean isEnabled, | ||
45 | + Annotations... annotations) { | ||
46 | + this(element, number, isEnabled, Type.COPPER, DEFAULT_SPEED, annotations); | ||
47 | + } | ||
30 | 48 | ||
31 | /** | 49 | /** |
32 | * Creates a network element attributed to the specified provider. | 50 | * Creates a network element attributed to the specified provider. |
... | @@ -34,19 +52,49 @@ public class DefaultPort extends AbstractAnnotated implements Port { | ... | @@ -34,19 +52,49 @@ public class DefaultPort extends AbstractAnnotated implements Port { |
34 | * @param element parent network element | 52 | * @param element parent network element |
35 | * @param number port number | 53 | * @param number port number |
36 | * @param isEnabled indicator whether the port is up and active | 54 | * @param isEnabled indicator whether the port is up and active |
55 | + * @param type port type | ||
56 | + * @param portSpeed port speed in Mbs | ||
37 | * @param annotations optional key/value annotations | 57 | * @param annotations optional key/value annotations |
38 | */ | 58 | */ |
39 | - public DefaultPort(Element element, PortNumber number, | 59 | + public DefaultPort(Element element, PortNumber number, boolean isEnabled, |
40 | - boolean isEnabled, Annotations... annotations) { | 60 | + Type type, long portSpeed, Annotations... annotations) { |
41 | super(annotations); | 61 | super(annotations); |
42 | this.element = element; | 62 | this.element = element; |
43 | this.number = number; | 63 | this.number = number; |
44 | this.isEnabled = isEnabled; | 64 | this.isEnabled = isEnabled; |
65 | + this.type = type; | ||
66 | + this.portSpeed = portSpeed; | ||
67 | + | ||
68 | + } | ||
69 | + | ||
70 | + @Override | ||
71 | + public Element element() { | ||
72 | + return element; | ||
73 | + } | ||
74 | + | ||
75 | + @Override | ||
76 | + public PortNumber number() { | ||
77 | + return number; | ||
78 | + } | ||
79 | + | ||
80 | + @Override | ||
81 | + public boolean isEnabled() { | ||
82 | + return isEnabled; | ||
83 | + } | ||
84 | + | ||
85 | + @Override | ||
86 | + public Type type() { | ||
87 | + return type; | ||
88 | + } | ||
89 | + | ||
90 | + @Override | ||
91 | + public long portSpeed() { | ||
92 | + return portSpeed; | ||
45 | } | 93 | } |
46 | 94 | ||
47 | @Override | 95 | @Override |
48 | public int hashCode() { | 96 | public int hashCode() { |
49 | - return Objects.hash(number, isEnabled); | 97 | + return Objects.hash(number, isEnabled, type, portSpeed); |
50 | } | 98 | } |
51 | 99 | ||
52 | @Override | 100 | @Override |
... | @@ -58,7 +106,9 @@ public class DefaultPort extends AbstractAnnotated implements Port { | ... | @@ -58,7 +106,9 @@ public class DefaultPort extends AbstractAnnotated implements Port { |
58 | final DefaultPort other = (DefaultPort) obj; | 106 | final DefaultPort other = (DefaultPort) obj; |
59 | return Objects.equals(this.element.id(), other.element.id()) && | 107 | return Objects.equals(this.element.id(), other.element.id()) && |
60 | Objects.equals(this.number, other.number) && | 108 | Objects.equals(this.number, other.number) && |
61 | - Objects.equals(this.isEnabled, other.isEnabled); | 109 | + Objects.equals(this.isEnabled, other.isEnabled) && |
110 | + Objects.equals(this.type, other.type) && | ||
111 | + Objects.equals(this.portSpeed, other.portSpeed); | ||
62 | } | 112 | } |
63 | return false; | 113 | return false; |
64 | } | 114 | } |
... | @@ -69,22 +119,9 @@ public class DefaultPort extends AbstractAnnotated implements Port { | ... | @@ -69,22 +119,9 @@ public class DefaultPort extends AbstractAnnotated implements Port { |
69 | .add("element", element.id()) | 119 | .add("element", element.id()) |
70 | .add("number", number) | 120 | .add("number", number) |
71 | .add("isEnabled", isEnabled) | 121 | .add("isEnabled", isEnabled) |
122 | + .add("type", type) | ||
123 | + .add("portSpeed", portSpeed) | ||
72 | .toString(); | 124 | .toString(); |
73 | } | 125 | } |
74 | 126 | ||
75 | - @Override | ||
76 | - public PortNumber number() { | ||
77 | - return number; | ||
78 | - } | ||
79 | - | ||
80 | - @Override | ||
81 | - public boolean isEnabled() { | ||
82 | - return isEnabled; | ||
83 | - } | ||
84 | - | ||
85 | - @Override | ||
86 | - public Element element() { | ||
87 | - return element; | ||
88 | - } | ||
89 | - | ||
90 | } | 127 | } | ... | ... |
... | @@ -21,6 +21,26 @@ package org.onlab.onos.net; | ... | @@ -21,6 +21,26 @@ package org.onlab.onos.net; |
21 | */ | 21 | */ |
22 | public interface Port extends Annotated { | 22 | public interface Port extends Annotated { |
23 | 23 | ||
24 | + /** Represents coarse port type classification. */ | ||
25 | + public enum Type { | ||
26 | + /** | ||
27 | + * Signifies copper-based connectivity. | ||
28 | + */ | ||
29 | + COPPER, | ||
30 | + | ||
31 | + /** | ||
32 | + * Signifies optical fiber-based connectivity. | ||
33 | + */ | ||
34 | + FIBER | ||
35 | + } | ||
36 | + | ||
37 | + /** | ||
38 | + * Returns the parent network element to which this port belongs. | ||
39 | + * | ||
40 | + * @return parent network element | ||
41 | + */ | ||
42 | + Element element(); | ||
43 | + | ||
24 | /** | 44 | /** |
25 | * Returns the port number. | 45 | * Returns the port number. |
26 | * | 46 | * |
... | @@ -36,12 +56,18 @@ public interface Port extends Annotated { | ... | @@ -36,12 +56,18 @@ public interface Port extends Annotated { |
36 | boolean isEnabled(); | 56 | boolean isEnabled(); |
37 | 57 | ||
38 | /** | 58 | /** |
39 | - * Returns the parent network element to which this port belongs. | 59 | + * Returns the port type. |
40 | * | 60 | * |
41 | - * @return parent network element | 61 | + * @return port type |
42 | */ | 62 | */ |
43 | - Element element(); | 63 | + Type type(); |
44 | 64 | ||
45 | - // set of port attributes | 65 | + /** |
66 | + * Returns the current port speed in Mbps. | ||
67 | + * | ||
68 | + * @return current port speed | ||
69 | + */ | ||
70 | + long portSpeed(); | ||
46 | 71 | ||
72 | + // TODO: more attributes? | ||
47 | } | 73 | } | ... | ... |
... | @@ -15,11 +15,12 @@ | ... | @@ -15,11 +15,12 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.device; | 16 | package org.onlab.onos.net.device; |
17 | 17 | ||
18 | +import com.google.common.base.MoreObjects; | ||
18 | import org.onlab.onos.net.AbstractDescription; | 19 | import org.onlab.onos.net.AbstractDescription; |
19 | import org.onlab.onos.net.PortNumber; | 20 | import org.onlab.onos.net.PortNumber; |
20 | import org.onlab.onos.net.SparseAnnotations; | 21 | import org.onlab.onos.net.SparseAnnotations; |
21 | 22 | ||
22 | -import com.google.common.base.MoreObjects; | 23 | +import static org.onlab.onos.net.Port.Type; |
23 | 24 | ||
24 | /** | 25 | /** |
25 | * Default implementation of immutable port description. | 26 | * Default implementation of immutable port description. |
... | @@ -27,8 +28,12 @@ import com.google.common.base.MoreObjects; | ... | @@ -27,8 +28,12 @@ import com.google.common.base.MoreObjects; |
27 | public class DefaultPortDescription extends AbstractDescription | 28 | public class DefaultPortDescription extends AbstractDescription |
28 | implements PortDescription { | 29 | implements PortDescription { |
29 | 30 | ||
31 | + private static final long DEFAULT_SPEED = 1_000; | ||
32 | + | ||
30 | private final PortNumber number; | 33 | private final PortNumber number; |
31 | private final boolean isEnabled; | 34 | private final boolean isEnabled; |
35 | + private final Type type; | ||
36 | + private final long portSpeed; | ||
32 | 37 | ||
33 | /** | 38 | /** |
34 | * Creates a port description using the supplied information. | 39 | * Creates a port description using the supplied information. |
... | @@ -39,9 +44,34 @@ public class DefaultPortDescription extends AbstractDescription | ... | @@ -39,9 +44,34 @@ public class DefaultPortDescription extends AbstractDescription |
39 | */ | 44 | */ |
40 | public DefaultPortDescription(PortNumber number, boolean isEnabled, | 45 | public DefaultPortDescription(PortNumber number, boolean isEnabled, |
41 | SparseAnnotations... annotations) { | 46 | SparseAnnotations... annotations) { |
47 | + this(number, isEnabled, Type.COPPER, DEFAULT_SPEED, annotations); | ||
48 | + } | ||
49 | + | ||
50 | + /** | ||
51 | + * Creates a port description using the supplied information. | ||
52 | + * | ||
53 | + * @param number port number | ||
54 | + * @param isEnabled port enabled state | ||
55 | + * @param type port type | ||
56 | + * @param portSpeed port speed in Mbps | ||
57 | + * @param annotations optional key/value annotations map | ||
58 | + */ | ||
59 | + public DefaultPortDescription(PortNumber number, boolean isEnabled, | ||
60 | + Type type, long portSpeed, | ||
61 | + SparseAnnotations...annotations) { | ||
42 | super(annotations); | 62 | super(annotations); |
43 | this.number = number; | 63 | this.number = number; |
44 | this.isEnabled = isEnabled; | 64 | this.isEnabled = isEnabled; |
65 | + this.type = type; | ||
66 | + this.portSpeed = portSpeed; | ||
67 | + } | ||
68 | + | ||
69 | + // Default constructor for serialization | ||
70 | + private DefaultPortDescription() { | ||
71 | + this.number = null; | ||
72 | + this.isEnabled = false; | ||
73 | + this.portSpeed = DEFAULT_SPEED; | ||
74 | + this.type = Type.COPPER; | ||
45 | } | 75 | } |
46 | 76 | ||
47 | /** | 77 | /** |
... | @@ -52,7 +82,8 @@ public class DefaultPortDescription extends AbstractDescription | ... | @@ -52,7 +82,8 @@ public class DefaultPortDescription extends AbstractDescription |
52 | */ | 82 | */ |
53 | public DefaultPortDescription(PortDescription base, | 83 | public DefaultPortDescription(PortDescription base, |
54 | SparseAnnotations annotations) { | 84 | SparseAnnotations annotations) { |
55 | - this(base.portNumber(), base.isEnabled(), annotations); | 85 | + this(base.portNumber(), base.isEnabled(), base.type(), base.portSpeed(), |
86 | + annotations); | ||
56 | } | 87 | } |
57 | 88 | ||
58 | @Override | 89 | @Override |
... | @@ -66,17 +97,24 @@ public class DefaultPortDescription extends AbstractDescription | ... | @@ -66,17 +97,24 @@ public class DefaultPortDescription extends AbstractDescription |
66 | } | 97 | } |
67 | 98 | ||
68 | @Override | 99 | @Override |
100 | + public Type type() { | ||
101 | + return type; | ||
102 | + } | ||
103 | + | ||
104 | + @Override | ||
105 | + public long portSpeed() { | ||
106 | + return portSpeed; | ||
107 | + } | ||
108 | + | ||
109 | + @Override | ||
69 | public String toString() { | 110 | public String toString() { |
70 | return MoreObjects.toStringHelper(getClass()) | 111 | return MoreObjects.toStringHelper(getClass()) |
71 | .add("number", number) | 112 | .add("number", number) |
72 | .add("isEnabled", isEnabled) | 113 | .add("isEnabled", isEnabled) |
114 | + .add("type", type) | ||
115 | + .add("portSpeed", portSpeed) | ||
73 | .add("annotations", annotations()) | 116 | .add("annotations", annotations()) |
74 | .toString(); | 117 | .toString(); |
75 | } | 118 | } |
76 | 119 | ||
77 | - // default constructor for serialization | ||
78 | - private DefaultPortDescription() { | ||
79 | - this.number = null; | ||
80 | - this.isEnabled = false; | ||
81 | - } | ||
82 | } | 120 | } | ... | ... |
... | @@ -18,13 +18,13 @@ package org.onlab.onos.net.device; | ... | @@ -18,13 +18,13 @@ package org.onlab.onos.net.device; |
18 | import org.onlab.onos.net.Description; | 18 | import org.onlab.onos.net.Description; |
19 | import org.onlab.onos.net.PortNumber; | 19 | import org.onlab.onos.net.PortNumber; |
20 | 20 | ||
21 | +import static org.onlab.onos.net.Port.Type; | ||
22 | + | ||
21 | /** | 23 | /** |
22 | * Information about a port. | 24 | * Information about a port. |
23 | */ | 25 | */ |
24 | public interface PortDescription extends Description { | 26 | public interface PortDescription extends Description { |
25 | 27 | ||
26 | - // TODO: possibly relocate this to a common ground so that this can also used by host tracking if required | ||
27 | - | ||
28 | /** | 28 | /** |
29 | * Returns the port number. | 29 | * Returns the port number. |
30 | * | 30 | * |
... | @@ -39,4 +39,18 @@ public interface PortDescription extends Description { | ... | @@ -39,4 +39,18 @@ public interface PortDescription extends Description { |
39 | */ | 39 | */ |
40 | boolean isEnabled(); | 40 | boolean isEnabled(); |
41 | 41 | ||
42 | + /** | ||
43 | + * Returns the port type. | ||
44 | + * | ||
45 | + * @return port type | ||
46 | + */ | ||
47 | + Type type(); | ||
48 | + | ||
49 | + /** | ||
50 | + * Returns the current port speed in Mbps. | ||
51 | + * | ||
52 | + * @return current port speed | ||
53 | + */ | ||
54 | + long portSpeed(); | ||
55 | + | ||
42 | } | 56 | } | ... | ... |
... | @@ -20,6 +20,7 @@ import org.onlab.onos.core.ApplicationId; | ... | @@ -20,6 +20,7 @@ import org.onlab.onos.core.ApplicationId; |
20 | import org.onlab.onos.net.Path; | 20 | import org.onlab.onos.net.Path; |
21 | import org.onlab.onos.net.flow.TrafficSelector; | 21 | import org.onlab.onos.net.flow.TrafficSelector; |
22 | import org.onlab.onos.net.flow.TrafficTreatment; | 22 | import org.onlab.onos.net.flow.TrafficTreatment; |
23 | +import org.onlab.onos.net.resource.LinkResourceRequest; | ||
23 | 24 | ||
24 | /** | 25 | /** |
25 | * Abstraction of explicitly path specified connectivity intent. | 26 | * Abstraction of explicitly path specified connectivity intent. |
... | @@ -27,6 +28,7 @@ import org.onlab.onos.net.flow.TrafficTreatment; | ... | @@ -27,6 +28,7 @@ import org.onlab.onos.net.flow.TrafficTreatment; |
27 | public class PathIntent extends ConnectivityIntent { | 28 | public class PathIntent extends ConnectivityIntent { |
28 | 29 | ||
29 | private final Path path; | 30 | private final Path path; |
31 | + private final LinkResourceRequest[] resourceRequests; | ||
30 | 32 | ||
31 | /** | 33 | /** |
32 | * Creates a new point-to-point intent with the supplied ingress/egress | 34 | * Creates a new point-to-point intent with the supplied ingress/egress |
... | @@ -39,10 +41,11 @@ public class PathIntent extends ConnectivityIntent { | ... | @@ -39,10 +41,11 @@ public class PathIntent extends ConnectivityIntent { |
39 | * @throws NullPointerException {@code path} is null | 41 | * @throws NullPointerException {@code path} is null |
40 | */ | 42 | */ |
41 | public PathIntent(ApplicationId appId, TrafficSelector selector, | 43 | public PathIntent(ApplicationId appId, TrafficSelector selector, |
42 | - TrafficTreatment treatment, Path path) { | 44 | + TrafficTreatment treatment, Path path, LinkResourceRequest[] resourceRequests) { |
43 | super(id(PathIntent.class, selector, treatment, path), appId, | 45 | super(id(PathIntent.class, selector, treatment, path), appId, |
44 | resources(path.links()), selector, treatment); | 46 | resources(path.links()), selector, treatment); |
45 | this.path = path; | 47 | this.path = path; |
48 | + this.resourceRequests = resourceRequests; | ||
46 | } | 49 | } |
47 | 50 | ||
48 | /** | 51 | /** |
... | @@ -51,6 +54,7 @@ public class PathIntent extends ConnectivityIntent { | ... | @@ -51,6 +54,7 @@ public class PathIntent extends ConnectivityIntent { |
51 | protected PathIntent() { | 54 | protected PathIntent() { |
52 | super(); | 55 | super(); |
53 | this.path = null; | 56 | this.path = null; |
57 | + this.resourceRequests = new LinkResourceRequest[0]; | ||
54 | } | 58 | } |
55 | 59 | ||
56 | /** | 60 | /** |
... | @@ -67,6 +71,10 @@ public class PathIntent extends ConnectivityIntent { | ... | @@ -67,6 +71,10 @@ public class PathIntent extends ConnectivityIntent { |
67 | return true; | 71 | return true; |
68 | } | 72 | } |
69 | 73 | ||
74 | + public LinkResourceRequest[] resourceRequests() { | ||
75 | + return resourceRequests; | ||
76 | + } | ||
77 | + | ||
70 | @Override | 78 | @Override |
71 | public String toString() { | 79 | public String toString() { |
72 | return MoreObjects.toStringHelper(getClass()) | 80 | return MoreObjects.toStringHelper(getClass()) | ... | ... |
core/api/src/main/java/org/onlab/onos/net/intent/PointToPointIntentWithBandwidthConstraint.java
0 → 100644
1 | +/* | ||
2 | + * Licensed to the Apache Software Foundation (ASF) under one | ||
3 | + * or more contributor license agreements. See the NOTICE file | ||
4 | + * distributed with this work for additional information | ||
5 | + * regarding copyright ownership. The ASF licenses this file | ||
6 | + * to you under the Apache License, Version 2.0 (the | ||
7 | + * "License"); you may not use this file except in compliance | ||
8 | + * with the License. You may obtain a copy of the License at | ||
9 | + * | ||
10 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + * | ||
12 | + * Unless required by applicable law or agreed to in writing, | ||
13 | + * software distributed under the License is distributed on an | ||
14 | + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
15 | + * KIND, either express or implied. See the License for the | ||
16 | + * specific language governing permissions and limitations | ||
17 | + * under the License. | ||
18 | + */ | ||
19 | +package org.onlab.onos.net.intent; | ||
20 | + | ||
21 | +import org.onlab.onos.core.ApplicationId; | ||
22 | +import org.onlab.onos.net.ConnectPoint; | ||
23 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
24 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
25 | +import org.onlab.onos.net.resource.BandwidthResourceRequest; | ||
26 | + | ||
27 | +import com.google.common.base.MoreObjects; | ||
28 | + | ||
29 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
30 | + | ||
31 | +/** | ||
32 | + * Abstraction of point-to-point connectivity. | ||
33 | + */ | ||
34 | +public class PointToPointIntentWithBandwidthConstraint extends ConnectivityIntent { | ||
35 | + | ||
36 | + private final ConnectPoint ingressPoint; | ||
37 | + private final ConnectPoint egressPoint; | ||
38 | + private final BandwidthResourceRequest bandwidthResourceRequest; | ||
39 | + | ||
40 | + /** | ||
41 | + * Creates a new point-to-point intent with the supplied ingress/egress | ||
42 | + * ports. | ||
43 | + * | ||
44 | + * @param appId application identifier | ||
45 | + * @param selector traffic selector | ||
46 | + * @param treatment treatment | ||
47 | + * @param ingressPoint ingress port | ||
48 | + * @param egressPoint egress port | ||
49 | + * @throws NullPointerException if {@code ingressPoint} or {@code egressPoints} is null. | ||
50 | + */ | ||
51 | + public PointToPointIntentWithBandwidthConstraint(ApplicationId appId, TrafficSelector selector, | ||
52 | + TrafficTreatment treatment, | ||
53 | + ConnectPoint ingressPoint, | ||
54 | + ConnectPoint egressPoint, | ||
55 | + BandwidthResourceRequest bandwidthResourceRequest) { | ||
56 | + super(id(PointToPointIntentWithBandwidthConstraint.class, selector, | ||
57 | + treatment, ingressPoint, egressPoint, bandwidthResourceRequest.bandwidth()), | ||
58 | + appId, null, selector, treatment); | ||
59 | + this.ingressPoint = checkNotNull(ingressPoint); | ||
60 | + this.egressPoint = checkNotNull(egressPoint); | ||
61 | + this.bandwidthResourceRequest = bandwidthResourceRequest; | ||
62 | + } | ||
63 | + | ||
64 | + /** | ||
65 | + * Constructor for serializer. | ||
66 | + */ | ||
67 | + protected PointToPointIntentWithBandwidthConstraint() { | ||
68 | + super(); | ||
69 | + this.ingressPoint = null; | ||
70 | + this.egressPoint = null; | ||
71 | + bandwidthResourceRequest = new BandwidthResourceRequest(0.0); | ||
72 | + } | ||
73 | + | ||
74 | + /** | ||
75 | + * Returns the port on which the ingress traffic should be connected to | ||
76 | + * the egress. | ||
77 | + * | ||
78 | + * @return ingress port | ||
79 | + */ | ||
80 | + public ConnectPoint ingressPoint() { | ||
81 | + return ingressPoint; | ||
82 | + } | ||
83 | + | ||
84 | + /** | ||
85 | + * Returns the port on which the traffic should egress. | ||
86 | + * | ||
87 | + * @return egress port | ||
88 | + */ | ||
89 | + public ConnectPoint egressPoint() { | ||
90 | + return egressPoint; | ||
91 | + } | ||
92 | + | ||
93 | + public BandwidthResourceRequest bandwidthRequest() { | ||
94 | + return this.bandwidthResourceRequest; | ||
95 | + } | ||
96 | + | ||
97 | + @Override | ||
98 | + public String toString() { | ||
99 | + return MoreObjects.toStringHelper(getClass()) | ||
100 | + .add("id", id()) | ||
101 | + .add("appId", appId()) | ||
102 | + .add("selector", selector()) | ||
103 | + .add("treatment", treatment()) | ||
104 | + .add("ingress", ingressPoint) | ||
105 | + .add("egress", egressPoint) | ||
106 | + .add("bandwidth", bandwidthResourceRequest.bandwidth().toString()) | ||
107 | + .toString(); | ||
108 | + } | ||
109 | + | ||
110 | +} |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
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 | +package org.onlab.onos.net.resource; | ||
17 | + | ||
18 | +import java.util.Set; | ||
19 | + | ||
20 | +import org.onlab.onos.net.Link; | ||
21 | +import org.onlab.onos.net.intent.IntentId; | ||
22 | + | ||
23 | + | ||
24 | +/** | ||
25 | + * Manages link resources. | ||
26 | + */ | ||
27 | +public interface LinkResourceStore { | ||
28 | + Set<ResourceAllocation> getFreeResources(Link link); | ||
29 | + | ||
30 | + void allocateResources(LinkResourceAllocations allocations); | ||
31 | + | ||
32 | + void releaseResources(LinkResourceAllocations allocations); | ||
33 | + | ||
34 | + LinkResourceAllocations getAllocations(IntentId intentId); | ||
35 | + | ||
36 | + Iterable<LinkResourceAllocations> getAllocations(Link link); | ||
37 | + | ||
38 | + Iterable<LinkResourceAllocations> getAllocations(); | ||
39 | +} |
... | @@ -23,6 +23,8 @@ import org.onlab.packet.ChassisId; | ... | @@ -23,6 +23,8 @@ import org.onlab.packet.ChassisId; |
23 | import static org.junit.Assert.assertEquals; | 23 | import static org.junit.Assert.assertEquals; |
24 | import static org.onlab.onos.net.Device.Type.SWITCH; | 24 | import static org.onlab.onos.net.Device.Type.SWITCH; |
25 | import static org.onlab.onos.net.DeviceId.deviceId; | 25 | import static org.onlab.onos.net.DeviceId.deviceId; |
26 | +import static org.onlab.onos.net.Port.Type.COPPER; | ||
27 | +import static org.onlab.onos.net.Port.Type.FIBER; | ||
26 | import static org.onlab.onos.net.PortNumber.portNumber; | 28 | import static org.onlab.onos.net.PortNumber.portNumber; |
27 | 29 | ||
28 | /** | 30 | /** |
... | @@ -35,15 +37,16 @@ public class DefaultPortTest { | ... | @@ -35,15 +37,16 @@ public class DefaultPortTest { |
35 | private static final DeviceId DID2 = deviceId("of:bar"); | 37 | private static final DeviceId DID2 = deviceId("of:bar"); |
36 | private static final PortNumber P1 = portNumber(1); | 38 | private static final PortNumber P1 = portNumber(1); |
37 | private static final PortNumber P2 = portNumber(2); | 39 | private static final PortNumber P2 = portNumber(2); |
40 | + private static final long SP1 = 1_000_000; | ||
38 | 41 | ||
39 | @Test | 42 | @Test |
40 | public void testEquality() { | 43 | public void testEquality() { |
41 | Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n", | 44 | Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n", |
42 | new ChassisId()); | 45 | new ChassisId()); |
43 | - Port p1 = new DefaultPort(device, portNumber(1), true); | 46 | + Port p1 = new DefaultPort(device, portNumber(1), true, COPPER, SP1); |
44 | - Port p2 = new DefaultPort(device, portNumber(1), true); | 47 | + Port p2 = new DefaultPort(device, portNumber(1), true, COPPER, SP1); |
45 | - Port p3 = new DefaultPort(device, portNumber(2), true); | 48 | + Port p3 = new DefaultPort(device, portNumber(2), true, FIBER, SP1); |
46 | - Port p4 = new DefaultPort(device, portNumber(2), true); | 49 | + Port p4 = new DefaultPort(device, portNumber(2), true, FIBER, SP1); |
47 | Port p5 = new DefaultPort(device, portNumber(1), false); | 50 | Port p5 = new DefaultPort(device, portNumber(1), false); |
48 | 51 | ||
49 | new EqualsTester().addEqualityGroup(p1, p2) | 52 | new EqualsTester().addEqualityGroup(p1, p2) |
... | @@ -56,10 +59,12 @@ public class DefaultPortTest { | ... | @@ -56,10 +59,12 @@ public class DefaultPortTest { |
56 | public void basics() { | 59 | public void basics() { |
57 | Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n", | 60 | Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n", |
58 | new ChassisId()); | 61 | new ChassisId()); |
59 | - Port port = new DefaultPort(device, portNumber(1), true); | 62 | + Port port = new DefaultPort(device, portNumber(1), true, FIBER, SP1); |
60 | assertEquals("incorrect element", device, port.element()); | 63 | assertEquals("incorrect element", device, port.element()); |
61 | assertEquals("incorrect number", portNumber(1), port.number()); | 64 | assertEquals("incorrect number", portNumber(1), port.number()); |
62 | assertEquals("incorrect state", true, port.isEnabled()); | 65 | assertEquals("incorrect state", true, port.isEnabled()); |
66 | + assertEquals("incorrect speed", SP1, port.portSpeed()); | ||
67 | + assertEquals("incorrect type", FIBER, port.type()); | ||
63 | } | 68 | } |
64 | 69 | ||
65 | } | 70 | } | ... | ... |
... | @@ -15,11 +15,12 @@ | ... | @@ -15,11 +15,12 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent; | 16 | package org.onlab.onos.net.intent; |
17 | 17 | ||
18 | -import static org.junit.Assert.assertEquals; | ||
19 | - | ||
20 | import org.junit.Test; | 18 | import org.junit.Test; |
21 | import org.onlab.onos.net.NetTestTools; | 19 | import org.onlab.onos.net.NetTestTools; |
22 | import org.onlab.onos.net.Path; | 20 | import org.onlab.onos.net.Path; |
21 | +import org.onlab.onos.net.resource.LinkResourceRequest; | ||
22 | + | ||
23 | +import static org.junit.Assert.assertEquals; | ||
23 | 24 | ||
24 | public class PathIntentTest extends ConnectivityIntentTest { | 25 | public class PathIntentTest extends ConnectivityIntentTest { |
25 | // 111:11 --> 222:22 | 26 | // 111:11 --> 222:22 |
... | @@ -39,11 +40,11 @@ public class PathIntentTest extends ConnectivityIntentTest { | ... | @@ -39,11 +40,11 @@ public class PathIntentTest extends ConnectivityIntentTest { |
39 | 40 | ||
40 | @Override | 41 | @Override |
41 | protected PathIntent createOne() { | 42 | protected PathIntent createOne() { |
42 | - return new PathIntent(APPID, MATCH, NOP, PATH1); | 43 | + return new PathIntent(APPID, MATCH, NOP, PATH1, new LinkResourceRequest[0]); |
43 | } | 44 | } |
44 | 45 | ||
45 | @Override | 46 | @Override |
46 | protected PathIntent createAnother() { | 47 | protected PathIntent createAnother() { |
47 | - return new PathIntent(APPID, MATCH, NOP, PATH2); | 48 | + return new PathIntent(APPID, MATCH, NOP, PATH2, new LinkResourceRequest[0]); |
48 | } | 49 | } |
49 | } | 50 | } | ... | ... |
... | @@ -407,9 +407,9 @@ public class DeviceManager | ... | @@ -407,9 +407,9 @@ public class DeviceManager |
407 | // TODO duplicate suppression should probably occur in the MastershipManager | 407 | // TODO duplicate suppression should probably occur in the MastershipManager |
408 | // itself, so listeners that can't deal with duplicates don't have to | 408 | // itself, so listeners that can't deal with duplicates don't have to |
409 | // so this check themselves. | 409 | // so this check themselves. |
410 | - if (checkDuplicate(event.roleInfo(), term.termNumber())) { | 410 | +// if (checkDuplicate(event.roleInfo(), term.termNumber())) { |
411 | - return; | 411 | +// return; |
412 | - } | 412 | +// } |
413 | 413 | ||
414 | if (!myNodeId.equals(term.master())) { | 414 | if (!myNodeId.equals(term.master())) { |
415 | // something went wrong in consistency, let go | 415 | // something went wrong in consistency, let go |
... | @@ -435,7 +435,8 @@ public class DeviceManager | ... | @@ -435,7 +435,8 @@ public class DeviceManager |
435 | return; | 435 | return; |
436 | } | 436 | } |
437 | //flag the device as online. Is there a better way to do this? | 437 | //flag the device as online. Is there a better way to do this? |
438 | - DeviceEvent devEvent = store.createOrUpdateDevice(device.providerId(), did, | 438 | + DeviceEvent devEvent = |
439 | + store.createOrUpdateDevice(device.providerId(), did, | ||
439 | new DefaultDeviceDescription( | 440 | new DefaultDeviceDescription( |
440 | did.uri(), device.type(), device.manufacturer(), | 441 | did.uri(), device.type(), device.manufacturer(), |
441 | device.hwVersion(), device.swVersion(), | 442 | device.hwVersion(), device.swVersion(), | ... | ... |
... | @@ -15,6 +15,10 @@ | ... | @@ -15,6 +15,10 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent.impl; | 16 | package org.onlab.onos.net.intent.impl; |
17 | 17 | ||
18 | +import java.util.Arrays; | ||
19 | +import java.util.List; | ||
20 | +import java.util.Set; | ||
21 | + | ||
18 | import org.apache.felix.scr.annotations.Activate; | 22 | import org.apache.felix.scr.annotations.Activate; |
19 | import org.apache.felix.scr.annotations.Component; | 23 | import org.apache.felix.scr.annotations.Component; |
20 | import org.apache.felix.scr.annotations.Deactivate; | 24 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -32,13 +36,10 @@ import org.onlab.onos.net.intent.IntentCompiler; | ... | @@ -32,13 +36,10 @@ import org.onlab.onos.net.intent.IntentCompiler; |
32 | import org.onlab.onos.net.intent.IntentExtensionService; | 36 | import org.onlab.onos.net.intent.IntentExtensionService; |
33 | import org.onlab.onos.net.intent.PathIntent; | 37 | import org.onlab.onos.net.intent.PathIntent; |
34 | import org.onlab.onos.net.topology.LinkWeight; | 38 | import org.onlab.onos.net.topology.LinkWeight; |
39 | +import org.onlab.onos.net.resource.LinkResourceRequest; | ||
35 | import org.onlab.onos.net.topology.PathService; | 40 | import org.onlab.onos.net.topology.PathService; |
36 | import org.onlab.onos.net.topology.TopologyEdge; | 41 | import org.onlab.onos.net.topology.TopologyEdge; |
37 | 42 | ||
38 | -import java.util.Arrays; | ||
39 | -import java.util.List; | ||
40 | -import java.util.Set; | ||
41 | - | ||
42 | import static org.onlab.onos.net.flow.DefaultTrafficSelector.builder; | 43 | import static org.onlab.onos.net.flow.DefaultTrafficSelector.builder; |
43 | 44 | ||
44 | /** | 45 | /** |
... | @@ -85,7 +86,7 @@ public class HostToHostIntentCompiler | ... | @@ -85,7 +86,7 @@ public class HostToHostIntentCompiler |
85 | TrafficSelector selector = builder(intent.selector()) | 86 | TrafficSelector selector = builder(intent.selector()) |
86 | .matchEthSrc(src.mac()).matchEthDst(dst.mac()).build(); | 87 | .matchEthSrc(src.mac()).matchEthDst(dst.mac()).build(); |
87 | return new PathIntent(intent.appId(), selector, intent.treatment(), | 88 | return new PathIntent(intent.appId(), selector, intent.treatment(), |
88 | - path); | 89 | + path, new LinkResourceRequest[0]); |
89 | } | 90 | } |
90 | 91 | ||
91 | private Path getPath(HostId one, HostId two) { | 92 | private Path getPath(HostId one, HostId two) { | ... | ... |
... | @@ -15,9 +15,6 @@ | ... | @@ -15,9 +15,6 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent.impl; | 16 | package org.onlab.onos.net.intent.impl; |
17 | 17 | ||
18 | -import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; | ||
19 | -import static org.slf4j.LoggerFactory.getLogger; | ||
20 | - | ||
21 | import java.util.Iterator; | 18 | import java.util.Iterator; |
22 | import java.util.List; | 19 | import java.util.List; |
23 | 20 | ||
... | @@ -41,10 +38,15 @@ import org.onlab.onos.net.flow.TrafficTreatment; | ... | @@ -41,10 +38,15 @@ import org.onlab.onos.net.flow.TrafficTreatment; |
41 | import org.onlab.onos.net.intent.IntentExtensionService; | 38 | import org.onlab.onos.net.intent.IntentExtensionService; |
42 | import org.onlab.onos.net.intent.IntentInstaller; | 39 | import org.onlab.onos.net.intent.IntentInstaller; |
43 | import org.onlab.onos.net.intent.PathIntent; | 40 | import org.onlab.onos.net.intent.PathIntent; |
41 | +import org.onlab.onos.net.resource.LinkResourceAllocations; | ||
42 | +import org.onlab.onos.net.resource.LinkResourceService; | ||
44 | import org.slf4j.Logger; | 43 | import org.slf4j.Logger; |
45 | 44 | ||
46 | import com.google.common.collect.Lists; | 45 | import com.google.common.collect.Lists; |
47 | 46 | ||
47 | +import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; | ||
48 | +import static org.slf4j.LoggerFactory.getLogger; | ||
49 | + | ||
48 | /** | 50 | /** |
49 | * Installer for {@link PathIntent packet path connectivity intents}. | 51 | * Installer for {@link PathIntent packet path connectivity intents}. |
50 | */ | 52 | */ |
... | @@ -59,6 +61,9 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { | ... | @@ -59,6 +61,9 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { |
59 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 61 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
60 | protected CoreService coreService; | 62 | protected CoreService coreService; |
61 | 63 | ||
64 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
65 | + protected LinkResourceService resourceService; | ||
66 | + | ||
62 | private ApplicationId appId; | 67 | private ApplicationId appId; |
63 | 68 | ||
64 | @Activate | 69 | @Activate |
... | @@ -74,6 +79,14 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { | ... | @@ -74,6 +79,14 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { |
74 | 79 | ||
75 | @Override | 80 | @Override |
76 | public List<FlowRuleBatchOperation> install(PathIntent intent) { | 81 | public List<FlowRuleBatchOperation> install(PathIntent intent) { |
82 | + if (intent.resourceRequests().length > 0) { | ||
83 | + LinkResourceAllocations allocations = allocateBandwidth(intent); | ||
84 | + if (allocations == null) { | ||
85 | + log.debug("Insufficient bandwidth available to install path intent {}", intent); | ||
86 | + return null; | ||
87 | + } | ||
88 | + } | ||
89 | + | ||
77 | TrafficSelector.Builder builder = | 90 | TrafficSelector.Builder builder = |
78 | DefaultTrafficSelector.builder(intent.selector()); | 91 | DefaultTrafficSelector.builder(intent.selector()); |
79 | Iterator<Link> links = intent.path().links().iterator(); | 92 | Iterator<Link> links = intent.path().links().iterator(); |
... | @@ -117,6 +130,10 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { | ... | @@ -117,6 +130,10 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { |
117 | return Lists.newArrayList(new FlowRuleBatchOperation(rules)); | 130 | return Lists.newArrayList(new FlowRuleBatchOperation(rules)); |
118 | } | 131 | } |
119 | 132 | ||
133 | + private LinkResourceAllocations allocateBandwidth(PathIntent intent) { | ||
134 | + return resourceService.requestResources(intent.resourceRequests()[0]); | ||
135 | + } | ||
136 | + | ||
120 | // TODO refactor below this line... ---------------------------- | 137 | // TODO refactor below this line... ---------------------------- |
121 | 138 | ||
122 | /** | 139 | /** | ... | ... |
... | @@ -15,6 +15,10 @@ | ... | @@ -15,6 +15,10 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent.impl; | 16 | package org.onlab.onos.net.intent.impl; |
17 | 17 | ||
18 | +import java.util.ArrayList; | ||
19 | +import java.util.List; | ||
20 | +import java.util.Set; | ||
21 | + | ||
18 | import org.apache.felix.scr.annotations.Activate; | 22 | import org.apache.felix.scr.annotations.Activate; |
19 | import org.apache.felix.scr.annotations.Component; | 23 | import org.apache.felix.scr.annotations.Component; |
20 | import org.apache.felix.scr.annotations.Deactivate; | 24 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -31,15 +35,12 @@ import org.onlab.onos.net.intent.IntentExtensionService; | ... | @@ -31,15 +35,12 @@ import org.onlab.onos.net.intent.IntentExtensionService; |
31 | import org.onlab.onos.net.intent.PathIntent; | 35 | import org.onlab.onos.net.intent.PathIntent; |
32 | import org.onlab.onos.net.intent.PointToPointIntent; | 36 | import org.onlab.onos.net.intent.PointToPointIntent; |
33 | import org.onlab.onos.net.provider.ProviderId; | 37 | import org.onlab.onos.net.provider.ProviderId; |
38 | +import org.onlab.onos.net.resource.LinkResourceRequest; | ||
34 | import org.onlab.onos.net.topology.LinkWeight; | 39 | import org.onlab.onos.net.topology.LinkWeight; |
35 | import org.onlab.onos.net.topology.Topology; | 40 | import org.onlab.onos.net.topology.Topology; |
36 | import org.onlab.onos.net.topology.TopologyEdge; | 41 | import org.onlab.onos.net.topology.TopologyEdge; |
37 | import org.onlab.onos.net.topology.TopologyService; | 42 | import org.onlab.onos.net.topology.TopologyService; |
38 | 43 | ||
39 | -import java.util.ArrayList; | ||
40 | -import java.util.List; | ||
41 | -import java.util.Set; | ||
42 | - | ||
43 | import static java.util.Arrays.asList; | 44 | import static java.util.Arrays.asList; |
44 | 45 | ||
45 | /** | 46 | /** |
... | @@ -89,7 +90,8 @@ public class PointToPointIntentCompiler | ... | @@ -89,7 +90,8 @@ public class PointToPointIntentCompiler |
89 | private Intent createPathIntent(Path path, | 90 | private Intent createPathIntent(Path path, |
90 | PointToPointIntent intent) { | 91 | PointToPointIntent intent) { |
91 | return new PathIntent(intent.appId(), | 92 | return new PathIntent(intent.appId(), |
92 | - intent.selector(), intent.treatment(), path); | 93 | + intent.selector(), intent.treatment(), path, |
94 | + new LinkResourceRequest[0]); | ||
93 | } | 95 | } |
94 | 96 | ||
95 | /** | 97 | /** | ... | ... |
1 | +package org.onlab.onos.net.intent.impl; | ||
2 | + | ||
3 | +import java.util.ArrayList; | ||
4 | +import java.util.Arrays; | ||
5 | +import java.util.List; | ||
6 | +import java.util.Set; | ||
7 | + | ||
8 | +import org.apache.felix.scr.annotations.Activate; | ||
9 | +import org.apache.felix.scr.annotations.Component; | ||
10 | +import org.apache.felix.scr.annotations.Deactivate; | ||
11 | +import org.apache.felix.scr.annotations.Reference; | ||
12 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
13 | +import org.onlab.onos.net.ConnectPoint; | ||
14 | +import org.onlab.onos.net.DefaultEdgeLink; | ||
15 | +import org.onlab.onos.net.DefaultPath; | ||
16 | +import org.onlab.onos.net.Link; | ||
17 | +import org.onlab.onos.net.Path; | ||
18 | +import org.onlab.onos.net.intent.Intent; | ||
19 | +import org.onlab.onos.net.intent.IntentCompiler; | ||
20 | +import org.onlab.onos.net.intent.IntentExtensionService; | ||
21 | +import org.onlab.onos.net.intent.PathIntent; | ||
22 | +import org.onlab.onos.net.intent.PointToPointIntent; | ||
23 | +import org.onlab.onos.net.intent.PointToPointIntentWithBandwidthConstraint; | ||
24 | +import org.onlab.onos.net.provider.ProviderId; | ||
25 | +import org.onlab.onos.net.resource.BandwidthResourceRequest; | ||
26 | +import org.onlab.onos.net.resource.DefaultLinkResourceRequest; | ||
27 | +import org.onlab.onos.net.resource.LinkResourceRequest; | ||
28 | +import org.onlab.onos.net.resource.LinkResourceService; | ||
29 | +import org.onlab.onos.net.resource.ResourceRequest; | ||
30 | +import org.onlab.onos.net.resource.ResourceType; | ||
31 | +import org.onlab.onos.net.topology.LinkWeight; | ||
32 | +import org.onlab.onos.net.topology.Topology; | ||
33 | +import org.onlab.onos.net.topology.TopologyEdge; | ||
34 | +import org.onlab.onos.net.topology.TopologyService; | ||
35 | + | ||
36 | +/** | ||
37 | + * A intent compiler for {@link org.onlab.onos.net.intent.HostToHostIntent}. | ||
38 | + */ | ||
39 | +@Component(immediate = true) | ||
40 | +public class PointToPointIntentWithBandwidthConstraintCompiler | ||
41 | + implements IntentCompiler<PointToPointIntentWithBandwidthConstraint> { | ||
42 | + | ||
43 | + private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true); | ||
44 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
45 | + protected IntentExtensionService intentManager; | ||
46 | + | ||
47 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
48 | + protected TopologyService topologyService; | ||
49 | + | ||
50 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
51 | + protected LinkResourceService resourceService; | ||
52 | + | ||
53 | + @Activate | ||
54 | + public void activate() { | ||
55 | + intentManager.registerCompiler(PointToPointIntentWithBandwidthConstraint.class, this); | ||
56 | + } | ||
57 | + | ||
58 | + @Deactivate | ||
59 | + public void deactivate() { | ||
60 | + intentManager.unregisterCompiler(PointToPointIntent.class); | ||
61 | + } | ||
62 | + | ||
63 | + @Override | ||
64 | + public List<Intent> compile(PointToPointIntentWithBandwidthConstraint intent) { | ||
65 | + Path path = getPath(intent.ingressPoint(), intent.egressPoint(), intent.bandwidthRequest()); | ||
66 | + | ||
67 | + List<Link> links = new ArrayList<>(); | ||
68 | + links.add(DefaultEdgeLink.createEdgeLink(intent.ingressPoint(), true)); | ||
69 | + links.addAll(path.links()); | ||
70 | + links.add(DefaultEdgeLink.createEdgeLink(intent.egressPoint(), false)); | ||
71 | + | ||
72 | + return Arrays.asList(createPathIntent(new DefaultPath(PID, links, path.cost() + 2, | ||
73 | + path.annotations()), | ||
74 | + intent)); | ||
75 | + } | ||
76 | + | ||
77 | + /** | ||
78 | + * Creates a path intent from the specified path and original | ||
79 | + * connectivity intent. | ||
80 | + * | ||
81 | + * @param path path to create an intent for | ||
82 | + * @param intent original intent | ||
83 | + */ | ||
84 | + private Intent createPathIntent(Path path, | ||
85 | + PointToPointIntentWithBandwidthConstraint intent) { | ||
86 | + LinkResourceRequest.Builder request = DefaultLinkResourceRequest.builder(intent.id(), | ||
87 | + path.links()) | ||
88 | + // TODO - this seems awkward, maybe allow directly attaching a BandwidthRequest | ||
89 | + .addBandwidthRequest(intent.bandwidthRequest().bandwidth().toDouble()); | ||
90 | + LinkResourceRequest bandwidthRequest = request.build(); | ||
91 | + LinkResourceRequest[] bandwidthRequests = {bandwidthRequest}; | ||
92 | + return new PathIntent(intent.appId(), | ||
93 | + intent.selector(), intent.treatment(), path, | ||
94 | + bandwidthRequests); | ||
95 | + } | ||
96 | + | ||
97 | + /** | ||
98 | + * Computes a path between two ConnectPoints. | ||
99 | + * | ||
100 | + * @param one start of the path | ||
101 | + * @param two end of the path | ||
102 | + * @return Path between the two | ||
103 | + * @throws org.onlab.onos.net.intent.impl.PathNotFoundException if a path cannot be found | ||
104 | + */ | ||
105 | + private Path getPath(ConnectPoint one, ConnectPoint two, final BandwidthResourceRequest bandwidthRequest) { | ||
106 | + Topology topology = topologyService.currentTopology(); | ||
107 | + LinkWeight weight = new LinkWeight() { | ||
108 | + @Override | ||
109 | + public double weight(TopologyEdge edge) { | ||
110 | + if (bandwidthRequest != null) { | ||
111 | + double allocatedBandwidth = 0.0; | ||
112 | + Iterable<ResourceRequest> availableResources = resourceService.getAvailableResources(edge.link()); | ||
113 | + for (ResourceRequest availableResource : availableResources) { | ||
114 | + if (availableResource.type() == ResourceType.BANDWIDTH) { | ||
115 | + BandwidthResourceRequest bandwidthRequest = (BandwidthResourceRequest) availableResource; | ||
116 | + allocatedBandwidth += bandwidthRequest.bandwidth().toDouble(); | ||
117 | + } | ||
118 | + } | ||
119 | + | ||
120 | + // TODO this needs to be discovered from switch/ports somehow | ||
121 | + double maxBandwidth = 1000; | ||
122 | + | ||
123 | + double availableBandwidth = maxBandwidth - allocatedBandwidth; | ||
124 | + if (availableBandwidth >= bandwidthRequest.bandwidth().toDouble()) { | ||
125 | + return 1; | ||
126 | + } else { | ||
127 | + return -1; | ||
128 | + } | ||
129 | + } else { | ||
130 | + return 1; | ||
131 | + } | ||
132 | + } | ||
133 | + }; | ||
134 | + | ||
135 | + Set<Path> paths = topologyService.getPaths(topology, | ||
136 | + one.deviceId(), | ||
137 | + two.deviceId(), | ||
138 | + weight); | ||
139 | + | ||
140 | + if (paths.isEmpty()) { | ||
141 | + throw new PathNotFoundException("No packet path from " + one + " to " + two); | ||
142 | + } | ||
143 | + // TODO: let's be more intelligent about this eventually | ||
144 | + return paths.iterator().next(); | ||
145 | + } | ||
146 | +} |
... | @@ -15,9 +15,13 @@ | ... | @@ -15,9 +15,13 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.resource.impl; | 16 | package org.onlab.onos.net.resource.impl; |
17 | 17 | ||
18 | +import static com.google.common.base.Preconditions.checkArgument; | ||
19 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
18 | import static org.slf4j.LoggerFactory.getLogger; | 20 | import static org.slf4j.LoggerFactory.getLogger; |
19 | 21 | ||
22 | +import java.util.Collections; | ||
20 | import java.util.HashMap; | 23 | import java.util.HashMap; |
24 | +import java.util.HashSet; | ||
21 | import java.util.Iterator; | 25 | import java.util.Iterator; |
22 | import java.util.Map; | 26 | import java.util.Map; |
23 | import java.util.Set; | 27 | import java.util.Set; |
... | @@ -25,6 +29,8 @@ import java.util.Set; | ... | @@ -25,6 +29,8 @@ import java.util.Set; |
25 | import org.apache.felix.scr.annotations.Activate; | 29 | import org.apache.felix.scr.annotations.Activate; |
26 | import org.apache.felix.scr.annotations.Component; | 30 | import org.apache.felix.scr.annotations.Component; |
27 | import org.apache.felix.scr.annotations.Deactivate; | 31 | import org.apache.felix.scr.annotations.Deactivate; |
32 | +import org.apache.felix.scr.annotations.Reference; | ||
33 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
28 | import org.apache.felix.scr.annotations.Service; | 34 | import org.apache.felix.scr.annotations.Service; |
29 | import org.onlab.onos.net.Link; | 35 | import org.onlab.onos.net.Link; |
30 | import org.onlab.onos.net.intent.IntentId; | 36 | import org.onlab.onos.net.intent.IntentId; |
... | @@ -32,15 +38,16 @@ import org.onlab.onos.net.resource.BandwidthResourceAllocation; | ... | @@ -32,15 +38,16 @@ import org.onlab.onos.net.resource.BandwidthResourceAllocation; |
32 | import org.onlab.onos.net.resource.BandwidthResourceRequest; | 38 | import org.onlab.onos.net.resource.BandwidthResourceRequest; |
33 | import org.onlab.onos.net.resource.Lambda; | 39 | import org.onlab.onos.net.resource.Lambda; |
34 | import org.onlab.onos.net.resource.LambdaResourceAllocation; | 40 | import org.onlab.onos.net.resource.LambdaResourceAllocation; |
41 | +import org.onlab.onos.net.resource.LambdaResourceRequest; | ||
35 | import org.onlab.onos.net.resource.LinkResourceAllocations; | 42 | import org.onlab.onos.net.resource.LinkResourceAllocations; |
36 | import org.onlab.onos.net.resource.LinkResourceRequest; | 43 | import org.onlab.onos.net.resource.LinkResourceRequest; |
37 | import org.onlab.onos.net.resource.LinkResourceService; | 44 | import org.onlab.onos.net.resource.LinkResourceService; |
45 | +import org.onlab.onos.net.resource.LinkResourceStore; | ||
38 | import org.onlab.onos.net.resource.ResourceAllocation; | 46 | import org.onlab.onos.net.resource.ResourceAllocation; |
39 | import org.onlab.onos.net.resource.ResourceRequest; | 47 | import org.onlab.onos.net.resource.ResourceRequest; |
48 | +import org.onlab.onos.net.resource.ResourceType; | ||
40 | import org.slf4j.Logger; | 49 | import org.slf4j.Logger; |
41 | 50 | ||
42 | -import com.google.common.collect.Sets; | ||
43 | - | ||
44 | /** | 51 | /** |
45 | * Provides basic implementation of link resources allocation. | 52 | * Provides basic implementation of link resources allocation. |
46 | */ | 53 | */ |
... | @@ -50,6 +57,9 @@ public class LinkResourceManager implements LinkResourceService { | ... | @@ -50,6 +57,9 @@ public class LinkResourceManager implements LinkResourceService { |
50 | 57 | ||
51 | private final Logger log = getLogger(getClass()); | 58 | private final Logger log = getLogger(getClass()); |
52 | 59 | ||
60 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
61 | + private LinkResourceStore store; | ||
62 | + | ||
53 | @Activate | 63 | @Activate |
54 | public void activate() { | 64 | public void activate() { |
55 | log.info("Started"); | 65 | log.info("Started"); |
... | @@ -60,27 +70,65 @@ public class LinkResourceManager implements LinkResourceService { | ... | @@ -60,27 +70,65 @@ public class LinkResourceManager implements LinkResourceService { |
60 | log.info("Stopped"); | 70 | log.info("Stopped"); |
61 | } | 71 | } |
62 | 72 | ||
73 | + /** | ||
74 | + * Returns available lambdas on specified link. | ||
75 | + * | ||
76 | + * @param link the link | ||
77 | + * @return available lambdas on specified link | ||
78 | + */ | ||
79 | + private Set<Lambda> getAvailableLambdas(Link link) { | ||
80 | + checkNotNull(link); | ||
81 | + Set<ResourceAllocation> resAllocs = store.getFreeResources(link); | ||
82 | + if (resAllocs == null) { | ||
83 | + return Collections.emptySet(); | ||
84 | + } | ||
85 | + Set<Lambda> lambdas = new HashSet<>(); | ||
86 | + for (ResourceAllocation res : resAllocs) { | ||
87 | + if (res.type() == ResourceType.LAMBDA) { | ||
88 | + lambdas.add(((LambdaResourceAllocation) res).lambda()); | ||
89 | + } | ||
90 | + } | ||
91 | + return lambdas; | ||
92 | + } | ||
93 | + | ||
94 | + /** | ||
95 | + * Returns available lambdas on specified links. | ||
96 | + * | ||
97 | + * @param links the links | ||
98 | + * @return available lambdas on specified links | ||
99 | + */ | ||
63 | private Iterable<Lambda> getAvailableLambdas(Iterable<Link> links) { | 100 | private Iterable<Lambda> getAvailableLambdas(Iterable<Link> links) { |
64 | - return Sets.newHashSet(Lambda.valueOf(7)); | 101 | + checkNotNull(links); |
102 | + Iterator<Link> i = links.iterator(); | ||
103 | + checkArgument(i.hasNext()); | ||
104 | + Set<Lambda> lambdas = new HashSet<>(getAvailableLambdas(i.next())); | ||
105 | + while (i.hasNext()) { | ||
106 | + lambdas.retainAll(getAvailableLambdas(i.next())); | ||
107 | + } | ||
108 | + return lambdas; | ||
65 | } | 109 | } |
66 | 110 | ||
67 | @Override | 111 | @Override |
68 | public LinkResourceAllocations requestResources(LinkResourceRequest req) { | 112 | public LinkResourceAllocations requestResources(LinkResourceRequest req) { |
69 | - // TODO implement it using a resource data store. | 113 | + // TODO Concatenate multiple bandwidth requests. |
114 | + // TODO Support multiple lambda resource requests. | ||
115 | + // TODO Throw appropriate exception. | ||
70 | 116 | ||
71 | - ResourceAllocation alloc = null; | 117 | + Set<ResourceAllocation> allocs = new HashSet<>(); |
72 | for (ResourceRequest r : req.resources()) { | 118 | for (ResourceRequest r : req.resources()) { |
73 | switch (r.type()) { | 119 | switch (r.type()) { |
74 | case BANDWIDTH: | 120 | case BANDWIDTH: |
75 | - log.info("requestResources() always returns requested bandwidth"); | ||
76 | BandwidthResourceRequest br = (BandwidthResourceRequest) r; | 121 | BandwidthResourceRequest br = (BandwidthResourceRequest) r; |
77 | - alloc = new BandwidthResourceAllocation(br.bandwidth()); | 122 | + allocs.add(new BandwidthResourceAllocation(br.bandwidth())); |
78 | break; | 123 | break; |
79 | case LAMBDA: | 124 | case LAMBDA: |
80 | - log.info("requestResources() always returns lambda 7"); | 125 | + Iterator<Lambda> lambdaIterator = |
81 | - Iterator<Lambda> lambdaIterator = getAvailableLambdas(req.links()).iterator(); | 126 | + getAvailableLambdas(req.links()).iterator(); |
82 | if (lambdaIterator.hasNext()) { | 127 | if (lambdaIterator.hasNext()) { |
83 | - alloc = new LambdaResourceAllocation(lambdaIterator.next()); | 128 | + allocs.add(new LambdaResourceAllocation(lambdaIterator.next())); |
129 | + } else { | ||
130 | + log.info("Failed to allocate lambda resource."); | ||
131 | + return null; | ||
84 | } | 132 | } |
85 | break; | 133 | break; |
86 | default: | 134 | default: |
... | @@ -90,50 +138,66 @@ public class LinkResourceManager implements LinkResourceService { | ... | @@ -90,50 +138,66 @@ public class LinkResourceManager implements LinkResourceService { |
90 | 138 | ||
91 | Map<Link, Set<ResourceAllocation>> allocations = new HashMap<>(); | 139 | Map<Link, Set<ResourceAllocation>> allocations = new HashMap<>(); |
92 | for (Link link : req.links()) { | 140 | for (Link link : req.links()) { |
93 | - allocations.put(link, Sets.newHashSet(alloc)); | 141 | + allocations.put(link, allocs); |
94 | } | 142 | } |
95 | - return new DefaultLinkResourceAllocations(req, allocations); | 143 | + LinkResourceAllocations result = |
144 | + new DefaultLinkResourceAllocations(req, allocations); | ||
145 | + store.allocateResources(result); | ||
146 | + return result; | ||
147 | + | ||
96 | } | 148 | } |
97 | 149 | ||
98 | @Override | 150 | @Override |
99 | public void releaseResources(LinkResourceAllocations allocations) { | 151 | public void releaseResources(LinkResourceAllocations allocations) { |
100 | - // TODO Auto-generated method stub | 152 | + store.releaseResources(allocations); |
101 | - | ||
102 | } | 153 | } |
103 | 154 | ||
104 | @Override | 155 | @Override |
105 | public LinkResourceAllocations updateResources(LinkResourceRequest req, | 156 | public LinkResourceAllocations updateResources(LinkResourceRequest req, |
106 | LinkResourceAllocations oldAllocations) { | 157 | LinkResourceAllocations oldAllocations) { |
158 | + // TODO | ||
107 | return null; | 159 | return null; |
108 | } | 160 | } |
109 | 161 | ||
110 | @Override | 162 | @Override |
111 | public Iterable<LinkResourceAllocations> getAllocations() { | 163 | public Iterable<LinkResourceAllocations> getAllocations() { |
112 | - // TODO Auto-generated method stub | 164 | + return store.getAllocations(); |
113 | - return null; | ||
114 | } | 165 | } |
115 | 166 | ||
116 | @Override | 167 | @Override |
117 | public Iterable<LinkResourceAllocations> getAllocations(Link link) { | 168 | public Iterable<LinkResourceAllocations> getAllocations(Link link) { |
118 | - // TODO Auto-generated method stub | 169 | + return store.getAllocations(link); |
119 | - return null; | ||
120 | } | 170 | } |
121 | 171 | ||
122 | @Override | 172 | @Override |
123 | public LinkResourceAllocations getAllocations(IntentId intentId) { | 173 | public LinkResourceAllocations getAllocations(IntentId intentId) { |
124 | - // TODO Auto-generated method stub | 174 | + return store.getAllocations(intentId); |
125 | - return null; | ||
126 | } | 175 | } |
127 | 176 | ||
128 | @Override | 177 | @Override |
129 | public Iterable<ResourceRequest> getAvailableResources(Link link) { | 178 | public Iterable<ResourceRequest> getAvailableResources(Link link) { |
130 | - // TODO Auto-generated method stub | 179 | + Set<ResourceAllocation> freeRes = store.getFreeResources(link); |
131 | - return null; | 180 | + Set<ResourceRequest> result = new HashSet<>(); |
181 | + for (ResourceAllocation alloc : freeRes) { | ||
182 | + switch (alloc.type()) { | ||
183 | + case BANDWIDTH: | ||
184 | + result.add(new BandwidthResourceRequest( | ||
185 | + ((BandwidthResourceAllocation) alloc).bandwidth())); | ||
186 | + break; | ||
187 | + case LAMBDA: | ||
188 | + result.add(new LambdaResourceRequest()); | ||
189 | + break; | ||
190 | + default: | ||
191 | + break; | ||
192 | + } | ||
193 | + } | ||
194 | + return result; | ||
132 | } | 195 | } |
133 | 196 | ||
134 | @Override | 197 | @Override |
135 | public ResourceRequest getAvailableResources(Link link, | 198 | public ResourceRequest getAvailableResources(Link link, |
136 | LinkResourceAllocations allocations) { | 199 | LinkResourceAllocations allocations) { |
200 | + // TODO | ||
137 | return null; | 201 | return null; |
138 | } | 202 | } |
139 | 203 | ... | ... |
... | @@ -543,8 +543,9 @@ public class GossipDeviceStore | ... | @@ -543,8 +543,9 @@ public class GossipDeviceStore |
543 | Port newPort, | 543 | Port newPort, |
544 | Map<PortNumber, Port> ports) { | 544 | Map<PortNumber, Port> ports) { |
545 | if (oldPort.isEnabled() != newPort.isEnabled() || | 545 | if (oldPort.isEnabled() != newPort.isEnabled() || |
546 | + oldPort.type() != newPort.type() || | ||
547 | + oldPort.portSpeed() != newPort.portSpeed() || | ||
546 | !AnnotationsUtil.isEqual(oldPort.annotations(), newPort.annotations())) { | 548 | !AnnotationsUtil.isEqual(oldPort.annotations(), newPort.annotations())) { |
547 | - | ||
548 | ports.put(oldPort.number(), newPort); | 549 | ports.put(oldPort.number(), newPort); |
549 | return new DeviceEvent(PORT_UPDATED, device, newPort); | 550 | return new DeviceEvent(PORT_UPDATED, device, newPort); |
550 | } | 551 | } |
... | @@ -867,7 +868,10 @@ public class GossipDeviceStore | ... | @@ -867,7 +868,10 @@ public class GossipDeviceStore |
867 | } | 868 | } |
868 | } | 869 | } |
869 | 870 | ||
870 | - return new DefaultPort(device, number, isEnabled, annotations); | 871 | + return portDesc == null ? |
872 | + new DefaultPort(device, number, false, annotations) : | ||
873 | + new DefaultPort(device, number, isEnabled, portDesc.value().type(), | ||
874 | + portDesc.value().portSpeed(), annotations); | ||
871 | } | 875 | } |
872 | 876 | ||
873 | /** | 877 | /** | ... | ... |
This diff is collapsed. Click to expand it.
... | @@ -15,6 +15,10 @@ | ... | @@ -15,6 +15,10 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.store.mastership.impl; | 16 | package org.onlab.onos.store.mastership.impl; |
17 | 17 | ||
18 | +import static org.onlab.onos.net.MastershipRole.MASTER; | ||
19 | +import static org.onlab.onos.net.MastershipRole.NONE; | ||
20 | +import static org.onlab.onos.net.MastershipRole.STANDBY; | ||
21 | + | ||
18 | import java.util.Collections; | 22 | import java.util.Collections; |
19 | import java.util.EnumMap; | 23 | import java.util.EnumMap; |
20 | import java.util.LinkedList; | 24 | import java.util.LinkedList; |
... | @@ -59,18 +63,30 @@ final class RoleValue { | ... | @@ -59,18 +63,30 @@ final class RoleValue { |
59 | return value.get(type).contains(nodeId); | 63 | return value.get(type).contains(nodeId); |
60 | } | 64 | } |
61 | 65 | ||
66 | + public MastershipRole getRole(NodeId nodeId) { | ||
67 | + if (contains(MASTER, nodeId)) { | ||
68 | + return MASTER; | ||
69 | + } | ||
70 | + if (contains(STANDBY, nodeId)) { | ||
71 | + return STANDBY; | ||
72 | + } | ||
73 | + return NONE; | ||
74 | + } | ||
75 | + | ||
62 | /** | 76 | /** |
63 | * Associates a node to a certain role. | 77 | * Associates a node to a certain role. |
64 | * | 78 | * |
65 | * @param type the role | 79 | * @param type the role |
66 | * @param nodeId the node ID of the node to associate | 80 | * @param nodeId the node ID of the node to associate |
81 | + * @return true if modified | ||
67 | */ | 82 | */ |
68 | - public void add(MastershipRole type, NodeId nodeId) { | 83 | + public boolean add(MastershipRole type, NodeId nodeId) { |
69 | List<NodeId> nodes = value.get(type); | 84 | List<NodeId> nodes = value.get(type); |
70 | 85 | ||
71 | if (!nodes.contains(nodeId)) { | 86 | if (!nodes.contains(nodeId)) { |
72 | - nodes.add(nodeId); | 87 | + return nodes.add(nodeId); |
73 | } | 88 | } |
89 | + return false; | ||
74 | } | 90 | } |
75 | 91 | ||
76 | /** | 92 | /** |
... | @@ -78,7 +94,7 @@ final class RoleValue { | ... | @@ -78,7 +94,7 @@ final class RoleValue { |
78 | * | 94 | * |
79 | * @param type the role | 95 | * @param type the role |
80 | * @param nodeId the ID of the node to remove | 96 | * @param nodeId the ID of the node to remove |
81 | - * @return | 97 | + * @return true if modified |
82 | */ | 98 | */ |
83 | public boolean remove(MastershipRole type, NodeId nodeId) { | 99 | public boolean remove(MastershipRole type, NodeId nodeId) { |
84 | List<NodeId> nodes = value.get(type); | 100 | List<NodeId> nodes = value.get(type); |
... | @@ -96,10 +112,12 @@ final class RoleValue { | ... | @@ -96,10 +112,12 @@ final class RoleValue { |
96 | * @param nodeId the Node ID of node changing roles | 112 | * @param nodeId the Node ID of node changing roles |
97 | * @param from the old role | 113 | * @param from the old role |
98 | * @param to the new role | 114 | * @param to the new role |
115 | + * @return true if modified | ||
99 | */ | 116 | */ |
100 | - public void reassign(NodeId nodeId, MastershipRole from, MastershipRole to) { | 117 | + public boolean reassign(NodeId nodeId, MastershipRole from, MastershipRole to) { |
101 | - remove(from, nodeId); | 118 | + boolean modified = remove(from, nodeId); |
102 | - add(to, nodeId); | 119 | + modified |= add(to, nodeId); |
120 | + return modified; | ||
103 | } | 121 | } |
104 | 122 | ||
105 | /** | 123 | /** |
... | @@ -109,10 +127,12 @@ final class RoleValue { | ... | @@ -109,10 +127,12 @@ final class RoleValue { |
109 | * @param from the old NodeId to replace | 127 | * @param from the old NodeId to replace |
110 | * @param to the new NodeId | 128 | * @param to the new NodeId |
111 | * @param type the role associated with the old NodeId | 129 | * @param type the role associated with the old NodeId |
130 | + * @return true if modified | ||
112 | */ | 131 | */ |
113 | - public void replace(NodeId from, NodeId to, MastershipRole type) { | 132 | + public boolean replace(NodeId from, NodeId to, MastershipRole type) { |
114 | - remove(type, from); | 133 | + boolean modified = remove(type, from); |
115 | - add(type, to); | 134 | + modified |= add(type, to); |
135 | + return modified; | ||
116 | } | 136 | } |
117 | 137 | ||
118 | /** | 138 | /** | ... | ... |
... | @@ -142,7 +142,7 @@ public class DistributedMastershipStoreTest { | ... | @@ -142,7 +142,7 @@ public class DistributedMastershipStoreTest { |
142 | testStore.setCurrent(CN1); | 142 | testStore.setCurrent(CN1); |
143 | 143 | ||
144 | //if already MASTER, nothing should happen | 144 | //if already MASTER, nothing should happen |
145 | - testStore.put(DID2, N1, true, false, false); | 145 | + testStore.put(DID2, N1, true, false, true); |
146 | assertEquals("wrong role for MASTER:", MASTER, dms.requestRole(DID2)); | 146 | assertEquals("wrong role for MASTER:", MASTER, dms.requestRole(DID2)); |
147 | 147 | ||
148 | //populate maps with DID1, N1 thru NONE case | 148 | //populate maps with DID1, N1 thru NONE case | ... | ... |
... | @@ -22,11 +22,11 @@ import java.util.HashMap; | ... | @@ -22,11 +22,11 @@ import java.util.HashMap; |
22 | import java.util.HashSet; | 22 | import java.util.HashSet; |
23 | import java.util.LinkedList; | 23 | import java.util.LinkedList; |
24 | 24 | ||
25 | -import org.onlab.onos.core.DefaultApplicationId; | ||
26 | import org.onlab.onos.cluster.ControllerNode; | 25 | import org.onlab.onos.cluster.ControllerNode; |
27 | import org.onlab.onos.cluster.DefaultControllerNode; | 26 | import org.onlab.onos.cluster.DefaultControllerNode; |
28 | import org.onlab.onos.cluster.NodeId; | 27 | import org.onlab.onos.cluster.NodeId; |
29 | import org.onlab.onos.cluster.RoleInfo; | 28 | import org.onlab.onos.cluster.RoleInfo; |
29 | +import org.onlab.onos.core.DefaultApplicationId; | ||
30 | import org.onlab.onos.mastership.MastershipTerm; | 30 | import org.onlab.onos.mastership.MastershipTerm; |
31 | import org.onlab.onos.net.ConnectPoint; | 31 | import org.onlab.onos.net.ConnectPoint; |
32 | import org.onlab.onos.net.DefaultAnnotations; | 32 | import org.onlab.onos.net.DefaultAnnotations; |
... | @@ -59,6 +59,9 @@ import org.onlab.onos.net.flow.StoredFlowEntry; | ... | @@ -59,6 +59,9 @@ import org.onlab.onos.net.flow.StoredFlowEntry; |
59 | import org.onlab.onos.net.flow.criteria.Criteria; | 59 | import org.onlab.onos.net.flow.criteria.Criteria; |
60 | import org.onlab.onos.net.flow.criteria.Criterion; | 60 | import org.onlab.onos.net.flow.criteria.Criterion; |
61 | import org.onlab.onos.net.flow.instructions.Instructions; | 61 | import org.onlab.onos.net.flow.instructions.Instructions; |
62 | +import org.onlab.onos.net.flow.instructions.L0ModificationInstruction; | ||
63 | +import org.onlab.onos.net.flow.instructions.L2ModificationInstruction; | ||
64 | +import org.onlab.onos.net.flow.instructions.L3ModificationInstruction; | ||
62 | import org.onlab.onos.net.host.DefaultHostDescription; | 65 | import org.onlab.onos.net.host.DefaultHostDescription; |
63 | import org.onlab.onos.net.host.HostDescription; | 66 | import org.onlab.onos.net.host.HostDescription; |
64 | import org.onlab.onos.net.intent.ConnectivityIntent; | 67 | import org.onlab.onos.net.intent.ConnectivityIntent; |
... | @@ -66,6 +69,7 @@ import org.onlab.onos.net.intent.HostToHostIntent; | ... | @@ -66,6 +69,7 @@ import org.onlab.onos.net.intent.HostToHostIntent; |
66 | import org.onlab.onos.net.intent.Intent; | 69 | import org.onlab.onos.net.intent.Intent; |
67 | import org.onlab.onos.net.intent.IntentId; | 70 | import org.onlab.onos.net.intent.IntentId; |
68 | import org.onlab.onos.net.intent.IntentState; | 71 | import org.onlab.onos.net.intent.IntentState; |
72 | +import org.onlab.onos.net.intent.LinkCollectionIntent; | ||
69 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; | 73 | import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; |
70 | import org.onlab.onos.net.intent.PathIntent; | 74 | import org.onlab.onos.net.intent.PathIntent; |
71 | import org.onlab.onos.net.intent.PointToPointIntent; | 75 | import org.onlab.onos.net.intent.PointToPointIntent; |
... | @@ -115,6 +119,7 @@ public final class KryoNamespaces { | ... | @@ -115,6 +119,7 @@ public final class KryoNamespaces { |
115 | // | 119 | // |
116 | ControllerNode.State.class, | 120 | ControllerNode.State.class, |
117 | Device.Type.class, | 121 | Device.Type.class, |
122 | + Port.Type.class, | ||
118 | ChassisId.class, | 123 | ChassisId.class, |
119 | DefaultAnnotations.class, | 124 | DefaultAnnotations.class, |
120 | DefaultControllerNode.class, | 125 | DefaultControllerNode.class, |
... | @@ -149,6 +154,17 @@ public final class KryoNamespaces { | ... | @@ -149,6 +154,17 @@ public final class KryoNamespaces { |
149 | DefaultTrafficTreatment.class, | 154 | DefaultTrafficTreatment.class, |
150 | Instructions.DropInstruction.class, | 155 | Instructions.DropInstruction.class, |
151 | Instructions.OutputInstruction.class, | 156 | Instructions.OutputInstruction.class, |
157 | + L0ModificationInstruction.class, | ||
158 | + L0ModificationInstruction.L0SubType.class, | ||
159 | + L0ModificationInstruction.ModLambdaInstruction.class, | ||
160 | + L2ModificationInstruction.class, | ||
161 | + L2ModificationInstruction.L2SubType.class, | ||
162 | + L2ModificationInstruction.ModEtherInstruction.class, | ||
163 | + L2ModificationInstruction.ModVlanIdInstruction.class, | ||
164 | + L2ModificationInstruction.ModVlanPcpInstruction.class, | ||
165 | + L3ModificationInstruction.class, | ||
166 | + L3ModificationInstruction.L3SubType.class, | ||
167 | + L3ModificationInstruction.ModIPInstruction.class, | ||
152 | RoleInfo.class, | 168 | RoleInfo.class, |
153 | FlowRuleBatchOperation.class, | 169 | FlowRuleBatchOperation.class, |
154 | CompletedBatchOperation.class, | 170 | CompletedBatchOperation.class, |
... | @@ -163,7 +179,8 @@ public final class KryoNamespaces { | ... | @@ -163,7 +179,8 @@ public final class KryoNamespaces { |
163 | DefaultEdgeLink.class, | 179 | DefaultEdgeLink.class, |
164 | HostToHostIntent.class, | 180 | HostToHostIntent.class, |
165 | PointToPointIntent.class, | 181 | PointToPointIntent.class, |
166 | - MultiPointToSinglePointIntent.class | 182 | + MultiPointToSinglePointIntent.class, |
183 | + LinkCollectionIntent.class | ||
167 | ) | 184 | ) |
168 | .register(DefaultApplicationId.class, new DefaultApplicationIdSerializer()) | 185 | .register(DefaultApplicationId.class, new DefaultApplicationIdSerializer()) |
169 | .register(URI.class, new URISerializer()) | 186 | .register(URI.class, new URISerializer()) | ... | ... |
... | @@ -15,13 +15,10 @@ | ... | @@ -15,13 +15,10 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.store.serializers; | 16 | package org.onlab.onos.store.serializers; |
17 | 17 | ||
18 | -import static org.junit.Assert.assertEquals; | 18 | +import com.google.common.collect.ImmutableList; |
19 | -import static org.onlab.onos.net.DeviceId.deviceId; | 19 | +import com.google.common.collect.ImmutableMap; |
20 | -import static org.onlab.onos.net.PortNumber.portNumber; | 20 | +import com.google.common.collect.ImmutableSet; |
21 | -import static java.util.Arrays.asList; | 21 | +import com.google.common.testing.EqualsTester; |
22 | - | ||
23 | -import java.nio.ByteBuffer; | ||
24 | - | ||
25 | import org.junit.After; | 22 | import org.junit.After; |
26 | import org.junit.Before; | 23 | import org.junit.Before; |
27 | import org.junit.BeforeClass; | 24 | import org.junit.BeforeClass; |
... | @@ -50,10 +47,12 @@ import org.onlab.packet.IpPrefix; | ... | @@ -50,10 +47,12 @@ import org.onlab.packet.IpPrefix; |
50 | import org.onlab.packet.MacAddress; | 47 | import org.onlab.packet.MacAddress; |
51 | import org.onlab.util.KryoNamespace; | 48 | import org.onlab.util.KryoNamespace; |
52 | 49 | ||
53 | -import com.google.common.collect.ImmutableList; | 50 | +import java.nio.ByteBuffer; |
54 | -import com.google.common.collect.ImmutableMap; | 51 | + |
55 | -import com.google.common.collect.ImmutableSet; | 52 | +import static java.util.Arrays.asList; |
56 | -import com.google.common.testing.EqualsTester; | 53 | +import static org.junit.Assert.assertEquals; |
54 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
55 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
57 | 56 | ||
58 | public class KryoSerializerTest { | 57 | public class KryoSerializerTest { |
59 | 58 | ... | ... |
... | @@ -291,8 +291,9 @@ public class SimpleDeviceStore | ... | @@ -291,8 +291,9 @@ public class SimpleDeviceStore |
291 | Port newPort, | 291 | Port newPort, |
292 | Map<PortNumber, Port> ports) { | 292 | Map<PortNumber, Port> ports) { |
293 | if (oldPort.isEnabled() != newPort.isEnabled() || | 293 | if (oldPort.isEnabled() != newPort.isEnabled() || |
294 | + oldPort.type() != newPort.type() || | ||
295 | + oldPort.portSpeed() != newPort.portSpeed() || | ||
294 | !AnnotationsUtil.isEqual(oldPort.annotations(), newPort.annotations())) { | 296 | !AnnotationsUtil.isEqual(oldPort.annotations(), newPort.annotations())) { |
295 | - | ||
296 | ports.put(oldPort.number(), newPort); | 297 | ports.put(oldPort.number(), newPort); |
297 | return new DeviceEvent(PORT_UPDATED, device, newPort); | 298 | return new DeviceEvent(PORT_UPDATED, device, newPort); |
298 | } | 299 | } |
... | @@ -510,7 +511,10 @@ public class SimpleDeviceStore | ... | @@ -510,7 +511,10 @@ public class SimpleDeviceStore |
510 | } | 511 | } |
511 | } | 512 | } |
512 | 513 | ||
513 | - return new DefaultPort(device, number, isEnabled, annotations); | 514 | + return portDesc == null ? |
515 | + new DefaultPort(device, number, false, annotations) : | ||
516 | + new DefaultPort(device, number, isEnabled, portDesc.type(), | ||
517 | + portDesc.portSpeed(), annotations); | ||
514 | } | 518 | } |
515 | 519 | ||
516 | /** | 520 | /** | ... | ... |
core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleLinkResourceStore.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
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 | +package org.onlab.onos.store.trivial.impl; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.*; | ||
19 | +import static org.slf4j.LoggerFactory.getLogger; | ||
20 | + | ||
21 | +import java.util.Collections; | ||
22 | +import java.util.HashMap; | ||
23 | +import java.util.HashSet; | ||
24 | +import java.util.Map; | ||
25 | +import java.util.Set; | ||
26 | + | ||
27 | +import org.apache.felix.scr.annotations.Activate; | ||
28 | +import org.apache.felix.scr.annotations.Component; | ||
29 | +import org.apache.felix.scr.annotations.Deactivate; | ||
30 | +import org.apache.felix.scr.annotations.Service; | ||
31 | +import org.onlab.onos.net.Link; | ||
32 | +import org.onlab.onos.net.intent.IntentId; | ||
33 | +import org.onlab.onos.net.resource.Bandwidth; | ||
34 | +import org.onlab.onos.net.resource.BandwidthResourceAllocation; | ||
35 | +import org.onlab.onos.net.resource.Lambda; | ||
36 | +import org.onlab.onos.net.resource.LambdaResourceAllocation; | ||
37 | +import org.onlab.onos.net.resource.LinkResourceAllocations; | ||
38 | +import org.onlab.onos.net.resource.LinkResourceStore; | ||
39 | +import org.onlab.onos.net.resource.ResourceAllocation; | ||
40 | +import org.onlab.onos.net.resource.ResourceType; | ||
41 | +import org.slf4j.Logger; | ||
42 | + | ||
43 | +/** | ||
44 | + * Manages link resources using trivial in-memory structures implementation. | ||
45 | + */ | ||
46 | +@Component(immediate = true) | ||
47 | +@Service | ||
48 | +public class SimpleLinkResourceStore implements LinkResourceStore { | ||
49 | + private final Logger log = getLogger(getClass()); | ||
50 | + private Map<IntentId, LinkResourceAllocations> linkResourceAllocationsMap; | ||
51 | + private Map<Link, Set<LinkResourceAllocations>> allocatedResources; | ||
52 | + private Map<Link, Set<ResourceAllocation>> freeResources; | ||
53 | + | ||
54 | + @Activate | ||
55 | + public void activate() { | ||
56 | + linkResourceAllocationsMap = new HashMap<>(); | ||
57 | + allocatedResources = new HashMap<>(); | ||
58 | + freeResources = new HashMap<>(); | ||
59 | + | ||
60 | + log.info("Started"); | ||
61 | + } | ||
62 | + | ||
63 | + @Deactivate | ||
64 | + public void deactivate() { | ||
65 | + log.info("Stopped"); | ||
66 | + } | ||
67 | + | ||
68 | + private Set<ResourceAllocation> readOriginalFreeResources(Link link) { | ||
69 | + // TODO read capacity and lambda resources from topology | ||
70 | + Set<ResourceAllocation> allocations = new HashSet<>(); | ||
71 | + for (int i = 1; i <= 100; i++) { | ||
72 | + allocations.add(new LambdaResourceAllocation(Lambda.valueOf(i))); | ||
73 | + } | ||
74 | + allocations.add(new BandwidthResourceAllocation(Bandwidth.valueOf(1000000))); | ||
75 | + return allocations; | ||
76 | + } | ||
77 | + | ||
78 | + private BandwidthResourceAllocation getBandwidth(Set<ResourceAllocation> freeRes) { | ||
79 | + for (ResourceAllocation res : freeRes) { | ||
80 | + if (res.type() == ResourceType.BANDWIDTH) { | ||
81 | + return (BandwidthResourceAllocation) res; | ||
82 | + } | ||
83 | + } | ||
84 | + return new BandwidthResourceAllocation(Bandwidth.valueOf(0)); | ||
85 | + } | ||
86 | + | ||
87 | + private void subtractFreeResources(Link link, LinkResourceAllocations allocations) { | ||
88 | + // TODO Use lock or version for updating freeResources. | ||
89 | + checkNotNull(link); | ||
90 | + Set<ResourceAllocation> freeRes = freeResources.get(link); | ||
91 | + checkNotNull(freeRes); | ||
92 | + freeRes = new HashSet<>(freeRes); | ||
93 | + Set<ResourceAllocation> subRes = allocations.getResourceAllocation(link); | ||
94 | + for (ResourceAllocation res : subRes) { | ||
95 | + switch (res.type()) { | ||
96 | + case BANDWIDTH: | ||
97 | + BandwidthResourceAllocation ba = getBandwidth(freeRes); | ||
98 | + double requestedBandwidth = | ||
99 | + ((BandwidthResourceAllocation) res).bandwidth().toDouble(); | ||
100 | + double newBandwidth = ba.bandwidth().toDouble() - requestedBandwidth; | ||
101 | + checkState(newBandwidth >= 0.0); | ||
102 | + freeRes.remove(ba); | ||
103 | + freeRes.add(new BandwidthResourceAllocation( | ||
104 | + Bandwidth.valueOf(newBandwidth))); | ||
105 | + break; | ||
106 | + case LAMBDA: | ||
107 | + checkState(freeRes.remove(res)); | ||
108 | + break; | ||
109 | + default: | ||
110 | + break; | ||
111 | + } | ||
112 | + } | ||
113 | + freeResources.put(link, freeRes); | ||
114 | + | ||
115 | + } | ||
116 | + | ||
117 | + private void addFreeResources(Link link, LinkResourceAllocations allocations) { | ||
118 | + // TODO Use lock or version for updating freeResources. | ||
119 | + Set<ResourceAllocation> freeRes = freeResources.get(link); | ||
120 | + checkNotNull(freeRes); | ||
121 | + freeRes = new HashSet<>(freeRes); | ||
122 | + Set<ResourceAllocation> addRes = allocations.getResourceAllocation(link); | ||
123 | + for (ResourceAllocation res : addRes) { | ||
124 | + switch (res.type()) { | ||
125 | + case BANDWIDTH: | ||
126 | + BandwidthResourceAllocation ba = getBandwidth(freeRes); | ||
127 | + double requestedBandwidth = | ||
128 | + ((BandwidthResourceAllocation) res).bandwidth().toDouble(); | ||
129 | + double newBandwidth = ba.bandwidth().toDouble() + requestedBandwidth; | ||
130 | + freeRes.remove(ba); | ||
131 | + freeRes.add(new BandwidthResourceAllocation( | ||
132 | + Bandwidth.valueOf(newBandwidth))); | ||
133 | + break; | ||
134 | + case LAMBDA: | ||
135 | + checkState(freeRes.add(res)); | ||
136 | + break; | ||
137 | + default: | ||
138 | + break; | ||
139 | + } | ||
140 | + } | ||
141 | + freeResources.put(link, freeRes); | ||
142 | + } | ||
143 | + | ||
144 | + @Override | ||
145 | + public Set<ResourceAllocation> getFreeResources(Link link) { | ||
146 | + checkNotNull(link); | ||
147 | + Set<ResourceAllocation> freeRes = freeResources.get(link); | ||
148 | + if (freeRes == null) { | ||
149 | + freeRes = readOriginalFreeResources(link); | ||
150 | + } | ||
151 | + | ||
152 | + return freeRes; | ||
153 | + } | ||
154 | + | ||
155 | + @Override | ||
156 | + public void allocateResources(LinkResourceAllocations allocations) { | ||
157 | + checkNotNull(allocations); | ||
158 | + linkResourceAllocationsMap.put(allocations.intendId(), allocations); | ||
159 | + for (Link link : allocations.links()) { | ||
160 | + subtractFreeResources(link, allocations); | ||
161 | + Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link); | ||
162 | + if (linkAllocs == null) { | ||
163 | + linkAllocs = new HashSet<>(); | ||
164 | + } | ||
165 | + linkAllocs.add(allocations); | ||
166 | + allocatedResources.put(link, linkAllocs); | ||
167 | + } | ||
168 | + } | ||
169 | + | ||
170 | + @Override | ||
171 | + public void releaseResources(LinkResourceAllocations allocations) { | ||
172 | + checkNotNull(allocations); | ||
173 | + linkResourceAllocationsMap.remove(allocations); | ||
174 | + for (Link link : allocations.links()) { | ||
175 | + addFreeResources(link, allocations); | ||
176 | + Set<LinkResourceAllocations> linkAllocs = allocatedResources.get(link); | ||
177 | + if (linkAllocs == null) { | ||
178 | + log.error("Missing resource allocation."); | ||
179 | + } else { | ||
180 | + linkAllocs.remove(allocations); | ||
181 | + } | ||
182 | + allocatedResources.put(link, linkAllocs); | ||
183 | + } | ||
184 | + } | ||
185 | + | ||
186 | + @Override | ||
187 | + public LinkResourceAllocations getAllocations(IntentId intentId) { | ||
188 | + checkNotNull(intentId); | ||
189 | + return linkResourceAllocationsMap.get(intentId); | ||
190 | + } | ||
191 | + | ||
192 | + @Override | ||
193 | + public Iterable<LinkResourceAllocations> getAllocations(Link link) { | ||
194 | + checkNotNull(link); | ||
195 | + Set<LinkResourceAllocations> result = allocatedResources.get(link); | ||
196 | + if (result == null) { | ||
197 | + result = Collections.emptySet(); | ||
198 | + } | ||
199 | + return Collections.unmodifiableSet(result); | ||
200 | + } | ||
201 | + | ||
202 | + @Override | ||
203 | + public Iterable<LinkResourceAllocations> getAllocations() { | ||
204 | + return Collections.unmodifiableCollection(linkResourceAllocationsMap.values()); | ||
205 | + } | ||
206 | + | ||
207 | +} |
... | @@ -15,6 +15,22 @@ | ... | @@ -15,6 +15,22 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.provider.lldp.impl; | 16 | package org.onlab.onos.provider.lldp.impl; |
17 | 17 | ||
18 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
19 | +import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||
20 | +import static org.onlab.onos.net.MastershipRole.MASTER; | ||
21 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
22 | +import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; | ||
23 | +import static org.slf4j.LoggerFactory.getLogger; | ||
24 | + | ||
25 | +import java.nio.ByteBuffer; | ||
26 | +import java.util.Collections; | ||
27 | +import java.util.HashMap; | ||
28 | +import java.util.HashSet; | ||
29 | +import java.util.Iterator; | ||
30 | +import java.util.Map; | ||
31 | +import java.util.Set; | ||
32 | +import java.util.concurrent.atomic.AtomicInteger; | ||
33 | + | ||
18 | import org.jboss.netty.util.Timeout; | 34 | import org.jboss.netty.util.Timeout; |
19 | import org.jboss.netty.util.TimerTask; | 35 | import org.jboss.netty.util.TimerTask; |
20 | import org.onlab.onos.mastership.MastershipService; | 36 | import org.onlab.onos.mastership.MastershipService; |
... | @@ -36,22 +52,6 @@ import org.onlab.packet.ONOSLLDP; | ... | @@ -36,22 +52,6 @@ import org.onlab.packet.ONOSLLDP; |
36 | import org.onlab.util.Timer; | 52 | import org.onlab.util.Timer; |
37 | import org.slf4j.Logger; | 53 | import org.slf4j.Logger; |
38 | 54 | ||
39 | -import java.nio.ByteBuffer; | ||
40 | -import java.util.Collections; | ||
41 | -import java.util.HashMap; | ||
42 | -import java.util.HashSet; | ||
43 | -import java.util.Iterator; | ||
44 | -import java.util.Map; | ||
45 | -import java.util.Set; | ||
46 | -import java.util.concurrent.atomic.AtomicInteger; | ||
47 | - | ||
48 | -import static com.google.common.base.Preconditions.checkNotNull; | ||
49 | -import static java.util.concurrent.TimeUnit.MILLISECONDS; | ||
50 | -import static org.onlab.onos.net.MastershipRole.MASTER; | ||
51 | -import static org.onlab.onos.net.PortNumber.portNumber; | ||
52 | -import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; | ||
53 | -import static org.slf4j.LoggerFactory.getLogger; | ||
54 | - | ||
55 | /** | 55 | /** |
56 | * Run discovery process from a physical switch. Ports are initially labeled as | 56 | * Run discovery process from a physical switch. Ports are initially labeled as |
57 | * slow ports. When an LLDP is successfully received, label the remote port as | 57 | * slow ports. When an LLDP is successfully received, label the remote port as |
... | @@ -336,7 +336,7 @@ public class LinkDiscovery implements TimerTask { | ... | @@ -336,7 +336,7 @@ public class LinkDiscovery implements TimerTask { |
336 | private void sendProbes(Long portNumber) { | 336 | private void sendProbes(Long portNumber) { |
337 | // TODO: should have suppression port configuration, not by type | 337 | // TODO: should have suppression port configuration, not by type |
338 | if (device.type() != Device.Type.ROADM) { | 338 | if (device.type() != Device.Type.ROADM) { |
339 | - log.debug("Sending probes out to {}@{}", portNumber, device.id()); | 339 | + log.trace("Sending probes out to {}@{}", portNumber, device.id()); |
340 | OutboundPacket pkt = this.createOutBoundLLDP(portNumber); | 340 | OutboundPacket pkt = this.createOutBoundLLDP(portNumber); |
341 | pktService.emit(pkt); | 341 | pktService.emit(pkt); |
342 | if (useBDDP) { | 342 | if (useBDDP) { | ... | ... |
... | @@ -23,6 +23,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -23,6 +23,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
23 | import org.onlab.onos.net.Device; | 23 | import org.onlab.onos.net.Device; |
24 | import org.onlab.onos.net.DeviceId; | 24 | import org.onlab.onos.net.DeviceId; |
25 | import org.onlab.onos.net.MastershipRole; | 25 | import org.onlab.onos.net.MastershipRole; |
26 | +import org.onlab.onos.net.Port; | ||
26 | import org.onlab.onos.net.PortNumber; | 27 | import org.onlab.onos.net.PortNumber; |
27 | import org.onlab.onos.net.device.DefaultDeviceDescription; | 28 | import org.onlab.onos.net.device.DefaultDeviceDescription; |
28 | import org.onlab.onos.net.device.DefaultPortDescription; | 29 | import org.onlab.onos.net.device.DefaultPortDescription; |
... | @@ -43,14 +44,19 @@ import org.onlab.packet.ChassisId; | ... | @@ -43,14 +44,19 @@ import org.onlab.packet.ChassisId; |
43 | import org.projectfloodlight.openflow.protocol.OFFactory; | 44 | import org.projectfloodlight.openflow.protocol.OFFactory; |
44 | import org.projectfloodlight.openflow.protocol.OFPortConfig; | 45 | import org.projectfloodlight.openflow.protocol.OFPortConfig; |
45 | import org.projectfloodlight.openflow.protocol.OFPortDesc; | 46 | import org.projectfloodlight.openflow.protocol.OFPortDesc; |
47 | +import org.projectfloodlight.openflow.protocol.OFPortFeatures; | ||
46 | import org.projectfloodlight.openflow.protocol.OFPortState; | 48 | import org.projectfloodlight.openflow.protocol.OFPortState; |
47 | import org.projectfloodlight.openflow.protocol.OFPortStatus; | 49 | import org.projectfloodlight.openflow.protocol.OFPortStatus; |
50 | +import org.projectfloodlight.openflow.protocol.OFVersion; | ||
51 | +import org.projectfloodlight.openflow.types.PortSpeed; | ||
48 | import org.slf4j.Logger; | 52 | import org.slf4j.Logger; |
49 | 53 | ||
50 | import java.util.ArrayList; | 54 | import java.util.ArrayList; |
51 | import java.util.List; | 55 | import java.util.List; |
52 | 56 | ||
53 | import static org.onlab.onos.net.DeviceId.deviceId; | 57 | import static org.onlab.onos.net.DeviceId.deviceId; |
58 | +import static org.onlab.onos.net.Port.Type.COPPER; | ||
59 | +import static org.onlab.onos.net.Port.Type.FIBER; | ||
54 | import static org.onlab.onos.openflow.controller.Dpid.dpid; | 60 | import static org.onlab.onos.openflow.controller.Dpid.dpid; |
55 | import static org.onlab.onos.openflow.controller.Dpid.uri; | 61 | import static org.onlab.onos.openflow.controller.Dpid.uri; |
56 | import static org.slf4j.LoggerFactory.getLogger; | 62 | import static org.slf4j.LoggerFactory.getLogger; |
... | @@ -63,6 +69,7 @@ import static org.slf4j.LoggerFactory.getLogger; | ... | @@ -63,6 +69,7 @@ import static org.slf4j.LoggerFactory.getLogger; |
63 | public class OpenFlowDeviceProvider extends AbstractProvider implements DeviceProvider { | 69 | public class OpenFlowDeviceProvider extends AbstractProvider implements DeviceProvider { |
64 | 70 | ||
65 | private static final Logger LOG = getLogger(OpenFlowDeviceProvider.class); | 71 | private static final Logger LOG = getLogger(OpenFlowDeviceProvider.class); |
72 | + private static final long MBPS = 1_000 * 1_000; | ||
66 | 73 | ||
67 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 74 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
68 | protected DeviceProviderRegistry providerRegistry; | 75 | protected DeviceProviderRegistry providerRegistry; |
... | @@ -244,8 +251,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -244,8 +251,7 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
244 | * @param ports the list of ports | 251 | * @param ports the list of ports |
245 | * @return list of portdescriptions | 252 | * @return list of portdescriptions |
246 | */ | 253 | */ |
247 | - private List<PortDescription> buildPortDescriptions( | 254 | + private List<PortDescription> buildPortDescriptions(List<OFPortDesc> ports) { |
248 | - List<OFPortDesc> ports) { | ||
249 | final List<PortDescription> portDescs = new ArrayList<>(ports.size()); | 255 | final List<PortDescription> portDescs = new ArrayList<>(ports.size()); |
250 | for (OFPortDesc port : ports) { | 256 | for (OFPortDesc port : ports) { |
251 | portDescs.add(buildPortDescription(port)); | 257 | portDescs.add(buildPortDescription(port)); |
... | @@ -260,12 +266,25 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -260,12 +266,25 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
260 | * @return portDescription for the port. | 266 | * @return portDescription for the port. |
261 | */ | 267 | */ |
262 | private PortDescription buildPortDescription(OFPortDesc port) { | 268 | private PortDescription buildPortDescription(OFPortDesc port) { |
263 | - final PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); | 269 | + PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); |
264 | - final boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) && | 270 | + boolean enabled = |
271 | + !port.getState().contains(OFPortState.LINK_DOWN) && | ||
265 | !port.getConfig().contains(OFPortConfig.PORT_DOWN); | 272 | !port.getConfig().contains(OFPortConfig.PORT_DOWN); |
266 | - return new DefaultPortDescription(portNo, enabled); | 273 | + Port.Type type = port.getCurr().contains(OFPortFeatures.PF_FIBER) ? FIBER : COPPER; |
274 | + return new DefaultPortDescription(portNo, enabled, type, portSpeed(port)); | ||
267 | } | 275 | } |
268 | 276 | ||
277 | + private long portSpeed(OFPortDesc port) { | ||
278 | + if (port.getVersion() == OFVersion.OF_13) { | ||
279 | + return port.getCurrSpeed() / MBPS; | ||
280 | + } | ||
281 | + | ||
282 | + PortSpeed portSpeed = PortSpeed.SPEED_NONE; | ||
283 | + for (OFPortFeatures feat : port.getCurr()) { | ||
284 | + portSpeed = PortSpeed.max(portSpeed, feat.getPortSpeed()); | ||
285 | + } | ||
286 | + return portSpeed.getSpeedBps() / MBPS; | ||
287 | + } | ||
269 | } | 288 | } |
270 | 289 | ||
271 | } | 290 | } | ... | ... |
... | @@ -6,4 +6,4 @@ | ... | @@ -6,4 +6,4 @@ |
6 | [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 | 6 | [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 |
7 | . $ONOS_ROOT/tools/build/envDefaults | 7 | . $ONOS_ROOT/tools/build/envDefaults |
8 | 8 | ||
9 | -cd $ONOS_ROOT && mvn clean install && cd docs && mvn javadoc:aggregate | 9 | +cd $ONOS_ROOT && mvn clean install "$@" && cd docs && mvn javadoc:aggregate | ... | ... |
... | @@ -34,6 +34,7 @@ alias mci='mvn clean install' | ... | @@ -34,6 +34,7 @@ alias mci='mvn clean install' |
34 | 34 | ||
35 | # Short-hand for ONOS build, package and test. | 35 | # Short-hand for ONOS build, package and test. |
36 | alias ob='onos-build' | 36 | alias ob='onos-build' |
37 | +alias obi='onos-build -Dmaven.test.failure.ignore=true' | ||
37 | alias obs='onos-build-selective' | 38 | alias obs='onos-build-selective' |
38 | alias op='onos-package' | 39 | alias op='onos-package' |
39 | alias ot='onos-test' | 40 | alias ot='onos-test' | ... | ... |
1 | # Local VirtualBox-based single ONOS instance & ONOS mininet box | 1 | # Local VirtualBox-based single ONOS instance & ONOS mininet box |
2 | 2 | ||
3 | -export ONOS_CELL="cbench" | ||
4 | - | ||
5 | export ONOS_NIC=192.168.56.* | 3 | export ONOS_NIC=192.168.56.* |
6 | export OC1="192.168.56.103" | 4 | export OC1="192.168.56.103" |
7 | export OCN="192.168.56.103" | 5 | export OCN="192.168.56.103" | ... | ... |
1 | # Local VirtualBox-based ONOS instances 1,2 & ONOS mininet box | 1 | # Local VirtualBox-based ONOS instances 1,2 & ONOS mininet box |
2 | 2 | ||
3 | -export ONOS_CELL="local" | ||
4 | - | ||
5 | export ONOS_NIC=192.168.56.* | 3 | export ONOS_NIC=192.168.56.* |
6 | export OC1="192.168.56.101" | 4 | export OC1="192.168.56.101" |
7 | export OC2="192.168.56.102" | 5 | export OC2="192.168.56.102" | ... | ... |
1 | # ProxMox-based cell of ONOS instance; no mininet-box | 1 | # ProxMox-based cell of ONOS instance; no mininet-box |
2 | 2 | ||
3 | -export ONOS_CELL="office" | ||
4 | - | ||
5 | export ONOS_NIC="10.1.10.*" | 3 | export ONOS_NIC="10.1.10.*" |
6 | export OC1="10.1.10.223" | 4 | export OC1="10.1.10.223" |
7 | export OCI="${OC1}" | 5 | export OCI="${OC1}" | ... | ... |
1 | # ProxMox-based cell of ONOS instances 1,2 & ONOS mininet box | 1 | # ProxMox-based cell of ONOS instances 1,2 & ONOS mininet box |
2 | 2 | ||
3 | -export ONOS_CELL="prox" | ||
4 | - | ||
5 | export ONOS_NIC="10.1.9.*" | 3 | export ONOS_NIC="10.1.9.*" |
6 | export OC1="10.1.9.94" | 4 | export OC1="10.1.9.94" |
7 | export OC2="10.1.9.82" | 5 | export OC2="10.1.9.82" | ... | ... |
1 | # Local VirtualBox-based single ONOS instance & ONOS mininet box | 1 | # Local VirtualBox-based single ONOS instance & ONOS mininet box |
2 | 2 | ||
3 | -export ONOS_CELL="single" | ||
4 | - | ||
5 | export ONOS_NIC=192.168.56.* | 3 | export ONOS_NIC=192.168.56.* |
6 | export OC1="192.168.56.101" | 4 | export OC1="192.168.56.101" |
7 | export OCN="192.168.56.103" | 5 | export OCN="192.168.56.103" | ... | ... |
1 | # Local VirtualBox-based ONOS instances 1,2,3 & ONOS mininet box | 1 | # Local VirtualBox-based ONOS instances 1,2,3 & ONOS mininet box |
2 | 2 | ||
3 | -export ONOS_CELL="triple" | ||
4 | - | ||
5 | export ONOS_NIC=192.168.56.* | 3 | export ONOS_NIC=192.168.56.* |
6 | export OC1="192.168.56.101" | 4 | export OC1="192.168.56.101" |
7 | export OC2="192.168.56.102" | 5 | export OC2="192.168.56.102" | ... | ... |
... | @@ -3,28 +3,33 @@ | ... | @@ -3,28 +3,33 @@ |
3 | { | 3 | { |
4 | "uri": "of:0000ffffffffff01", "mac": "ffffffffffff01", "type": "ROADM", | 4 | "uri": "of:0000ffffffffff01", "mac": "ffffffffffff01", "type": "ROADM", |
5 | "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "ROADM1", | 5 | "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "ROADM1", |
6 | - "annotations": { "latitude": 37.6, "longitude": 122.3, "optical.regens": 0 } | 6 | + "annotations": { "latitude": 37.6, "longitude": 122.3, "optical.regens": 0 }, |
7 | + "ports": [ { "port": 10, "speed": 100000, "type": "FIBER" }, { "port": 20, "speed": 0, "type": "FIBER" } ] | ||
7 | }, | 8 | }, |
8 | { | 9 | { |
9 | "uri": "of:0000ffffffffff02", "mac": "ffffffffffff02", "type": "ROADM", | 10 | "uri": "of:0000ffffffffff02", "mac": "ffffffffffff02", "type": "ROADM", |
10 | "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "ROADM2", | 11 | "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "ROADM2", |
11 | - "annotations": { "latitude": 37.3, "longitude": 121.9, "optical.regens": 0 } | 12 | + "annotations": { "latitude": 37.3, "longitude": 121.9, "optical.regens": 0 }, |
13 | + "ports": [ { "port": 11, "speed": 100000, "type": "FIBER" }, { "port": 21, "speed": 0, "type": "FIBER" } ] | ||
12 | }, | 14 | }, |
13 | { | 15 | { |
14 | "uri": "of:0000ffffffffff03", "mac": "ffffffffffff03", "type": "ROADM", | 16 | "uri": "of:0000ffffffffff03", "mac": "ffffffffffff03", "type": "ROADM", |
15 | "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "ROADM3", | 17 | "mfr": "Linc", "hw": "OE", "sw": "?", "serial": "?", "name": "ROADM3", |
16 | - "annotations": { "latitude": 33.9, "longitude": 118.4, "optical.regens": 2 } | 18 | + "annotations": { "latitude": 33.9, "longitude": 118.4, "optical.regens": 2 }, |
19 | + "ports": [ { "port": 30, "speed": 0, "type": "FIBER" }, { "port": 31, "speed": 0, "type": "FIBER" } ] | ||
17 | }, | 20 | }, |
18 | 21 | ||
19 | { | 22 | { |
20 | - "uri": "of:0000ffffffff0001", "mac": "ffffffffff0003", "type": "SWITCH", | 23 | + "uri": "of:0000ffffffff0001", "mac": "ffffffffff0001", "type": "SWITCH", |
21 | "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "ROUTER1", | 24 | "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "ROUTER1", |
22 | - "annotations": { "latitude": 37.6, "longitude": 122.3 } | 25 | + "annotations": { "latitude": 37.6, "longitude": 122.3 }, |
26 | + "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ] | ||
23 | }, | 27 | }, |
24 | { | 28 | { |
25 | "uri": "of:0000ffffffff0002", "mac": "ffffffffff0002", "type": "SWITCH", | 29 | "uri": "of:0000ffffffff0002", "mac": "ffffffffff0002", "type": "SWITCH", |
26 | "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "ROUTER2", | 30 | "mfr": "Linc", "hw": "PK", "sw": "?", "serial": "?", "name": "ROUTER2", |
27 | - "annotations": { "latitude": 37.3, "longitude": 121.9 } | 31 | + "annotations": { "latitude": 37.3, "longitude": 121.9 }, |
32 | + "ports": [ { "port": 1, "speed": 10000, "type": "COPPER" }, { "port": 2, "speed": 100000, "type": "FIBER" } ] | ||
28 | } | 33 | } |
29 | ], | 34 | ], |
30 | 35 | ||
... | @@ -36,10 +41,8 @@ | ... | @@ -36,10 +41,8 @@ |
36 | { "src": "of:0000ffffffff0002/2", "dst": "of:0000ffffffffff02/11", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect" } } | 41 | { "src": "of:0000ffffffff0002/2", "dst": "of:0000ffffffffff02/11", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect" } } |
37 | ], | 42 | ], |
38 | 43 | ||
39 | - "Xhosts" : [ | 44 | + "hosts" : [ |
40 | - { "mac": "a0:00:00:00:00:11", "vlan": -1, "location": "of:0000ffffffff0001/11", "ip": "1.2.3.4" }, | 45 | + { "mac": "00:00:00:00:00:01", "vlan": -1, "location": "of:0000ffffffff0001/1", "ip": "10.0.0.1" }, |
41 | - { "mac": "a0:00:00:00:00:12", "vlan": -1, "location": "of:0000ffffffff0001/12", "ip": "1.2.3.5" }, | 46 | + { "mac": "00:00:00:00:00:02", "vlan": -1, "location": "of:0000ffffffff0002/1", "ip": "10.0.0.2" } |
42 | - { "mac": "a0:00:00:00:00:21", "vlan": -1, "location": "of:0000ffffffff0002/11", "ip": "2.2.3.4" }, | ||
43 | - { "mac": "a0:00:00:00:00:22", "vlan": -1, "location": "of:0000ffffffff0002/12", "ip": "2.2.3.5" } | ||
44 | ] | 47 | ] |
45 | } | 48 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
tools/test/topos/oe-nonlinear-10.json
0 → 100644
This diff is collapsed. Click to expand it.
... | @@ -101,20 +101,6 @@ public final class Ip4Prefix { | ... | @@ -101,20 +101,6 @@ public final class Ip4Prefix { |
101 | return this.address.toString() + "/" + this.prefixLen; | 101 | return this.address.toString() + "/" + this.prefixLen; |
102 | } | 102 | } |
103 | 103 | ||
104 | - /** | ||
105 | - * Compares the value of two Ip4Prefix objects. | ||
106 | - * <p/> | ||
107 | - * Note the value of the IPv4 address is compared directly between the | ||
108 | - * objects, and must match exactly for the objects to be considered equal. | ||
109 | - * This may result in objects which represent the same IP prefix being | ||
110 | - * classified as unequal, because the unsignificant bits of the address | ||
111 | - * field don't match (the bits to the right of the prefix length). | ||
112 | - * <p/> | ||
113 | - * TODO Change this behavior so that objects that represent the same prefix | ||
114 | - * are classified as equal according to this equals method. | ||
115 | - * | ||
116 | - * @see Object#equals(Object) | ||
117 | - */ | ||
118 | @Override | 104 | @Override |
119 | public boolean equals(Object other) { | 105 | public boolean equals(Object other) { |
120 | if (other == this) { | 106 | if (other == this) { | ... | ... |
... | @@ -101,20 +101,6 @@ public final class Ip6Prefix { | ... | @@ -101,20 +101,6 @@ public final class Ip6Prefix { |
101 | return this.address.toString() + "/" + this.prefixLen; | 101 | return this.address.toString() + "/" + this.prefixLen; |
102 | } | 102 | } |
103 | 103 | ||
104 | - /** | ||
105 | - * Compares the value of two Ip6Prefix objects. | ||
106 | - * <p/> | ||
107 | - * Note the value of the IPv6 address is compared directly between the | ||
108 | - * objects, and must match exactly for the objects to be considered equal. | ||
109 | - * This may result in objects which represent the same IP prefix being | ||
110 | - * classified as unequal, because the unsignificant bits of the address | ||
111 | - * field don't match (the bits to the right of the prefix length). | ||
112 | - * <p/> | ||
113 | - * TODO Change this behavior so that objects that represent the same prefix | ||
114 | - * are classified as equal according to this equals method. | ||
115 | - * | ||
116 | - * @see Object#equals(Object) | ||
117 | - */ | ||
118 | @Override | 104 | @Override |
119 | public boolean equals(Object other) { | 105 | public boolean equals(Object other) { |
120 | if (other == this) { | 106 | if (other == this) { | ... | ... |
... | @@ -17,6 +17,8 @@ package org.onlab.packet; | ... | @@ -17,6 +17,8 @@ package org.onlab.packet; |
17 | 17 | ||
18 | import java.nio.ByteBuffer; | 18 | import java.nio.ByteBuffer; |
19 | import java.util.Arrays; | 19 | import java.util.Arrays; |
20 | +import java.util.Objects; | ||
21 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
20 | 22 | ||
21 | /** | 23 | /** |
22 | * A class representing an IPv4 address. | 24 | * A class representing an IPv4 address. |
... | @@ -37,35 +39,68 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -37,35 +39,68 @@ public final class IpAddress implements Comparable<IpAddress> { |
37 | /** | 39 | /** |
38 | * Constructor for given IP address version and address octets. | 40 | * Constructor for given IP address version and address octets. |
39 | * | 41 | * |
40 | - * @param ver the IP address version | 42 | + * @param value the IP address value stored in network byte order |
41 | - * @param octets the IP address octets | 43 | + * (i.e., the most significant byte first) |
44 | + * @param value the IP address value | ||
42 | */ | 45 | */ |
43 | - private IpAddress(Version ver, byte[] octets) { | 46 | + private IpAddress(Version version, byte[] value) { |
44 | - this.version = ver; | 47 | + checkNotNull(value); |
45 | - this.octets = Arrays.copyOf(octets, INET_BYTE_LENGTH); | 48 | + |
49 | + this.version = version; | ||
50 | + this.octets = Arrays.copyOf(value, INET_BYTE_LENGTH); | ||
51 | + } | ||
52 | + | ||
53 | + /** | ||
54 | + * Converts an integer into an IPv4 address. | ||
55 | + * | ||
56 | + * @param value an integer representing an IPv4 value | ||
57 | + * @return an IP address | ||
58 | + */ | ||
59 | + public static IpAddress valueOf(int value) { | ||
60 | + byte[] bytes = | ||
61 | + ByteBuffer.allocate(INET_BYTE_LENGTH).putInt(value).array(); | ||
62 | + return new IpAddress(Version.INET, bytes); | ||
46 | } | 63 | } |
47 | 64 | ||
48 | /** | 65 | /** |
49 | * Converts a byte array into an IP address. | 66 | * Converts a byte array into an IP address. |
50 | * | 67 | * |
51 | - * @param address the IP address value stored in network byte order | 68 | + * @param value the IP address value stored in network byte order |
52 | * (i.e., the most significant byte first) | 69 | * (i.e., the most significant byte first) |
53 | * @return an IP address | 70 | * @return an IP address |
54 | */ | 71 | */ |
55 | - public static IpAddress valueOf(byte[] address) { | 72 | + public static IpAddress valueOf(byte[] value) { |
56 | - return new IpAddress(Version.INET, address); | 73 | + return new IpAddress(Version.INET, value); |
57 | } | 74 | } |
58 | 75 | ||
59 | /** | 76 | /** |
60 | - * Converts an integer into an IPv4 address. | 77 | + * Converts a byte array and a given offset from the beginning of the |
78 | + * array into an IP address. | ||
79 | + * <p/> | ||
80 | + * The IP address is stored in network byte order (i.e., the most | ||
81 | + * significant byte first). | ||
61 | * | 82 | * |
62 | - * @param address an integer representing an IPv4 value | 83 | + * @param value the value to use |
84 | + * @param offset the offset in bytes from the beginning of the byte array | ||
63 | * @return an IP address | 85 | * @return an IP address |
64 | */ | 86 | */ |
65 | - public static IpAddress valueOf(int address) { | 87 | + public static IpAddress valueOf(byte[] value, int offset) { |
66 | - byte[] bytes = | 88 | + // Verify the arguments |
67 | - ByteBuffer.allocate(INET_BYTE_LENGTH).putInt(address).array(); | 89 | + if ((offset < 0) || (offset + INET_BYTE_LENGTH > value.length)) { |
68 | - return new IpAddress(Version.INET, bytes); | 90 | + String msg; |
91 | + if (value.length < INET_BYTE_LENGTH) { | ||
92 | + msg = "Invalid IPv4 address array: array length: " + | ||
93 | + value.length + ". Must be at least " + INET_BYTE_LENGTH; | ||
94 | + } else { | ||
95 | + msg = "Invalid IPv4 address array: array offset: " + | ||
96 | + offset + ". Must be in the interval [0, " + | ||
97 | + (value.length - INET_BYTE_LENGTH) + "]"; | ||
98 | + } | ||
99 | + throw new IllegalArgumentException(msg); | ||
100 | + } | ||
101 | + | ||
102 | + byte[] bc = Arrays.copyOfRange(value, offset, value.length); | ||
103 | + return IpAddress.valueOf(bc); | ||
69 | } | 104 | } |
70 | 105 | ||
71 | /** | 106 | /** |
... | @@ -77,8 +112,9 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -77,8 +112,9 @@ public final class IpAddress implements Comparable<IpAddress> { |
77 | public static IpAddress valueOf(String address) { | 112 | public static IpAddress valueOf(String address) { |
78 | final String[] net = address.split("\\."); | 113 | final String[] net = address.split("\\."); |
79 | if (net.length != INET_BYTE_LENGTH) { | 114 | if (net.length != INET_BYTE_LENGTH) { |
80 | - throw new IllegalArgumentException("Malformed IP address string; " | 115 | + String msg = "Malformed IPv4 address string; " + |
81 | - + "Address must have four decimal values separated by dots (.)"); | 116 | + "Address must have four decimal values separated by dots (.)"; |
117 | + throw new IllegalArgumentException(msg); | ||
82 | } | 118 | } |
83 | final byte[] bytes = new byte[INET_BYTE_LENGTH]; | 119 | final byte[] bytes = new byte[INET_BYTE_LENGTH]; |
84 | for (int i = 0; i < INET_BYTE_LENGTH; i++) { | 120 | for (int i = 0; i < INET_BYTE_LENGTH; i++) { |
... | @@ -115,6 +151,48 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -115,6 +151,48 @@ public final class IpAddress implements Comparable<IpAddress> { |
115 | return bb.getInt(); | 151 | return bb.getInt(); |
116 | } | 152 | } |
117 | 153 | ||
154 | + /** | ||
155 | + * Creates an IP network mask prefix. | ||
156 | + * | ||
157 | + * @param prefixLen the length of the mask prefix. Must be in the interval | ||
158 | + * [0, 32] for IPv4 | ||
159 | + * @return a new IP address that contains a mask prefix of the | ||
160 | + * specified length | ||
161 | + */ | ||
162 | + public static IpAddress makeMaskPrefix(int prefixLen) { | ||
163 | + // Verify the prefix length | ||
164 | + if ((prefixLen < 0) || (prefixLen > INET_BIT_LENGTH)) { | ||
165 | + final String msg = "Invalid IPv4 prefix length: " + prefixLen + | ||
166 | + ". Must be in the interval [0, 32]."; | ||
167 | + throw new IllegalArgumentException(msg); | ||
168 | + } | ||
169 | + | ||
170 | + long v = (0xffffffffL << (INET_BIT_LENGTH - prefixLen)) & 0xffffffffL; | ||
171 | + return IpAddress.valueOf((int) v); | ||
172 | + } | ||
173 | + | ||
174 | + /** | ||
175 | + * Creates an IP address by masking it with a network mask of given | ||
176 | + * mask length. | ||
177 | + * | ||
178 | + * @param addr the address to mask | ||
179 | + * @param prefixLen the length of the mask prefix. Must be in the interval | ||
180 | + * [0, 32] for IPv4 | ||
181 | + * @return a new IP address that is masked with a mask prefix of the | ||
182 | + * specified length | ||
183 | + */ | ||
184 | + public static IpAddress makeMaskedAddress(final IpAddress addr, | ||
185 | + int prefixLen) { | ||
186 | + IpAddress mask = IpAddress.makeMaskPrefix(prefixLen); | ||
187 | + byte[] net = new byte[INET_BYTE_LENGTH]; | ||
188 | + | ||
189 | + // Mask each byte | ||
190 | + for (int i = 0; i < INET_BYTE_LENGTH; i++) { | ||
191 | + net[i] = (byte) (addr.octets[i] & mask.octets[i]); | ||
192 | + } | ||
193 | + return IpAddress.valueOf(net); | ||
194 | + } | ||
195 | + | ||
118 | @Override | 196 | @Override |
119 | public int compareTo(IpAddress o) { | 197 | public int compareTo(IpAddress o) { |
120 | Long lv = ((long) this.toInt()) & 0xffffffffL; | 198 | Long lv = ((long) this.toInt()) & 0xffffffffL; |
... | @@ -124,32 +202,20 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -124,32 +202,20 @@ public final class IpAddress implements Comparable<IpAddress> { |
124 | 202 | ||
125 | @Override | 203 | @Override |
126 | public int hashCode() { | 204 | public int hashCode() { |
127 | - final int prime = 31; | 205 | + return Objects.hash(version, Arrays.hashCode(octets)); |
128 | - int result = 1; | ||
129 | - result = prime * result + Arrays.hashCode(octets); | ||
130 | - result = prime * result + ((version == null) ? 0 : version.hashCode()); | ||
131 | - return result; | ||
132 | } | 206 | } |
133 | 207 | ||
134 | @Override | 208 | @Override |
135 | public boolean equals(Object obj) { | 209 | public boolean equals(Object obj) { |
136 | - if (this == obj) { | 210 | + if (obj == this) { |
137 | return true; | 211 | return true; |
138 | } | 212 | } |
139 | - if (obj == null) { | 213 | + if ((obj == null) || (getClass() != obj.getClass())) { |
140 | - return false; | ||
141 | - } | ||
142 | - if (getClass() != obj.getClass()) { | ||
143 | return false; | 214 | return false; |
144 | } | 215 | } |
145 | IpAddress other = (IpAddress) obj; | 216 | IpAddress other = (IpAddress) obj; |
146 | - if (!Arrays.equals(octets, other.octets)) { | 217 | + return (version == other.version) && |
147 | - return false; | 218 | + Arrays.equals(octets, other.octets); |
148 | - } | ||
149 | - if (version != other.version) { | ||
150 | - return false; | ||
151 | - } | ||
152 | - return true; | ||
153 | } | 219 | } |
154 | 220 | ||
155 | @Override | 221 | @Override | ... | ... |
... | @@ -19,17 +19,21 @@ import com.fasterxml.jackson.databind.JsonNode; | ... | @@ -19,17 +19,21 @@ import com.fasterxml.jackson.databind.JsonNode; |
19 | import org.onlab.onos.net.ConnectPoint; | 19 | import org.onlab.onos.net.ConnectPoint; |
20 | import org.onlab.onos.net.DefaultAnnotations; | 20 | import org.onlab.onos.net.DefaultAnnotations; |
21 | import org.onlab.onos.net.Device; | 21 | import org.onlab.onos.net.Device; |
22 | +import org.onlab.onos.net.DeviceId; | ||
22 | import org.onlab.onos.net.Host; | 23 | import org.onlab.onos.net.Host; |
23 | import org.onlab.onos.net.HostId; | 24 | import org.onlab.onos.net.HostId; |
24 | import org.onlab.onos.net.HostLocation; | 25 | import org.onlab.onos.net.HostLocation; |
25 | import org.onlab.onos.net.Link; | 26 | import org.onlab.onos.net.Link; |
26 | import org.onlab.onos.net.MastershipRole; | 27 | import org.onlab.onos.net.MastershipRole; |
28 | +import org.onlab.onos.net.Port; | ||
27 | import org.onlab.onos.net.SparseAnnotations; | 29 | import org.onlab.onos.net.SparseAnnotations; |
28 | import org.onlab.onos.net.device.DefaultDeviceDescription; | 30 | import org.onlab.onos.net.device.DefaultDeviceDescription; |
31 | +import org.onlab.onos.net.device.DefaultPortDescription; | ||
29 | import org.onlab.onos.net.device.DeviceDescription; | 32 | import org.onlab.onos.net.device.DeviceDescription; |
30 | import org.onlab.onos.net.device.DeviceProvider; | 33 | import org.onlab.onos.net.device.DeviceProvider; |
31 | import org.onlab.onos.net.device.DeviceProviderRegistry; | 34 | import org.onlab.onos.net.device.DeviceProviderRegistry; |
32 | import org.onlab.onos.net.device.DeviceProviderService; | 35 | import org.onlab.onos.net.device.DeviceProviderService; |
36 | +import org.onlab.onos.net.device.PortDescription; | ||
33 | import org.onlab.onos.net.host.DefaultHostDescription; | 37 | import org.onlab.onos.net.host.DefaultHostDescription; |
34 | import org.onlab.onos.net.host.HostProvider; | 38 | import org.onlab.onos.net.host.HostProvider; |
35 | import org.onlab.onos.net.host.HostProviderRegistry; | 39 | import org.onlab.onos.net.host.HostProviderRegistry; |
... | @@ -45,7 +49,9 @@ import org.onlab.packet.MacAddress; | ... | @@ -45,7 +49,9 @@ import org.onlab.packet.MacAddress; |
45 | import org.onlab.packet.VlanId; | 49 | import org.onlab.packet.VlanId; |
46 | 50 | ||
47 | import java.net.URI; | 51 | import java.net.URI; |
52 | +import java.util.ArrayList; | ||
48 | import java.util.Iterator; | 53 | import java.util.Iterator; |
54 | +import java.util.List; | ||
49 | 55 | ||
50 | import static com.google.common.base.Preconditions.checkNotNull; | 56 | import static com.google.common.base.Preconditions.checkNotNull; |
51 | import static org.onlab.onos.net.DeviceId.deviceId; | 57 | import static org.onlab.onos.net.DeviceId.deviceId; |
... | @@ -120,7 +126,30 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -120,7 +126,30 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
120 | DeviceDescription desc = | 126 | DeviceDescription desc = |
121 | new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial, | 127 | new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial, |
122 | cid, annotations); | 128 | cid, annotations); |
123 | - dps.deviceConnected(deviceId(uri), desc); | 129 | + DeviceId deviceId = deviceId(uri); |
130 | + dps.deviceConnected(deviceId, desc); | ||
131 | + | ||
132 | + JsonNode ports = node.get("ports"); | ||
133 | + if (ports != null) { | ||
134 | + parsePorts(dps, deviceId, ports); | ||
135 | + } | ||
136 | + } | ||
137 | + | ||
138 | + // Parses the given node with list of device ports. | ||
139 | + private void parsePorts(DeviceProviderService dps, DeviceId deviceId, JsonNode nodes) { | ||
140 | + List<PortDescription> ports = new ArrayList<>(); | ||
141 | + for (JsonNode node : nodes) { | ||
142 | + ports.add(parsePort(node)); | ||
143 | + } | ||
144 | + dps.updatePorts(deviceId, ports); | ||
145 | + } | ||
146 | + | ||
147 | + // Parses the given node with port information. | ||
148 | + private PortDescription parsePort(JsonNode node) { | ||
149 | + Port.Type type = Port.Type.valueOf(node.path("type").asText("COPPER")); | ||
150 | + return new DefaultPortDescription(portNumber(node.path("port").asLong(0)), | ||
151 | + node.path("enabled").asBoolean(true), | ||
152 | + type, node.path("speed").asLong(1_000)); | ||
124 | } | 153 | } |
125 | 154 | ||
126 | // Parses the given JSON and provides links as configured. | 155 | // Parses the given JSON and provides links as configured. | ... | ... |
... | @@ -18,9 +18,12 @@ package org.onlab.onos.gui; | ... | @@ -18,9 +18,12 @@ package org.onlab.onos.gui; |
18 | import com.fasterxml.jackson.databind.ObjectMapper; | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
19 | import com.fasterxml.jackson.databind.node.ArrayNode; | 19 | import com.fasterxml.jackson.databind.node.ArrayNode; |
20 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
21 | +import org.onlab.onos.net.Annotations; | ||
21 | import org.onlab.onos.net.ConnectPoint; | 22 | import org.onlab.onos.net.ConnectPoint; |
22 | import org.onlab.onos.net.Device; | 23 | import org.onlab.onos.net.Device; |
24 | +import org.onlab.onos.net.DeviceId; | ||
23 | import org.onlab.onos.net.Host; | 25 | import org.onlab.onos.net.Host; |
26 | +import org.onlab.onos.net.HostId; | ||
24 | import org.onlab.onos.net.HostLocation; | 27 | import org.onlab.onos.net.HostLocation; |
25 | import org.onlab.onos.net.Link; | 28 | import org.onlab.onos.net.Link; |
26 | import org.onlab.onos.net.device.DeviceService; | 29 | import org.onlab.onos.net.device.DeviceService; |
... | @@ -35,6 +38,7 @@ import org.onlab.packet.MacAddress; | ... | @@ -35,6 +38,7 @@ import org.onlab.packet.MacAddress; |
35 | import org.onlab.rest.BaseResource; | 38 | import org.onlab.rest.BaseResource; |
36 | 39 | ||
37 | import javax.ws.rs.GET; | 40 | import javax.ws.rs.GET; |
41 | +import javax.ws.rs.PathParam; | ||
38 | import javax.ws.rs.Produces; | 42 | import javax.ws.rs.Produces; |
39 | import javax.ws.rs.core.Response; | 43 | import javax.ws.rs.core.Response; |
40 | import java.util.HashMap; | 44 | import java.util.HashMap; |
... | @@ -43,12 +47,17 @@ import java.util.Iterator; | ... | @@ -43,12 +47,17 @@ import java.util.Iterator; |
43 | import java.util.Map; | 47 | import java.util.Map; |
44 | import java.util.Set; | 48 | import java.util.Set; |
45 | 49 | ||
50 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
51 | +import static org.onlab.onos.net.HostId.hostId; | ||
52 | + | ||
46 | /** | 53 | /** |
47 | * Topology viewer resource. | 54 | * Topology viewer resource. |
48 | */ | 55 | */ |
49 | @javax.ws.rs.Path("topology") | 56 | @javax.ws.rs.Path("topology") |
50 | public class TopologyResource extends BaseResource { | 57 | public class TopologyResource extends BaseResource { |
51 | 58 | ||
59 | + private static final String HOST_SEP = "/"; | ||
60 | + | ||
52 | @javax.ws.rs.Path("/graph") | 61 | @javax.ws.rs.Path("/graph") |
53 | @GET | 62 | @GET |
54 | @Produces("application/json") | 63 | @Produces("application/json") |
... | @@ -70,6 +79,66 @@ public class TopologyResource extends BaseResource { | ... | @@ -70,6 +79,66 @@ public class TopologyResource extends BaseResource { |
70 | return Response.ok(rootNode.toString()).build(); | 79 | return Response.ok(rootNode.toString()).build(); |
71 | } | 80 | } |
72 | 81 | ||
82 | + @javax.ws.rs.Path("/graph/{id}") | ||
83 | + @GET | ||
84 | + @Produces("application/json") | ||
85 | + public Response details(@PathParam("id") String id) { | ||
86 | + if (id.contains(HOST_SEP)) { | ||
87 | + return hostDetails(hostId(id)); | ||
88 | + } | ||
89 | + return deviceDetails(deviceId(id)); | ||
90 | + } | ||
91 | + | ||
92 | + // Returns device details response. | ||
93 | + private Response deviceDetails(DeviceId deviceId) { | ||
94 | + DeviceService deviceService = get(DeviceService.class); | ||
95 | + Device device = deviceService.getDevice(deviceId); | ||
96 | + Annotations annot = device.annotations(); | ||
97 | + int portCount = deviceService.getPorts(deviceId).size(); | ||
98 | + ObjectNode r = json(deviceId.toString(), | ||
99 | + device.type().toString().toLowerCase(), | ||
100 | + new Prop("Name", annot.value("name")), | ||
101 | + new Prop("Vendor", device.manufacturer()), | ||
102 | + new Prop("H/W Version", device.hwVersion()), | ||
103 | + new Prop("S/W Version", device.swVersion()), | ||
104 | + new Prop("S/W Version", device.serialNumber()), | ||
105 | + new Separator(), | ||
106 | + new Prop("Latitude", annot.value("latitude")), | ||
107 | + new Prop("Longitude", annot.value("longitude")), | ||
108 | + new Prop("Ports", Integer.toString(portCount))); | ||
109 | + return Response.ok(r.toString()).build(); | ||
110 | + } | ||
111 | + | ||
112 | + // Returns host details response. | ||
113 | + private Response hostDetails(HostId hostId) { | ||
114 | + HostService hostService = get(HostService.class); | ||
115 | + Host host = hostService.getHost(hostId); | ||
116 | + Annotations annot = host.annotations(); | ||
117 | + ObjectNode r = json(hostId.toString(), "host", | ||
118 | + new Prop("MAC", host.mac().toString()), | ||
119 | + new Prop("IP", host.ipAddresses().toString()), | ||
120 | + new Separator(), | ||
121 | + new Prop("Latitude", annot.value("latitude")), | ||
122 | + new Prop("Longitude", annot.value("longitude"))); | ||
123 | + return Response.ok(r.toString()).build(); | ||
124 | + } | ||
125 | + | ||
126 | + // Produces JSON property details. | ||
127 | + private ObjectNode json(String id, String type, Prop... props) { | ||
128 | + ObjectMapper mapper = new ObjectMapper(); | ||
129 | + ObjectNode result = mapper.createObjectNode() | ||
130 | + .put("id", id).put("type", type); | ||
131 | + ObjectNode pnode = mapper.createObjectNode(); | ||
132 | + ArrayNode porder = mapper.createArrayNode(); | ||
133 | + for (Prop p : props) { | ||
134 | + porder.add(p.key); | ||
135 | + pnode.put(p.key, p.value); | ||
136 | + } | ||
137 | + result.set("propOrder", porder); | ||
138 | + result.set("props", pnode); | ||
139 | + return result; | ||
140 | + } | ||
141 | + | ||
73 | // Encodes all infrastructure devices. | 142 | // Encodes all infrastructure devices. |
74 | private ArrayNode getDevices(ObjectMapper mapper, DeviceService deviceService, | 143 | private ArrayNode getDevices(ObjectMapper mapper, DeviceService deviceService, |
75 | TopologyGraph graph) { | 144 | TopologyGraph graph) { |
... | @@ -209,4 +278,20 @@ public class TopologyResource extends BaseResource { | ... | @@ -209,4 +278,20 @@ public class TopologyResource extends BaseResource { |
209 | return cp.elementId().toString(); | 278 | return cp.elementId().toString(); |
210 | } | 279 | } |
211 | 280 | ||
281 | + // Auxiliary key/value carrier. | ||
282 | + private class Prop { | ||
283 | + private final String key; | ||
284 | + private final String value; | ||
285 | + | ||
286 | + protected Prop(String key, String value) { | ||
287 | + this.key = key; | ||
288 | + this.value = value; | ||
289 | + } | ||
290 | + } | ||
291 | + | ||
292 | + private class Separator extends Prop { | ||
293 | + protected Separator() { | ||
294 | + super("-", ""); | ||
295 | + } | ||
296 | + } | ||
212 | } | 297 | } | ... | ... |
web/gui/src/main/webapp/img/roadm.png
0 → 100644
8.83 KB
web/gui/src/main/webapp/img/switch.png
0 → 100644
9.27 KB
... | @@ -39,7 +39,7 @@ | ... | @@ -39,7 +39,7 @@ |
39 | <body> | 39 | <body> |
40 | <div id="frame"> | 40 | <div id="frame"> |
41 | <div id="mast"> | 41 | <div id="mast"> |
42 | - <img id="logo" src="img/onos-logo.png" width="60" height="38"> | 42 | + <img id="logo" src="img/onos-logo.png"> |
43 | <span class="title">Open Network Operating System</span> | 43 | <span class="title">Open Network Operating System</span> |
44 | <span id="displayModes" class="right"> | 44 | <span id="displayModes" class="right"> |
45 | <span id="showAll" class="radio active">All Layers</span> | 45 | <span id="showAll" class="radio active">All Layers</span> | ... | ... |
... | @@ -59,54 +59,72 @@ | ... | @@ -59,54 +59,72 @@ |
59 | "src": "of:0000000000000001", | 59 | "src": "of:0000000000000001", |
60 | "dst": "of:0000000000000002", | 60 | "dst": "of:0000000000000002", |
61 | "type": "optical", | 61 | "type": "optical", |
62 | + "srcPort": 1, | ||
63 | + "dstPort": 2, | ||
62 | "linkWidth": 1.5 | 64 | "linkWidth": 1.5 |
63 | }, | 65 | }, |
64 | { | 66 | { |
65 | "src": "of:0000000000000001", | 67 | "src": "of:0000000000000001", |
66 | "dst": "of:0000000000000003", | 68 | "dst": "of:0000000000000003", |
67 | "type": "optical", | 69 | "type": "optical", |
70 | + "srcPort": 2, | ||
71 | + "dstPort": 5, | ||
68 | "linkWidth": 1.5 | 72 | "linkWidth": 1.5 |
69 | }, | 73 | }, |
70 | { | 74 | { |
71 | "src": "of:0000000000000001", | 75 | "src": "of:0000000000000001", |
72 | "dst": "of:0000000000000004", | 76 | "dst": "of:0000000000000004", |
73 | "type": "optical", | 77 | "type": "optical", |
78 | + "srcPort": 3, | ||
79 | + "dstPort": 2, | ||
74 | "linkWidth": 1.5 | 80 | "linkWidth": 1.5 |
75 | }, | 81 | }, |
76 | { | 82 | { |
77 | "src": "of:0000000000000002", | 83 | "src": "of:0000000000000002", |
78 | "dst": "of:0000000000000003", | 84 | "dst": "of:0000000000000003", |
79 | "type": "optical", | 85 | "type": "optical", |
86 | + "srcPort": 3, | ||
87 | + "dstPort": 4, | ||
80 | "linkWidth": 1.5 | 88 | "linkWidth": 1.5 |
81 | }, | 89 | }, |
82 | { | 90 | { |
83 | "src": "of:0000000000000002", | 91 | "src": "of:0000000000000002", |
84 | "dst": "of:0000000000000004", | 92 | "dst": "of:0000000000000004", |
85 | "type": "optical", | 93 | "type": "optical", |
94 | + "srcPort": 4, | ||
95 | + "dstPort": 1, | ||
86 | "linkWidth": 1.5 | 96 | "linkWidth": 1.5 |
87 | }, | 97 | }, |
88 | { | 98 | { |
89 | "src": "of:0000000000000003", | 99 | "src": "of:0000000000000003", |
90 | "dst": "of:0000000000000004", | 100 | "dst": "of:0000000000000004", |
91 | "type": "optical", | 101 | "type": "optical", |
102 | + "srcPort": 3, | ||
103 | + "dstPort": 3, | ||
92 | "linkWidth": 1.5 | 104 | "linkWidth": 1.5 |
93 | }, | 105 | }, |
94 | { | 106 | { |
95 | "src": "of:0000000000000013", | 107 | "src": "of:0000000000000013", |
96 | "dst": "of:0000000000000003", | 108 | "dst": "of:0000000000000003", |
97 | "type": "direct", | 109 | "type": "direct", |
110 | + "srcPort": 1, | ||
111 | + "dstPort": 7, | ||
98 | "linkWidth": 1.0 | 112 | "linkWidth": 1.0 |
99 | }, | 113 | }, |
100 | { | 114 | { |
101 | "src": "of:0000000000000012", | 115 | "src": "of:0000000000000012", |
102 | "dst": "of:0000000000000002", | 116 | "dst": "of:0000000000000002", |
103 | "type": "direct", | 117 | "type": "direct", |
118 | + "srcPort": 1, | ||
119 | + "dstPort": 9, | ||
104 | "linkWidth": 1.0 | 120 | "linkWidth": 1.0 |
105 | }, | 121 | }, |
106 | { | 122 | { |
107 | "src": "of:0000000000000011", | 123 | "src": "of:0000000000000011", |
108 | "dst": "of:0000000000000001", | 124 | "dst": "of:0000000000000001", |
109 | "type": "direct", | 125 | "type": "direct", |
126 | + "srcPort": 1, | ||
127 | + "dstPort": 6, | ||
110 | "linkWidth": 1.0 | 128 | "linkWidth": 1.0 |
111 | } | 129 | } |
112 | ], | 130 | ], | ... | ... |
1 | { | 1 | { |
2 | "comment": "sample device properties", | 2 | "comment": "sample device properties", |
3 | "id": "of:0000000000000001", | 3 | "id": "of:0000000000000001", |
4 | - "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], | 4 | + "type": "roadm", |
5 | + "propOrder": [ "name", "type", "-", "dpid", "latitude", "longitude", "allowed" ], | ||
5 | "props": { | 6 | "props": { |
6 | "allowed": true, | 7 | "allowed": true, |
7 | "latitude": 37.6, | 8 | "latitude": 37.6, |
8 | "longitude": 122.3, | 9 | "longitude": 122.3, |
9 | "name": "SFO-W10", | 10 | "name": "SFO-W10", |
10 | - "dpid": "00:00:00:00:00:00:00:01", | 11 | + "dpid": "00:00:00:00:00:00:00:01" |
11 | - "type": "Roadm" | ||
12 | } | 12 | } |
13 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "comment": "sample device properties", | 2 | "comment": "sample device properties", |
3 | "id": "of:0000000000000002", | 3 | "id": "of:0000000000000002", |
4 | + "type": "switch", | ||
4 | "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], | 5 | "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], |
5 | "props": { | 6 | "props": { |
6 | "allowed": true, | 7 | "allowed": true, | ... | ... |
1 | { | 1 | { |
2 | "comment": "sample device properties", | 2 | "comment": "sample device properties", |
3 | "id": "of:0000000000000003", | 3 | "id": "of:0000000000000003", |
4 | + "type": "switch", | ||
4 | "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], | 5 | "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], |
5 | "props": { | 6 | "props": { |
6 | "allowed": true, | 7 | "allowed": true, | ... | ... |
1 | { | 1 | { |
2 | "comment": "sample device properties", | 2 | "comment": "sample device properties", |
3 | "id": "of:0000000000000004", | 3 | "id": "of:0000000000000004", |
4 | + "type": "switch", | ||
4 | "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], | 5 | "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ], |
5 | "props": { | 6 | "props": { |
6 | "allowed": true, | 7 | "allowed": true, | ... | ... |
1 | { | 1 | { |
2 | "comment": "sample device properties", | 2 | "comment": "sample device properties", |
3 | "id": "of:0000000000000011", | 3 | "id": "of:0000000000000011", |
4 | + "type": "switch", | ||
4 | "propOrder": [ "name", "type", "dpid", "optLink" ], | 5 | "propOrder": [ "name", "type", "dpid", "optLink" ], |
5 | "props": { | 6 | "props": { |
6 | "name": "SFO-pkt", | 7 | "name": "SFO-pkt", | ... | ... |
1 | { | 1 | { |
2 | "comment": "sample device properties", | 2 | "comment": "sample device properties", |
3 | "id": "of:0000000000000012", | 3 | "id": "of:0000000000000012", |
4 | + "type": "switch", | ||
4 | "propOrder": [ "name", "type", "dpid", "optLink" ], | 5 | "propOrder": [ "name", "type", "dpid", "optLink" ], |
5 | "props": { | 6 | "props": { |
6 | "name": "SJC-pkt", | 7 | "name": "SJC-pkt", | ... | ... |
1 | { | 1 | { |
2 | "comment": "sample device properties", | 2 | "comment": "sample device properties", |
3 | "id": "of:0000000000000013", | 3 | "id": "of:0000000000000013", |
4 | + "type": "switch", | ||
4 | "propOrder": [ "name", "type", "dpid", "optLink" ], | 5 | "propOrder": [ "name", "type", "dpid", "optLink" ], |
5 | "props": { | 6 | "props": { |
6 | "name": "LAX-pkt", | 7 | "name": "LAX-pkt", | ... | ... |
... | @@ -37,9 +37,10 @@ | ... | @@ -37,9 +37,10 @@ |
37 | layering: true, | 37 | layering: true, |
38 | collisionPrevention: true | 38 | collisionPrevention: true |
39 | }, | 39 | }, |
40 | - XjsonUrl: 'rs/topology/graph', | 40 | + jsonUrl: 'rs/topology/graph', |
41 | - jsonUrl: 'json/network.json', | 41 | + jsonPrefix: '', |
42 | - jsonPrefix: 'json/', | 42 | + XjsonUrl: 'json/network.json', |
43 | + XjsonPrefix: 'json/', | ||
43 | iconUrl: { | 44 | iconUrl: { |
44 | device: 'img/device.png', | 45 | device: 'img/device.png', |
45 | host: 'img/host.png', | 46 | host: 'img/host.png', |
... | @@ -238,6 +239,9 @@ | ... | @@ -238,6 +239,9 @@ |
238 | function processKeyEvent() { | 239 | function processKeyEvent() { |
239 | var code = d3.event.keyCode; | 240 | var code = d3.event.keyCode; |
240 | switch (code) { | 241 | switch (code) { |
242 | + case 71: // G | ||
243 | + cycleLayout(); | ||
244 | + break; | ||
241 | case 76: // L | 245 | case 76: // L |
242 | cycleLabels(); | 246 | cycleLabels(); |
243 | break; | 247 | break; |
... | @@ -251,6 +255,11 @@ | ... | @@ -251,6 +255,11 @@ |
251 | 255 | ||
252 | } | 256 | } |
253 | 257 | ||
258 | + function cycleLayout() { | ||
259 | + config.options.layering = !config.options.layering; | ||
260 | + network.force.resume(); | ||
261 | + } | ||
262 | + | ||
254 | function cycleLabels() { | 263 | function cycleLabels() { |
255 | console.log('Cycle Labels - context = ' + contextLabel()); | 264 | console.log('Cycle Labels - context = ' + contextLabel()); |
256 | } | 265 | } |
... | @@ -688,7 +697,8 @@ | ... | @@ -688,7 +697,8 @@ |
688 | } | 697 | } |
689 | 698 | ||
690 | function iconUrl(d) { | 699 | function iconUrl(d) { |
691 | - return config.iconUrl[d.icon]; | 700 | + return 'img/' + d.type + '.png'; |
701 | +// return config.iconUrl[d.icon]; | ||
692 | } | 702 | } |
693 | 703 | ||
694 | function translate(x, y) { | 704 | function translate(x, y) { |
... | @@ -889,9 +899,12 @@ | ... | @@ -889,9 +899,12 @@ |
889 | } | 899 | } |
890 | 900 | ||
891 | function detailUrl(id) { | 901 | function detailUrl(id) { |
902 | + if (config.jsonPrefix) { | ||
892 | var safeId = id.replace(/[^a-z0-9]/gi, '_'); | 903 | var safeId = id.replace(/[^a-z0-9]/gi, '_'); |
893 | return config.jsonPrefix + safeId + '.json'; | 904 | return config.jsonPrefix + safeId + '.json'; |
894 | } | 905 | } |
906 | + return config.jsonUrl + '/' + encodeURIComponent(id); | ||
907 | + } | ||
895 | 908 | ||
896 | function flyinPane(obj) { | 909 | function flyinPane(obj) { |
897 | var pane = d3.select('#flyout'), | 910 | var pane = d3.select('#flyout'), |
... | @@ -924,17 +937,29 @@ | ... | @@ -924,17 +937,29 @@ |
924 | function displayDetails(data, pane) { | 937 | function displayDetails(data, pane) { |
925 | $('#flyout').empty(); | 938 | $('#flyout').empty(); |
926 | 939 | ||
927 | - pane.append('h2').text(data.id); | 940 | + var title = pane.append("h2"), |
928 | - | 941 | + table = pane.append("table"), |
929 | - var table = pane.append("table"), | ||
930 | tbody = table.append("tbody"); | 942 | tbody = table.append("tbody"); |
931 | 943 | ||
944 | + $('<img src="img/' + data.type + '.png">').appendTo(title); | ||
945 | + $('<span>').attr('class', 'icon').text(data.id).appendTo(title); | ||
946 | + | ||
947 | + | ||
932 | // TODO: consider using d3 data bind to TR/TD | 948 | // TODO: consider using d3 data bind to TR/TD |
933 | 949 | ||
934 | data.propOrder.forEach(function(p) { | 950 | data.propOrder.forEach(function(p) { |
951 | + if (p === '-') { | ||
952 | + addSep(tbody); | ||
953 | + } else { | ||
935 | addProp(tbody, p, data.props[p]); | 954 | addProp(tbody, p, data.props[p]); |
955 | + } | ||
936 | }); | 956 | }); |
937 | 957 | ||
958 | + function addSep(tbody) { | ||
959 | + var tr = tbody.append('tr'); | ||
960 | + $('<hr>').appendTo(tr.append('td').attr('colspan', 2)); | ||
961 | + } | ||
962 | + | ||
938 | function addProp(tbody, label, value) { | 963 | function addProp(tbody, label, value) { |
939 | var tr = tbody.append('tr'); | 964 | var tr = tbody.append('tr'); |
940 | 965 | ... | ... |
... | @@ -28,11 +28,17 @@ body, html { | ... | @@ -28,11 +28,17 @@ body, html { |
28 | * Classes | 28 | * Classes |
29 | */ | 29 | */ |
30 | 30 | ||
31 | +img#logo { | ||
32 | + height: 38px; | ||
33 | + padding-left: 8px; | ||
34 | + padding-right: 8px; | ||
35 | +} | ||
36 | + | ||
31 | span.title { | 37 | span.title { |
32 | - color: #37b; | 38 | + color: #369; |
33 | font-size: 14pt; | 39 | font-size: 14pt; |
34 | font-style: italic; | 40 | font-style: italic; |
35 | - vertical-align: 10px; | 41 | + vertical-align: 12px; |
36 | } | 42 | } |
37 | 43 | ||
38 | span.radio { | 44 | span.radio { |
... | @@ -41,6 +47,8 @@ span.radio { | ... | @@ -41,6 +47,8 @@ span.radio { |
41 | } | 47 | } |
42 | 48 | ||
43 | span.right { | 49 | span.right { |
50 | + padding-top: 8px; | ||
51 | + padding-right: 16px; | ||
44 | float: right; | 52 | float: right; |
45 | } | 53 | } |
46 | 54 | ||
... | @@ -89,14 +97,13 @@ svg .link { | ... | @@ -89,14 +97,13 @@ svg .link { |
89 | } | 97 | } |
90 | 98 | ||
91 | svg .link.host { | 99 | svg .link.host { |
92 | - stroke: #6a6; | 100 | + stroke: #666; |
93 | - stroke-dasharray: 3,3; | 101 | + stroke-width: 1px; |
102 | + Xstroke-dasharray: 3,3; | ||
94 | } | 103 | } |
95 | 104 | ||
96 | svg .node.device rect { | 105 | svg .node.device rect { |
97 | - stroke-width: 3.0px; | 106 | + stroke-width: 1.5px; |
98 | - stroke: white; | ||
99 | - stroke-dasharray: 2,2; | ||
100 | 107 | ||
101 | transition: opacity 250ms; | 108 | transition: opacity 250ms; |
102 | -webkit-transition: opacity 250ms; | 109 | -webkit-transition: opacity 250ms; |
... | @@ -104,19 +111,21 @@ svg .node.device rect { | ... | @@ -104,19 +111,21 @@ svg .node.device rect { |
104 | } | 111 | } |
105 | 112 | ||
106 | svg .node.device.fixed rect { | 113 | svg .node.device.fixed rect { |
107 | - stroke-width: 0; | 114 | + stroke-width: 1.5; |
115 | + stroke: #ccc; | ||
116 | + Xstroke-dasharray: 4,2; | ||
108 | } | 117 | } |
109 | 118 | ||
110 | svg .node.device.roadm rect { | 119 | svg .node.device.roadm rect { |
111 | - fill: #229; | 120 | + fill: #03c; |
112 | } | 121 | } |
113 | 122 | ||
114 | svg .node.device.switch rect { | 123 | svg .node.device.switch rect { |
115 | - fill: #55f; | 124 | + fill: #06f; |
116 | } | 125 | } |
117 | 126 | ||
118 | svg .node.host circle { | 127 | svg .node.host circle { |
119 | - fill: #898; | 128 | + fill: #c96; |
120 | stroke: #000; | 129 | stroke: #000; |
121 | } | 130 | } |
122 | 131 | ||
... | @@ -148,7 +157,7 @@ svg .node.inactive rect, | ... | @@ -148,7 +157,7 @@ svg .node.inactive rect, |
148 | svg .node.inactive circle, | 157 | svg .node.inactive circle, |
149 | svg .node.inactive text, | 158 | svg .node.inactive text, |
150 | svg .node.inactive image { | 159 | svg .node.inactive image { |
151 | - opacity: .05; | 160 | + opacity: .1; |
152 | } | 161 | } |
153 | 162 | ||
154 | svg .node.inactive.selected rect, | 163 | svg .node.inactive.selected rect, |
... | @@ -199,8 +208,9 @@ body { | ... | @@ -199,8 +208,9 @@ body { |
199 | #mast { | 208 | #mast { |
200 | height: 36px; | 209 | height: 36px; |
201 | padding: 4px; | 210 | padding: 4px; |
202 | - background-color: #ccc; | 211 | + background-color: #bbb; |
203 | vertical-align: baseline; | 212 | vertical-align: baseline; |
213 | + box-shadow: 0px 2px 8px #777; | ||
204 | } | 214 | } |
205 | 215 | ||
206 | #frame { | 216 | #frame { |
... | @@ -214,19 +224,27 @@ body { | ... | @@ -214,19 +224,27 @@ body { |
214 | z-index: 100; | 224 | z-index: 100; |
215 | display: block; | 225 | display: block; |
216 | top: 10%; | 226 | top: 10%; |
217 | - width: 300px; | 227 | + width: 280px; |
218 | - height: 80%; | 228 | + right: -300px; |
219 | - right: -320px; | ||
220 | opacity: 0; | 229 | opacity: 0; |
221 | - background-color: rgba(0,0,0,0.5); | 230 | + background-color: rgba(255,255,255,0.5); |
231 | + | ||
222 | padding: 10px; | 232 | padding: 10px; |
223 | - color: white; | 233 | + color: black; |
224 | font-size: 10pt; | 234 | font-size: 10pt; |
235 | + box-shadow: 2px 2px 16px #777; | ||
225 | } | 236 | } |
226 | 237 | ||
227 | #flyout h2 { | 238 | #flyout h2 { |
228 | margin: 8px 4px; | 239 | margin: 8px 4px; |
229 | - color: yellow; | 240 | + color: black; |
241 | + vertical-align: middle; | ||
242 | +} | ||
243 | + | ||
244 | +#flyout h2 img { | ||
245 | + height: 32px; | ||
246 | + padding-right: 8px; | ||
247 | + vertical-align: middle; | ||
230 | } | 248 | } |
231 | 249 | ||
232 | #flyout p, table { | 250 | #flyout p, table { |
... | @@ -235,7 +253,7 @@ body { | ... | @@ -235,7 +253,7 @@ body { |
235 | 253 | ||
236 | #flyout td.label { | 254 | #flyout td.label { |
237 | font-style: italic; | 255 | font-style: italic; |
238 | - color: #ccf; | 256 | + color: #777; |
239 | padding-right: 12px; | 257 | padding-right: 12px; |
240 | } | 258 | } |
241 | 259 | ||
... | @@ -243,3 +261,10 @@ body { | ... | @@ -243,3 +261,10 @@ body { |
243 | 261 | ||
244 | } | 262 | } |
245 | 263 | ||
264 | +#flyout hr { | ||
265 | + height: 1px; | ||
266 | + color: #ccc; | ||
267 | + background-color: #ccc; | ||
268 | + border: 0; | ||
269 | +} | ||
270 | + | ... | ... |
-
Please register or login to post a comment