Ayaka Koshibe

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Conflicts:
	core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoPoolUtil.java

Change-Id: I6a8fc884f0c0b6578762d7b439177378e838735f
Showing 75 changed files with 1429 additions and 1073 deletions
...@@ -16,4 +16,11 @@ ...@@ -16,4 +16,11 @@
16 16
17 <description>ONOS simple reactive forwarding app</description> 17 <description>ONOS simple reactive forwarding app</description>
18 18
19 + <dependencies>
20 + <dependency>
21 + <groupId>org.osgi</groupId>
22 + <artifactId>org.osgi.compendium</artifactId>
23 + </dependency>
24 + </dependencies>
25 +
19 </project> 26 </project>
......
1 package org.onlab.onos.fwd; 1 package org.onlab.onos.fwd;
2 2
3 -import static org.slf4j.LoggerFactory.getLogger;
4 -
5 -import java.util.Set;
6 -
7 import org.apache.felix.scr.annotations.Activate; 3 import org.apache.felix.scr.annotations.Activate;
8 import org.apache.felix.scr.annotations.Component; 4 import org.apache.felix.scr.annotations.Component;
9 import org.apache.felix.scr.annotations.Deactivate; 5 import org.apache.felix.scr.annotations.Deactivate;
6 +import org.apache.felix.scr.annotations.Modified;
7 +import org.apache.felix.scr.annotations.Property;
10 import org.apache.felix.scr.annotations.Reference; 8 import org.apache.felix.scr.annotations.Reference;
11 import org.apache.felix.scr.annotations.ReferenceCardinality; 9 import org.apache.felix.scr.annotations.ReferenceCardinality;
12 import org.onlab.onos.ApplicationId; 10 import org.onlab.onos.ApplicationId;
...@@ -29,8 +27,14 @@ import org.onlab.onos.net.packet.PacketProcessor; ...@@ -29,8 +27,14 @@ import org.onlab.onos.net.packet.PacketProcessor;
29 import org.onlab.onos.net.packet.PacketService; 27 import org.onlab.onos.net.packet.PacketService;
30 import org.onlab.onos.net.topology.TopologyService; 28 import org.onlab.onos.net.topology.TopologyService;
31 import org.onlab.packet.Ethernet; 29 import org.onlab.packet.Ethernet;
30 +import org.osgi.service.component.ComponentContext;
32 import org.slf4j.Logger; 31 import org.slf4j.Logger;
33 32
33 +import java.util.Dictionary;
34 +import java.util.Set;
35 +
36 +import static org.slf4j.LoggerFactory.getLogger;
37 +
34 /** 38 /**
35 * Sample reactive forwarding application. 39 * Sample reactive forwarding application.
36 */ 40 */
...@@ -61,6 +65,10 @@ public class ReactiveForwarding { ...@@ -61,6 +65,10 @@ public class ReactiveForwarding {
61 65
62 private ApplicationId appId; 66 private ApplicationId appId;
63 67
68 + @Property(name = "enabled", boolValue = true,
69 + label = "Enable forwarding; default is true")
70 + private boolean isEnabled = true;
71 +
64 @Activate 72 @Activate
65 public void activate() { 73 public void activate() {
66 appId = coreService.registerApplication("org.onlab.onos.fwd"); 74 appId = coreService.registerApplication("org.onlab.onos.fwd");
...@@ -76,6 +84,22 @@ public class ReactiveForwarding { ...@@ -76,6 +84,22 @@ public class ReactiveForwarding {
76 log.info("Stopped"); 84 log.info("Stopped");
77 } 85 }
78 86
87 + @Modified
88 + public void modified(ComponentContext context) {
89 + Dictionary properties = context.getProperties();
90 + String flag = (String) properties.get("enabled");
91 + if (flag != null) {
92 + boolean enabled = flag.equals("true");
93 + if (isEnabled != enabled) {
94 + isEnabled = enabled;
95 + if (!isEnabled) {
96 + flowRuleService.removeFlowRulesById(appId);
97 + }
98 + log.info("Reconfigured. Forwarding is {}",
99 + isEnabled ? "enabled" : "disabled");
100 + }
101 + }
102 + }
79 103
80 /** 104 /**
81 * Packet processor responsible for forwarding packets along their paths. 105 * Packet processor responsible for forwarding packets along their paths.
...@@ -86,7 +110,7 @@ public class ReactiveForwarding { ...@@ -86,7 +110,7 @@ public class ReactiveForwarding {
86 public void process(PacketContext context) { 110 public void process(PacketContext context) {
87 // Stop processing if the packet has been handled, since we 111 // Stop processing if the packet has been handled, since we
88 // can't do any more to it. 112 // can't do any more to it.
89 - if (context.isHandled()) { 113 + if (!isEnabled || context.isHandled()) {
90 return; 114 return;
91 } 115 }
92 116
...@@ -185,7 +209,6 @@ public class ReactiveForwarding { ...@@ -185,7 +209,6 @@ public class ReactiveForwarding {
185 builder.build(), treat.build(), PRIORITY, appId, TIMEOUT); 209 builder.build(), treat.build(), PRIORITY, appId, TIMEOUT);
186 210
187 flowRuleService.applyFlowRules(f); 211 flowRuleService.applyFlowRules(f);
188 -
189 } 212 }
190 213
191 } 214 }
......
...@@ -36,6 +36,12 @@ ...@@ -36,6 +36,12 @@
36 <groupId>com.google.guava</groupId> 36 <groupId>com.google.guava</groupId>
37 <artifactId>guava</artifactId> 37 <artifactId>guava</artifactId>
38 </dependency> 38 </dependency>
39 +
40 + <dependency>
41 + <groupId>org.onlab.onos</groupId>
42 + <artifactId>onlab-thirdparty</artifactId>
43 + </dependency>
44 +
39 </dependencies> 45 </dependencies>
40 46
41 </project> 47 </project>
......
...@@ -126,8 +126,8 @@ public class PeerConnectivity { ...@@ -126,8 +126,8 @@ public class PeerConnectivity {
126 TrafficSelector selector = DefaultTrafficSelector.builder() 126 TrafficSelector selector = DefaultTrafficSelector.builder()
127 .matchEthType(Ethernet.TYPE_IPV4) 127 .matchEthType(Ethernet.TYPE_IPV4)
128 .matchIPProtocol(IPv4.PROTOCOL_TCP) 128 .matchIPProtocol(IPv4.PROTOCOL_TCP)
129 - .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH)) 129 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
130 - .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH)) 130 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
131 .matchTcpDst(BGP_PORT) 131 .matchTcpDst(BGP_PORT)
132 .build(); 132 .build();
133 133
...@@ -147,8 +147,8 @@ public class PeerConnectivity { ...@@ -147,8 +147,8 @@ public class PeerConnectivity {
147 selector = DefaultTrafficSelector.builder() 147 selector = DefaultTrafficSelector.builder()
148 .matchEthType(Ethernet.TYPE_IPV4) 148 .matchEthType(Ethernet.TYPE_IPV4)
149 .matchIPProtocol(IPv4.PROTOCOL_TCP) 149 .matchIPProtocol(IPv4.PROTOCOL_TCP)
150 - .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH)) 150 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
151 - .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH)) 151 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
152 .matchTcpSrc(BGP_PORT) 152 .matchTcpSrc(BGP_PORT)
153 .build(); 153 .build();
154 154
...@@ -165,8 +165,8 @@ public class PeerConnectivity { ...@@ -165,8 +165,8 @@ public class PeerConnectivity {
165 selector = DefaultTrafficSelector.builder() 165 selector = DefaultTrafficSelector.builder()
166 .matchEthType(Ethernet.TYPE_IPV4) 166 .matchEthType(Ethernet.TYPE_IPV4)
167 .matchIPProtocol(IPv4.PROTOCOL_TCP) 167 .matchIPProtocol(IPv4.PROTOCOL_TCP)
168 - .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH)) 168 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
169 - .matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH)) 169 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
170 .matchTcpDst(BGP_PORT) 170 .matchTcpDst(BGP_PORT)
171 .build(); 171 .build();
172 172
...@@ -183,8 +183,8 @@ public class PeerConnectivity { ...@@ -183,8 +183,8 @@ public class PeerConnectivity {
183 selector = DefaultTrafficSelector.builder() 183 selector = DefaultTrafficSelector.builder()
184 .matchEthType(Ethernet.TYPE_IPV4) 184 .matchEthType(Ethernet.TYPE_IPV4)
185 .matchIPProtocol(IPv4.PROTOCOL_TCP) 185 .matchIPProtocol(IPv4.PROTOCOL_TCP)
186 - .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH)) 186 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
187 - .matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH)) 187 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
188 .matchTcpSrc(BGP_PORT) 188 .matchTcpSrc(BGP_PORT)
189 .build(); 189 .build();
190 190
...@@ -251,8 +251,8 @@ public class PeerConnectivity { ...@@ -251,8 +251,8 @@ public class PeerConnectivity {
251 TrafficSelector selector = DefaultTrafficSelector.builder() 251 TrafficSelector selector = DefaultTrafficSelector.builder()
252 .matchEthType(Ethernet.TYPE_IPV4) 252 .matchEthType(Ethernet.TYPE_IPV4)
253 .matchIPProtocol(IPv4.PROTOCOL_ICMP) 253 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
254 - .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH)) 254 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
255 - .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH)) 255 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
256 .build(); 256 .build();
257 257
258 TrafficTreatment treatment = DefaultTrafficTreatment.builder() 258 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
...@@ -269,8 +269,8 @@ public class PeerConnectivity { ...@@ -269,8 +269,8 @@ public class PeerConnectivity {
269 selector = DefaultTrafficSelector.builder() 269 selector = DefaultTrafficSelector.builder()
270 .matchEthType(Ethernet.TYPE_IPV4) 270 .matchEthType(Ethernet.TYPE_IPV4)
271 .matchIPProtocol(IPv4.PROTOCOL_ICMP) 271 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
272 - .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH)) 272 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH))
273 - .matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH)) 273 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH))
274 .build(); 274 .build();
275 275
276 PointToPointIntent reversedIntent = new PointToPointIntent( 276 PointToPointIntent reversedIntent = new PointToPointIntent(
......
1 +package org.onlab.onos.sdnip;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +
5 +import java.util.Objects;
6 +
7 +import org.onlab.packet.IpAddress;
8 +import org.onlab.packet.IpPrefix;
9 +
10 +import com.google.common.base.MoreObjects;
11 +
12 +/**
13 + * Represents a route entry for an IP prefix.
14 + */
15 +public class RouteEntry {
16 + private final IpPrefix prefix; // The IP prefix
17 + private final IpAddress nextHop; // Next-hop IP address
18 +
19 + /**
20 + * Class constructor.
21 + *
22 + * @param prefix the IP prefix of the route
23 + * @param nextHop the next hop IP address for the route
24 + */
25 + public RouteEntry(IpPrefix prefix, IpAddress nextHop) {
26 + this.prefix = checkNotNull(prefix);
27 + this.nextHop = checkNotNull(nextHop);
28 + }
29 +
30 + /**
31 + * Returns the IP prefix of the route.
32 + *
33 + * @return the IP prefix of the route
34 + */
35 + public IpPrefix prefix() {
36 + return prefix;
37 + }
38 +
39 + /**
40 + * Returns the next hop IP address for the route.
41 + *
42 + * @return the next hop IP address for the route
43 + */
44 + public IpAddress nextHop() {
45 + return nextHop;
46 + }
47 +
48 + /**
49 + * Creates the binary string representation of an IPv4 prefix.
50 + * The string length is equal to the prefix length.
51 + *
52 + * @param ip4Prefix the IPv4 prefix to use
53 + * @return the binary string representation
54 + */
55 + static String createBinaryString(IpPrefix ip4Prefix) {
56 + if (ip4Prefix.prefixLength() == 0) {
57 + return "";
58 + }
59 +
60 + StringBuilder result = new StringBuilder(ip4Prefix.prefixLength());
61 + long value = ip4Prefix.toInt();
62 + for (int i = 0; i < ip4Prefix.prefixLength(); i++) {
63 + long mask = 1 << (IpAddress.MAX_INET_MASK - 1 - i);
64 + result.append(((value & mask) == 0) ? "0" : "1");
65 + }
66 + return result.toString();
67 + }
68 +
69 + @Override
70 + public boolean equals(Object other) {
71 + if (this == other) {
72 + return true;
73 + }
74 +
75 + //
76 + // NOTE: Subclasses are considered as change of identity, hence
77 + // equals() will return false if the class type doesn't match.
78 + //
79 + if (other == null || getClass() != other.getClass()) {
80 + return false;
81 + }
82 +
83 + RouteEntry otherRoute = (RouteEntry) other;
84 + return Objects.equals(this.prefix, otherRoute.prefix) &&
85 + Objects.equals(this.nextHop, otherRoute.nextHop);
86 + }
87 +
88 + @Override
89 + public int hashCode() {
90 + return Objects.hash(prefix, nextHop);
91 + }
92 +
93 + @Override
94 + public String toString() {
95 + return MoreObjects.toStringHelper(getClass())
96 + .add("prefix", prefix)
97 + .add("nextHop", nextHop)
98 + .toString();
99 + }
100 +}
1 +package org.onlab.onos.sdnip;
2 +
3 +/**
4 + * An interface to receive route updates from route providers.
5 + */
6 +public interface RouteListener {
7 + /**
8 + * Receives a route update from a route provider.
9 + *
10 + * @param routeUpdate the updated route information
11 + */
12 + public void update(RouteUpdate routeUpdate);
13 +}
1 +package org.onlab.onos.sdnip;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +
5 +import java.util.Objects;
6 +
7 +import com.google.common.base.MoreObjects;
8 +
9 +/**
10 + * Represents a change in routing information.
11 + */
12 +public class RouteUpdate {
13 + private final Type type; // The route update type
14 + private final RouteEntry routeEntry; // The updated route entry
15 +
16 + /**
17 + * Specifies the type of a route update.
18 + * <p/>
19 + * Route updates can either provide updated information for a route, or
20 + * withdraw a previously updated route.
21 + */
22 + public enum Type {
23 + /**
24 + * The update contains updated route information for a route.
25 + */
26 + UPDATE,
27 + /**
28 + * The update withdraws the route, meaning any previous information is
29 + * no longer valid.
30 + */
31 + DELETE
32 + }
33 +
34 + /**
35 + * Class constructor.
36 + *
37 + * @param type the type of the route update
38 + * @param routeEntry the route entry with the update
39 + */
40 + public RouteUpdate(Type type, RouteEntry routeEntry) {
41 + this.type = type;
42 + this.routeEntry = checkNotNull(routeEntry);
43 + }
44 +
45 + /**
46 + * Returns the type of the route update.
47 + *
48 + * @return the type of the update
49 + */
50 + public Type type() {
51 + return type;
52 + }
53 +
54 + /**
55 + * Returns the route entry the route update is for.
56 + *
57 + * @return the route entry the route update is for
58 + */
59 + public RouteEntry routeEntry() {
60 + return routeEntry;
61 + }
62 +
63 + @Override
64 + public boolean equals(Object other) {
65 + if (other == this) {
66 + return true;
67 + }
68 +
69 + if (!(other instanceof RouteUpdate)) {
70 + return false;
71 + }
72 +
73 + RouteUpdate otherUpdate = (RouteUpdate) other;
74 +
75 + return Objects.equals(this.type, otherUpdate.type) &&
76 + Objects.equals(this.routeEntry, otherUpdate.routeEntry);
77 + }
78 +
79 + @Override
80 + public int hashCode() {
81 + return Objects.hash(type, routeEntry);
82 + }
83 +
84 + @Override
85 + public String toString() {
86 + return MoreObjects.toStringHelper(getClass())
87 + .add("type", type)
88 + .add("routeEntry", routeEntry)
89 + .toString();
90 + }
91 +}
This diff is collapsed. Click to expand it.
...@@ -9,7 +9,11 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -9,7 +9,11 @@ import org.apache.felix.scr.annotations.Reference;
9 import org.apache.felix.scr.annotations.ReferenceCardinality; 9 import org.apache.felix.scr.annotations.ReferenceCardinality;
10 import org.onlab.onos.net.host.HostService; 10 import org.onlab.onos.net.host.HostService;
11 import org.onlab.onos.net.intent.IntentService; 11 import org.onlab.onos.net.intent.IntentService;
12 +import org.onlab.onos.sdnip.RouteUpdate.Type;
13 +import org.onlab.onos.sdnip.bgp.BgpSessionManager;
12 import org.onlab.onos.sdnip.config.SdnIpConfigReader; 14 import org.onlab.onos.sdnip.config.SdnIpConfigReader;
15 +import org.onlab.packet.IpAddress;
16 +import org.onlab.packet.IpPrefix;
13 import org.slf4j.Logger; 17 import org.slf4j.Logger;
14 18
15 /** 19 /**
...@@ -28,6 +32,8 @@ public class SdnIp { ...@@ -28,6 +32,8 @@ public class SdnIp {
28 32
29 private SdnIpConfigReader config; 33 private SdnIpConfigReader config;
30 private PeerConnectivity peerConnectivity; 34 private PeerConnectivity peerConnectivity;
35 + private Router router;
36 + private BgpSessionManager bgpSessionManager;
31 37
32 @Activate 38 @Activate
33 protected void activate() { 39 protected void activate() {
...@@ -41,6 +47,17 @@ public class SdnIp { ...@@ -41,6 +47,17 @@ public class SdnIp {
41 peerConnectivity = new PeerConnectivity(config, interfaceService, intentService); 47 peerConnectivity = new PeerConnectivity(config, interfaceService, intentService);
42 peerConnectivity.start(); 48 peerConnectivity.start();
43 49
50 + router = new Router(intentService, hostService, config, interfaceService);
51 + router.start();
52 +
53 + bgpSessionManager = new BgpSessionManager(router);
54 + bgpSessionManager.startUp(2000); // TODO
55 +
56 + // TODO need to disable link discovery on external ports
57 +
58 + router.update(new RouteUpdate(Type.UPDATE, new RouteEntry(
59 + IpPrefix.valueOf("172.16.20.0/24"),
60 + IpAddress.valueOf("192.168.10.1"))));
44 } 61 }
45 62
46 @Deactivate 63 @Deactivate
......
1 +package org.onlab.onos.sdnip.bgp;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.jboss.netty.buffer.ChannelBuffers;
5 +import org.jboss.netty.channel.Channel;
6 +import org.jboss.netty.channel.ChannelHandlerContext;
7 +import org.jboss.netty.handler.codec.frame.FrameDecoder;
8 +import org.onlab.onos.sdnip.bgp.BgpConstants.Notifications.MessageHeaderError;
9 +import org.slf4j.Logger;
10 +import org.slf4j.LoggerFactory;
11 +
12 +/**
13 + * Class for handling the decoding of the BGP messages.
14 + */
15 +class BgpFrameDecoder extends FrameDecoder {
16 + private static final Logger log =
17 + LoggerFactory.getLogger(BgpFrameDecoder.class);
18 +
19 + private final BgpSession bgpSession;
20 +
21 + /**
22 + * Constructor for a given BGP Session.
23 + *
24 + * @param bgpSession the BGP session state to use.
25 + */
26 + BgpFrameDecoder(BgpSession bgpSession) {
27 + this.bgpSession = bgpSession;
28 + }
29 +
30 + @Override
31 + protected Object decode(ChannelHandlerContext ctx,
32 + Channel channel,
33 + ChannelBuffer buf) throws Exception {
34 + //
35 + // NOTE: If we close the channel during the decoding, we might still
36 + // see some incoming messages while the channel closing is completed.
37 + //
38 + if (bgpSession.isClosed()) {
39 + return null;
40 + }
41 +
42 + log.trace("BGP Peer: decode(): remoteAddr = {} localAddr = {} " +
43 + "messageSize = {}",
44 + ctx.getChannel().getRemoteAddress(),
45 + ctx.getChannel().getLocalAddress(),
46 + buf.readableBytes());
47 +
48 + // Test for minimum length of the BGP message
49 + if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
50 + // No enough data received
51 + return null;
52 + }
53 +
54 + //
55 + // Mark the current buffer position in case we haven't received
56 + // the whole message.
57 + //
58 + buf.markReaderIndex();
59 +
60 + //
61 + // Read and check the BGP message Marker field: it must be all ones
62 + // (See RFC 4271, Section 4.1)
63 + //
64 + byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
65 + buf.readBytes(marker);
66 + for (int i = 0; i < marker.length; i++) {
67 + if (marker[i] != (byte) 0xff) {
68 + log.debug("BGP RX Error: invalid marker {} at position {}",
69 + marker[i], i);
70 + //
71 + // ERROR: Connection Not Synchronized
72 + //
73 + // Send NOTIFICATION and close the connection
74 + int errorCode = MessageHeaderError.ERROR_CODE;
75 + int errorSubcode =
76 + MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED;
77 + ChannelBuffer txMessage =
78 + bgpSession.prepareBgpNotification(errorCode, errorSubcode,
79 + null);
80 + ctx.getChannel().write(txMessage);
81 + bgpSession.closeChannel(ctx);
82 + return null;
83 + }
84 + }
85 +
86 + //
87 + // Read and check the BGP message Length field
88 + //
89 + int length = buf.readUnsignedShort();
90 + if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
91 + (length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
92 + log.debug("BGP RX Error: invalid Length field {}. " +
93 + "Must be between {} and {}",
94 + length,
95 + BgpConstants.BGP_HEADER_LENGTH,
96 + BgpConstants.BGP_MESSAGE_MAX_LENGTH);
97 + //
98 + // ERROR: Bad Message Length
99 + //
100 + // Send NOTIFICATION and close the connection
101 + ChannelBuffer txMessage =
102 + bgpSession.prepareBgpNotificationBadMessageLength(length);
103 + ctx.getChannel().write(txMessage);
104 + bgpSession.closeChannel(ctx);
105 + return null;
106 + }
107 +
108 + //
109 + // Test whether the rest of the message is received:
110 + // So far we have read the Marker (16 octets) and the
111 + // Length (2 octets) fields.
112 + //
113 + int remainingMessageLen =
114 + length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
115 + if (buf.readableBytes() < remainingMessageLen) {
116 + // No enough data received
117 + buf.resetReaderIndex();
118 + return null;
119 + }
120 +
121 + //
122 + // Read the BGP message Type field, and process based on that type
123 + //
124 + int type = buf.readUnsignedByte();
125 + remainingMessageLen--; // Adjust after reading the type
126 + ChannelBuffer message = buf.readBytes(remainingMessageLen);
127 +
128 + //
129 + // Process the remaining of the message based on the message type
130 + //
131 + switch (type) {
132 + case BgpConstants.BGP_TYPE_OPEN:
133 + bgpSession.processBgpOpen(ctx, message);
134 + break;
135 + case BgpConstants.BGP_TYPE_UPDATE:
136 + bgpSession.processBgpUpdate(ctx, message);
137 + break;
138 + case BgpConstants.BGP_TYPE_NOTIFICATION:
139 + bgpSession.processBgpNotification(ctx, message);
140 + break;
141 + case BgpConstants.BGP_TYPE_KEEPALIVE:
142 + bgpSession.processBgpKeepalive(ctx, message);
143 + break;
144 + default:
145 + //
146 + // ERROR: Bad Message Type
147 + //
148 + // Send NOTIFICATION and close the connection
149 + int errorCode = MessageHeaderError.ERROR_CODE;
150 + int errorSubcode = MessageHeaderError.BAD_MESSAGE_TYPE;
151 + ChannelBuffer data = ChannelBuffers.buffer(1);
152 + data.writeByte(type);
153 + ChannelBuffer txMessage =
154 + bgpSession.prepareBgpNotification(errorCode, errorSubcode,
155 + data);
156 + ctx.getChannel().write(txMessage);
157 + bgpSession.closeChannel(ctx);
158 + return null;
159 + }
160 + return null;
161 + }
162 +}
1 +/**
2 + * Implementation of the BGP protocol.
3 + */
4 +package org.onlab.onos.sdnip.bgp;
...\ No newline at end of file ...\ No newline at end of file
1 +package org.onlab.onos.sdnip;
2 +
3 +import static org.hamcrest.Matchers.is;
4 +import static org.hamcrest.Matchers.not;
5 +import static org.junit.Assert.assertThat;
6 +
7 +import org.junit.Test;
8 +import org.onlab.packet.IpAddress;
9 +import org.onlab.packet.IpPrefix;
10 +
11 +/**
12 + * Unit tests for the RouteEntry class.
13 + */
14 +public class RouteEntryTest {
15 + /**
16 + * Tests valid class constructor.
17 + */
18 + @Test
19 + public void testConstructor() {
20 + IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
21 + IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
22 +
23 + RouteEntry routeEntry = new RouteEntry(prefix, nextHop);
24 + assertThat(routeEntry.toString(),
25 + is("RouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8}"));
26 + }
27 +
28 + /**
29 + * Tests invalid class constructor for null IPv4 prefix.
30 + */
31 + @Test(expected = NullPointerException.class)
32 + public void testInvalidConstructorNullPrefix() {
33 + IpPrefix prefix = null;
34 + IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
35 +
36 + new RouteEntry(prefix, nextHop);
37 + }
38 +
39 + /**
40 + * Tests invalid class constructor for null IPv4 next-hop.
41 + */
42 + @Test(expected = NullPointerException.class)
43 + public void testInvalidConstructorNullNextHop() {
44 + IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
45 + IpAddress nextHop = null;
46 +
47 + new RouteEntry(prefix, nextHop);
48 + }
49 +
50 + /**
51 + * Tests getting the fields of a route entry.
52 + */
53 + @Test
54 + public void testGetFields() {
55 + IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
56 + IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
57 +
58 + RouteEntry routeEntry = new RouteEntry(prefix, nextHop);
59 + assertThat(routeEntry.prefix(), is(prefix));
60 + assertThat(routeEntry.nextHop(), is(nextHop));
61 + }
62 +
63 + /**
64 + * Tests creating a binary string from IPv4 prefix.
65 + */
66 + @Test
67 + public void testCreateBinaryString() {
68 + IpPrefix prefix;
69 +
70 + prefix = IpPrefix.valueOf("0.0.0.0/0");
71 + assertThat(RouteEntry.createBinaryString(prefix), is(""));
72 +
73 + prefix = IpPrefix.valueOf("192.168.166.0/22");
74 + assertThat(RouteEntry.createBinaryString(prefix),
75 + is("1100000010101000101001"));
76 +
77 + prefix = IpPrefix.valueOf("192.168.166.0/23");
78 + assertThat(RouteEntry.createBinaryString(prefix),
79 + is("11000000101010001010011"));
80 +
81 + prefix = IpPrefix.valueOf("192.168.166.0/24");
82 + assertThat(RouteEntry.createBinaryString(prefix),
83 + is("110000001010100010100110"));
84 +
85 + prefix = IpPrefix.valueOf("130.162.10.1/25");
86 + assertThat(RouteEntry.createBinaryString(prefix),
87 + is("1000001010100010000010100"));
88 +
89 + prefix = IpPrefix.valueOf("255.255.255.255/32");
90 + assertThat(RouteEntry.createBinaryString(prefix),
91 + is("11111111111111111111111111111111"));
92 + }
93 +
94 + /**
95 + * Tests equality of {@link RouteEntry}.
96 + */
97 + @Test
98 + public void testEquality() {
99 + IpPrefix prefix1 = IpPrefix.valueOf("1.2.3.0/24");
100 + IpAddress nextHop1 = IpAddress.valueOf("5.6.7.8");
101 + RouteEntry routeEntry1 = new RouteEntry(prefix1, nextHop1);
102 +
103 + IpPrefix prefix2 = IpPrefix.valueOf("1.2.3.0/24");
104 + IpAddress nextHop2 = IpAddress.valueOf("5.6.7.8");
105 + RouteEntry routeEntry2 = new RouteEntry(prefix2, nextHop2);
106 +
107 + assertThat(routeEntry1, is(routeEntry2));
108 + }
109 +
110 + /**
111 + * Tests non-equality of {@link RouteEntry}.
112 + */
113 + @Test
114 + public void testNonEquality() {
115 + IpPrefix prefix1 = IpPrefix.valueOf("1.2.3.0/24");
116 + IpAddress nextHop1 = IpAddress.valueOf("5.6.7.8");
117 + RouteEntry routeEntry1 = new RouteEntry(prefix1, nextHop1);
118 +
119 + IpPrefix prefix2 = IpPrefix.valueOf("1.2.3.0/25"); // Different
120 + IpAddress nextHop2 = IpAddress.valueOf("5.6.7.8");
121 + RouteEntry routeEntry2 = new RouteEntry(prefix2, nextHop2);
122 +
123 + IpPrefix prefix3 = IpPrefix.valueOf("1.2.3.0/24");
124 + IpAddress nextHop3 = IpAddress.valueOf("5.6.7.9"); // Different
125 + RouteEntry routeEntry3 = new RouteEntry(prefix3, nextHop3);
126 +
127 + assertThat(routeEntry1, is(not(routeEntry2)));
128 + assertThat(routeEntry1, is(not(routeEntry3)));
129 + }
130 +
131 + /**
132 + * Tests object string representation.
133 + */
134 + @Test
135 + public void testToString() {
136 + IpPrefix prefix = IpPrefix.valueOf("1.2.3.0/24");
137 + IpAddress nextHop = IpAddress.valueOf("5.6.7.8");
138 + RouteEntry routeEntry = new RouteEntry(prefix, nextHop);
139 +
140 + assertThat(routeEntry.toString(),
141 + is("RouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8}"));
142 + }
143 +}
...@@ -26,6 +26,16 @@ ...@@ -26,6 +26,16 @@
26 <groupId>org.onlab.onos</groupId> 26 <groupId>org.onlab.onos</groupId>
27 <artifactId>onlab-osgi</artifactId> 27 <artifactId>onlab-osgi</artifactId>
28 </dependency> 28 </dependency>
29 +
30 + <dependency>
31 + <groupId>com.fasterxml.jackson.core</groupId>
32 + <artifactId>jackson-databind</artifactId>
33 + </dependency>
34 + <dependency>
35 + <groupId>com.fasterxml.jackson.core</groupId>
36 + <artifactId>jackson-annotations</artifactId>
37 + </dependency>
38 +
29 <dependency> 39 <dependency>
30 <groupId>org.osgi</groupId> 40 <groupId>org.osgi</groupId>
31 <artifactId>org.osgi.core</artifactId> 41 <artifactId>org.osgi.core</artifactId>
......
1 package org.onlab.onos.cli; 1 package org.onlab.onos.cli;
2 2
3 +import org.apache.karaf.shell.commands.Option;
3 import org.apache.karaf.shell.console.OsgiCommandSupport; 4 import org.apache.karaf.shell.console.OsgiCommandSupport;
4 import org.onlab.osgi.DefaultServiceDirectory; 5 import org.onlab.osgi.DefaultServiceDirectory;
5 import org.onlab.osgi.ServiceNotFoundException; 6 import org.onlab.osgi.ServiceNotFoundException;
...@@ -9,6 +10,10 @@ import org.onlab.osgi.ServiceNotFoundException; ...@@ -9,6 +10,10 @@ import org.onlab.osgi.ServiceNotFoundException;
9 */ 10 */
10 public abstract class AbstractShellCommand extends OsgiCommandSupport { 11 public abstract class AbstractShellCommand extends OsgiCommandSupport {
11 12
13 + @Option(name = "-j", aliases = "--json", description = "Output JSON",
14 + required = false, multiValued = false)
15 + private boolean json = false;
16 +
12 /** 17 /**
13 * Returns the reference to the implementation of the specified service. 18 * Returns the reference to the implementation of the specified service.
14 * 19 *
...@@ -46,6 +51,15 @@ public abstract class AbstractShellCommand extends OsgiCommandSupport { ...@@ -46,6 +51,15 @@ public abstract class AbstractShellCommand extends OsgiCommandSupport {
46 */ 51 */
47 protected abstract void execute(); 52 protected abstract void execute();
48 53
54 + /**
55 + * Indicates whether JSON format should be output.
56 + *
57 + * @return true if JSON is requested
58 + */
59 + protected boolean outputJson() {
60 + return json;
61 + }
62 +
49 @Override 63 @Override
50 protected Object doExecute() throws Exception { 64 protected Object doExecute() throws Exception {
51 try { 65 try {
......
1 package org.onlab.onos.cli; 1 package org.onlab.onos.cli;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
3 import com.google.common.collect.Lists; 6 import com.google.common.collect.Lists;
4 -
5 import org.apache.karaf.shell.commands.Command; 7 import org.apache.karaf.shell.commands.Command;
6 import org.onlab.onos.cluster.ClusterService; 8 import org.onlab.onos.cluster.ClusterService;
7 import org.onlab.onos.cluster.ControllerNode; 9 import org.onlab.onos.cluster.ControllerNode;
...@@ -26,7 +28,10 @@ public class MastersListCommand extends AbstractShellCommand { ...@@ -26,7 +28,10 @@ public class MastersListCommand extends AbstractShellCommand {
26 MastershipService mastershipService = get(MastershipService.class); 28 MastershipService mastershipService = get(MastershipService.class);
27 List<ControllerNode> nodes = newArrayList(service.getNodes()); 29 List<ControllerNode> nodes = newArrayList(service.getNodes());
28 Collections.sort(nodes, Comparators.NODE_COMPARATOR); 30 Collections.sort(nodes, Comparators.NODE_COMPARATOR);
29 - ControllerNode self = service.getLocalNode(); 31 +
32 + if (outputJson()) {
33 + print("%s", json(service, mastershipService, nodes));
34 + } else {
30 for (ControllerNode node : nodes) { 35 for (ControllerNode node : nodes) {
31 List<DeviceId> ids = Lists.newArrayList(mastershipService.getDevicesOf(node.id())); 36 List<DeviceId> ids = Lists.newArrayList(mastershipService.getDevicesOf(node.id()));
32 Collections.sort(ids, Comparators.ELEMENT_ID_COMPARATOR); 37 Collections.sort(ids, Comparators.ELEMENT_ID_COMPARATOR);
...@@ -36,5 +41,37 @@ public class MastersListCommand extends AbstractShellCommand { ...@@ -36,5 +41,37 @@ public class MastersListCommand extends AbstractShellCommand {
36 } 41 }
37 } 42 }
38 } 43 }
44 + }
45 +
46 + // Produces JSON structure.
47 + private JsonNode json(ClusterService service, MastershipService mastershipService,
48 + List<ControllerNode> nodes) {
49 + ObjectMapper mapper = new ObjectMapper();
50 + ArrayNode result = mapper.createArrayNode();
51 + ControllerNode self = service.getLocalNode();
52 + for (ControllerNode node : nodes) {
53 + List<DeviceId> ids = Lists.newArrayList(mastershipService.getDevicesOf(node.id()));
54 + result.add(mapper.createObjectNode()
55 + .put("id", node.id().toString())
56 + .put("size", ids.size())
57 + .set("devices", json(mapper, ids)));
58 + }
59 + return result;
60 + }
61 +
62 + /**
63 + * Produces a JSON array containing the specified device identifiers.
64 + *
65 + * @param mapper object mapper
66 + * @param ids collection of device identifiers
67 + * @return JSON array
68 + */
69 + public static JsonNode json(ObjectMapper mapper, Iterable<DeviceId> ids) {
70 + ArrayNode result = mapper.createArrayNode();
71 + for (DeviceId deviceId : ids) {
72 + result.add(deviceId.toString());
73 + }
74 + return result;
75 + }
39 76
40 } 77 }
......
1 package org.onlab.onos.cli; 1 package org.onlab.onos.cli;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
3 import org.apache.karaf.shell.commands.Command; 6 import org.apache.karaf.shell.commands.Command;
4 import org.onlab.onos.cluster.ClusterService; 7 import org.onlab.onos.cluster.ClusterService;
5 import org.onlab.onos.cluster.ControllerNode; 8 import org.onlab.onos.cluster.ControllerNode;
...@@ -24,6 +27,9 @@ public class NodesListCommand extends AbstractShellCommand { ...@@ -24,6 +27,9 @@ public class NodesListCommand extends AbstractShellCommand {
24 ClusterService service = get(ClusterService.class); 27 ClusterService service = get(ClusterService.class);
25 List<ControllerNode> nodes = newArrayList(service.getNodes()); 28 List<ControllerNode> nodes = newArrayList(service.getNodes());
26 Collections.sort(nodes, Comparators.NODE_COMPARATOR); 29 Collections.sort(nodes, Comparators.NODE_COMPARATOR);
30 + if (outputJson()) {
31 + print("%s", json(service, nodes));
32 + } else {
27 ControllerNode self = service.getLocalNode(); 33 ControllerNode self = service.getLocalNode();
28 for (ControllerNode node : nodes) { 34 for (ControllerNode node : nodes) {
29 print(FMT, node.id(), node.ip(), node.tcpPort(), 35 print(FMT, node.id(), node.ip(), node.tcpPort(),
...@@ -31,5 +37,22 @@ public class NodesListCommand extends AbstractShellCommand { ...@@ -31,5 +37,22 @@ public class NodesListCommand extends AbstractShellCommand {
31 node.equals(self) ? "*" : ""); 37 node.equals(self) ? "*" : "");
32 } 38 }
33 } 39 }
40 + }
41 +
42 + // Produces JSON structure.
43 + private JsonNode json(ClusterService service, List<ControllerNode> nodes) {
44 + ObjectMapper mapper = new ObjectMapper();
45 + ArrayNode result = mapper.createArrayNode();
46 + ControllerNode self = service.getLocalNode();
47 + for (ControllerNode node : nodes) {
48 + result.add(mapper.createObjectNode()
49 + .put("id", node.id().toString())
50 + .put("ip", node.ip().toString())
51 + .put("tcpPort", node.tcpPort())
52 + .put("state", service.getState(node.id()).toString())
53 + .put("self", node.equals(self)));
54 + }
55 + return result;
56 + }
34 57
35 } 58 }
......
1 package org.onlab.onos.cli; 1 package org.onlab.onos.cli;
2 2
3 +import com.fasterxml.jackson.databind.ObjectMapper;
3 import org.apache.karaf.shell.commands.Command; 4 import org.apache.karaf.shell.commands.Command;
4 import org.onlab.onos.CoreService; 5 import org.onlab.onos.CoreService;
5 import org.onlab.onos.cluster.ClusterService; 6 import org.onlab.onos.cluster.ClusterService;
...@@ -22,6 +23,19 @@ public class SummaryCommand extends AbstractShellCommand { ...@@ -22,6 +23,19 @@ public class SummaryCommand extends AbstractShellCommand {
22 protected void execute() { 23 protected void execute() {
23 TopologyService topologyService = get(TopologyService.class); 24 TopologyService topologyService = get(TopologyService.class);
24 Topology topology = topologyService.currentTopology(); 25 Topology topology = topologyService.currentTopology();
26 + if (outputJson()) {
27 + print("%s", new ObjectMapper().createObjectNode()
28 + .put("node", get(ClusterService.class).getLocalNode().ip().toString())
29 + .put("version", get(CoreService.class).version().toString())
30 + .put("nodes", get(ClusterService.class).getNodes().size())
31 + .put("devices", get(DeviceService.class).getDeviceCount())
32 + .put("links", get(LinkService.class).getLinkCount())
33 + .put("hosts", get(HostService.class).getHostCount())
34 + .put("clusters", topologyService.getClusters(topology).size())
35 + .put("paths", topology.pathCount())
36 + .put("flows", get(FlowRuleService.class).getFlowRuleCount())
37 + .put("intents", get(IntentService.class).getIntentCount()));
38 + } else {
25 print("node=%s, version=%s", 39 print("node=%s, version=%s",
26 get(ClusterService.class).getLocalNode().ip(), 40 get(ClusterService.class).getLocalNode().ip(),
27 get(CoreService.class).version().toString()); 41 get(CoreService.class).version().toString());
...@@ -35,5 +49,6 @@ public class SummaryCommand extends AbstractShellCommand { ...@@ -35,5 +49,6 @@ public class SummaryCommand extends AbstractShellCommand {
35 get(FlowRuleService.class).getFlowRuleCount(), 49 get(FlowRuleService.class).getFlowRuleCount(),
36 get(IntentService.class).getIntentCount()); 50 get(IntentService.class).getIntentCount());
37 } 51 }
52 + }
38 53
39 } 54 }
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.ObjectMapper;
3 import com.google.common.collect.Lists; 4 import com.google.common.collect.Lists;
4 import org.apache.karaf.shell.commands.Argument; 5 import org.apache.karaf.shell.commands.Argument;
5 import org.apache.karaf.shell.commands.Command; 6 import org.apache.karaf.shell.commands.Command;
...@@ -10,6 +11,7 @@ import org.onlab.onos.net.topology.TopologyCluster; ...@@ -10,6 +11,7 @@ import org.onlab.onos.net.topology.TopologyCluster;
10 import java.util.Collections; 11 import java.util.Collections;
11 import java.util.List; 12 import java.util.List;
12 13
14 +import static org.onlab.onos.cli.MastersListCommand.json;
13 import static org.onlab.onos.net.topology.ClusterId.clusterId; 15 import static org.onlab.onos.net.topology.ClusterId.clusterId;
14 16
15 /** 17 /**
...@@ -33,11 +35,14 @@ public class ClusterDevicesCommand extends ClustersListCommand { ...@@ -33,11 +35,14 @@ public class ClusterDevicesCommand extends ClustersListCommand {
33 } else { 35 } else {
34 List<DeviceId> ids = Lists.newArrayList(service.getClusterDevices(topology, cluster)); 36 List<DeviceId> ids = Lists.newArrayList(service.getClusterDevices(topology, cluster));
35 Collections.sort(ids, Comparators.ELEMENT_ID_COMPARATOR); 37 Collections.sort(ids, Comparators.ELEMENT_ID_COMPARATOR);
38 + if (outputJson()) {
39 + print("%s", json(new ObjectMapper(), ids));
40 + } else {
36 for (DeviceId deviceId : ids) { 41 for (DeviceId deviceId : ids) {
37 print("%s", deviceId); 42 print("%s", deviceId);
38 } 43 }
39 } 44 }
40 } 45 }
41 - 46 + }
42 47
43 } 48 }
......
...@@ -5,6 +5,7 @@ import org.apache.karaf.shell.commands.Command; ...@@ -5,6 +5,7 @@ import org.apache.karaf.shell.commands.Command;
5 import org.onlab.onos.net.Link; 5 import org.onlab.onos.net.Link;
6 import org.onlab.onos.net.topology.TopologyCluster; 6 import org.onlab.onos.net.topology.TopologyCluster;
7 7
8 +import static org.onlab.onos.cli.net.LinksListCommand.json;
8 import static org.onlab.onos.cli.net.LinksListCommand.linkString; 9 import static org.onlab.onos.cli.net.LinksListCommand.linkString;
9 import static org.onlab.onos.net.topology.ClusterId.clusterId; 10 import static org.onlab.onos.net.topology.ClusterId.clusterId;
10 11
...@@ -26,6 +27,8 @@ public class ClusterLinksCommand extends ClustersListCommand { ...@@ -26,6 +27,8 @@ public class ClusterLinksCommand extends ClustersListCommand {
26 TopologyCluster cluster = service.getCluster(topology, clusterId(cid)); 27 TopologyCluster cluster = service.getCluster(topology, clusterId(cid));
27 if (cluster == null) { 28 if (cluster == null) {
28 error("No such cluster %s", cid); 29 error("No such cluster %s", cid);
30 + } else if (outputJson()) {
31 + print("%s", json(service.getClusterLinks(topology, cluster)));
29 } else { 32 } else {
30 for (Link link : service.getClusterLinks(topology, cluster)) { 33 for (Link link : service.getClusterLinks(topology, cluster)) {
31 print(linkString(link)); 34 print(linkString(link));
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
3 import com.google.common.collect.Lists; 6 import com.google.common.collect.Lists;
4 import org.apache.karaf.shell.commands.Command; 7 import org.apache.karaf.shell.commands.Command;
5 import org.onlab.onos.cli.Comparators; 8 import org.onlab.onos.cli.Comparators;
...@@ -24,9 +27,26 @@ public class ClustersListCommand extends TopologyCommand { ...@@ -24,9 +27,26 @@ public class ClustersListCommand extends TopologyCommand {
24 List<TopologyCluster> clusters = Lists.newArrayList(service.getClusters(topology)); 27 List<TopologyCluster> clusters = Lists.newArrayList(service.getClusters(topology));
25 Collections.sort(clusters, Comparators.CLUSTER_COMPARATOR); 28 Collections.sort(clusters, Comparators.CLUSTER_COMPARATOR);
26 29
30 + if (outputJson()) {
31 + print("%s", json(clusters));
32 + } else {
27 for (TopologyCluster cluster : clusters) { 33 for (TopologyCluster cluster : clusters) {
28 print(FMT, cluster.id().index(), cluster.deviceCount(), cluster.linkCount()); 34 print(FMT, cluster.id().index(), cluster.deviceCount(), cluster.linkCount());
29 } 35 }
30 } 36 }
37 + }
38 +
39 + // Produces a JSON result.
40 + private JsonNode json(Iterable<TopologyCluster> clusters) {
41 + ObjectMapper mapper = new ObjectMapper();
42 + ArrayNode result = mapper.createArrayNode();
43 + for (TopologyCluster cluster : clusters) {
44 + result.add(mapper.createObjectNode()
45 + .put("id", cluster.id().index())
46 + .put("deviceCount", cluster.deviceCount())
47 + .put("linkCount", cluster.linkCount()));
48 + }
49 + return result;
50 + }
31 51
32 } 52 }
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
6 +import com.fasterxml.jackson.databind.node.ObjectNode;
3 import org.apache.karaf.shell.commands.Argument; 7 import org.apache.karaf.shell.commands.Argument;
4 import org.apache.karaf.shell.commands.Command; 8 import org.apache.karaf.shell.commands.Command;
9 +import org.apache.karaf.shell.commands.Option;
5 import org.onlab.onos.cli.Comparators; 10 import org.onlab.onos.cli.Comparators;
6 import org.onlab.onos.net.Device; 11 import org.onlab.onos.net.Device;
7 import org.onlab.onos.net.Port; 12 import org.onlab.onos.net.Port;
...@@ -22,6 +27,14 @@ public class DevicePortsListCommand extends DevicesListCommand { ...@@ -22,6 +27,14 @@ public class DevicePortsListCommand extends DevicesListCommand {
22 27
23 private static final String FMT = " port=%s, state=%s"; 28 private static final String FMT = " port=%s, state=%s";
24 29
30 + @Option(name = "-e", aliases = "--enabled", description = "Show only enabled ports",
31 + required = false, multiValued = false)
32 + private boolean enabled = false;
33 +
34 + @Option(name = "-d", aliases = "--disabled", description = "Show only disabled ports",
35 + required = false, multiValued = false)
36 + private boolean disabled = false;
37 +
25 @Argument(index = 0, name = "uri", description = "Device ID", 38 @Argument(index = 0, name = "uri", description = "Device ID",
26 required = false, multiValued = false) 39 required = false, multiValued = false)
27 String uri = null; 40 String uri = null;
...@@ -30,27 +43,79 @@ public class DevicePortsListCommand extends DevicesListCommand { ...@@ -30,27 +43,79 @@ public class DevicePortsListCommand extends DevicesListCommand {
30 protected void execute() { 43 protected void execute() {
31 DeviceService service = get(DeviceService.class); 44 DeviceService service = get(DeviceService.class);
32 if (uri == null) { 45 if (uri == null) {
46 + if (outputJson()) {
47 + print("%s", jsonPorts(service, getSortedDevices(service)));
48 + } else {
33 for (Device device : getSortedDevices(service)) { 49 for (Device device : getSortedDevices(service)) {
34 printDevice(service, device); 50 printDevice(service, device);
35 } 51 }
52 + }
53 +
36 } else { 54 } else {
37 Device device = service.getDevice(deviceId(uri)); 55 Device device = service.getDevice(deviceId(uri));
38 if (device == null) { 56 if (device == null) {
39 error("No such device %s", uri); 57 error("No such device %s", uri);
58 + } else if (outputJson()) {
59 + print("%s", jsonPorts(service, new ObjectMapper(), device));
40 } else { 60 } else {
41 printDevice(service, device); 61 printDevice(service, device);
42 } 62 }
43 } 63 }
44 } 64 }
45 65
66 + /**
67 + * Produces JSON array containing ports of the specified devices.
68 + *
69 + * @param service device service
70 + * @param devices collection of devices
71 + * @return JSON array
72 + */
73 + public JsonNode jsonPorts(DeviceService service, Iterable<Device> devices) {
74 + ObjectMapper mapper = new ObjectMapper();
75 + ArrayNode result = mapper.createArrayNode();
76 + for (Device device : devices) {
77 + result.add(jsonPorts(service, mapper, device));
78 + }
79 + return result;
80 + }
81 +
82 + /**
83 + * Produces JSON array containing ports of the specified device.
84 + *
85 + * @param service device service
86 + * @param mapper object mapper
87 + * @param device infrastructure devices
88 + * @return JSON array
89 + */
90 + public JsonNode jsonPorts(DeviceService service, ObjectMapper mapper, Device device) {
91 + ObjectNode result = mapper.createObjectNode();
92 + ArrayNode ports = mapper.createArrayNode();
93 + for (Port port : service.getPorts(device.id())) {
94 + if (isIncluded(port)) {
95 + ports.add(mapper.createObjectNode()
96 + .put("port", port.number().toString())
97 + .put("isEnabled", port.isEnabled()));
98 + }
99 + }
100 + return result.put("device", device.id().toString()).set("ports", ports);
101 + }
102 +
103 + // Determines if a port should be included in output.
104 + private boolean isIncluded(Port port) {
105 + return enabled && port.isEnabled() || disabled && !port.isEnabled() ||
106 + !enabled && !disabled;
107 + }
108 +
46 @Override 109 @Override
47 protected void printDevice(DeviceService service, Device device) { 110 protected void printDevice(DeviceService service, Device device) {
48 super.printDevice(service, device); 111 super.printDevice(service, device);
49 List<Port> ports = new ArrayList<>(service.getPorts(device.id())); 112 List<Port> ports = new ArrayList<>(service.getPorts(device.id()));
50 Collections.sort(ports, Comparators.PORT_COMPARATOR); 113 Collections.sort(ports, Comparators.PORT_COMPARATOR);
51 for (Port port : ports) { 114 for (Port port : ports) {
115 + if (isIncluded(port)) {
52 print(FMT, port.number(), port.isEnabled() ? "enabled" : "disabled"); 116 print(FMT, port.number(), port.isEnabled() ? "enabled" : "disabled");
53 } 117 }
54 } 118 }
119 + }
55 120
56 } 121 }
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
6 +import com.fasterxml.jackson.databind.node.ObjectNode;
3 import org.apache.karaf.shell.commands.Command; 7 import org.apache.karaf.shell.commands.Command;
4 import org.onlab.onos.cli.AbstractShellCommand; 8 import org.onlab.onos.cli.AbstractShellCommand;
5 import org.onlab.onos.cli.Comparators; 9 import org.onlab.onos.cli.Comparators;
...@@ -24,10 +28,53 @@ public class DevicesListCommand extends AbstractShellCommand { ...@@ -24,10 +28,53 @@ public class DevicesListCommand extends AbstractShellCommand {
24 @Override 28 @Override
25 protected void execute() { 29 protected void execute() {
26 DeviceService service = get(DeviceService.class); 30 DeviceService service = get(DeviceService.class);
31 + if (outputJson()) {
32 + print("%s", json(service, getSortedDevices(service)));
33 + } else {
27 for (Device device : getSortedDevices(service)) { 34 for (Device device : getSortedDevices(service)) {
28 printDevice(service, device); 35 printDevice(service, device);
29 } 36 }
30 } 37 }
38 + }
39 +
40 + /**
41 + * Returns JSON node representing the specified devices.
42 + *
43 + * @param service device service
44 + * @param devices collection of devices
45 + * @return JSON node
46 + */
47 + public static JsonNode json(DeviceService service, Iterable<Device> devices) {
48 + ObjectMapper mapper = new ObjectMapper();
49 + ArrayNode result = mapper.createArrayNode();
50 + for (Device device : devices) {
51 + result.add(json(service, mapper, device));
52 + }
53 + return result;
54 + }
55 +
56 + /**
57 + * Returns JSON node representing the specified device.
58 + *
59 + * @param service device service
60 + * @param mapper object mapper
61 + * @param device infrastructure device
62 + * @return JSON node
63 + */
64 + public static ObjectNode json(DeviceService service, ObjectMapper mapper,
65 + Device device) {
66 + ObjectNode result = mapper.createObjectNode();
67 + if (device != null) {
68 + result.put("id", device.id().toString())
69 + .put("available", service.isAvailable(device.id()))
70 + .put("role", service.getRole(device.id()).toString())
71 + .put("mfr", device.manufacturer())
72 + .put("hw", device.hwVersion())
73 + .put("sw", device.swVersion())
74 + .put("serial", device.serialNumber());
75 + }
76 + return result;
77 + }
31 78
32 /** 79 /**
33 * Returns the list of devices sorted using the device ID URIs. 80 * Returns the list of devices sorted using the device ID URIs.
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
6 +import com.fasterxml.jackson.databind.node.ObjectNode;
3 import com.google.common.collect.Maps; 7 import com.google.common.collect.Maps;
4 import org.apache.karaf.shell.commands.Argument; 8 import org.apache.karaf.shell.commands.Argument;
5 import org.apache.karaf.shell.commands.Command; 9 import org.apache.karaf.shell.commands.Command;
...@@ -12,6 +16,8 @@ import org.onlab.onos.net.device.DeviceService; ...@@ -12,6 +16,8 @@ import org.onlab.onos.net.device.DeviceService;
12 import org.onlab.onos.net.flow.FlowEntry; 16 import org.onlab.onos.net.flow.FlowEntry;
13 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState; 17 import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
14 import org.onlab.onos.net.flow.FlowRuleService; 18 import org.onlab.onos.net.flow.FlowRuleService;
19 +import org.onlab.onos.net.flow.criteria.Criterion;
20 +import org.onlab.onos.net.flow.instructions.Instruction;
15 21
16 import java.util.Collections; 22 import java.util.Collections;
17 import java.util.List; 23 import java.util.List;
...@@ -48,10 +54,74 @@ public class FlowsListCommand extends AbstractShellCommand { ...@@ -48,10 +54,74 @@ public class FlowsListCommand extends AbstractShellCommand {
48 DeviceService deviceService = get(DeviceService.class); 54 DeviceService deviceService = get(DeviceService.class);
49 FlowRuleService service = get(FlowRuleService.class); 55 FlowRuleService service = get(FlowRuleService.class);
50 Map<Device, List<FlowEntry>> flows = getSortedFlows(deviceService, service); 56 Map<Device, List<FlowEntry>> flows = getSortedFlows(deviceService, service);
57 +
58 + if (outputJson()) {
59 + print("%s", json(coreService, getSortedDevices(deviceService), flows));
60 + } else {
51 for (Device d : getSortedDevices(deviceService)) { 61 for (Device d : getSortedDevices(deviceService)) {
52 printFlows(d, flows.get(d), coreService); 62 printFlows(d, flows.get(d), coreService);
53 } 63 }
54 } 64 }
65 + }
66 +
67 + /**
68 + * Produces a JSON array of flows grouped by the each device.
69 + *
70 + * @param coreService core service
71 + * @param devices collection of devices to group flow by
72 + * @param flows collection of flows per each device
73 + * @return JSON array
74 + */
75 + private JsonNode json(CoreService coreService, Iterable<Device> devices,
76 + Map<Device, List<FlowEntry>> flows) {
77 + ObjectMapper mapper = new ObjectMapper();
78 + ArrayNode result = mapper.createArrayNode();
79 + for (Device device : devices) {
80 + result.add(json(coreService, mapper, device, flows.get(device)));
81 + }
82 + return result;
83 + }
84 +
85 + // Produces JSON object with the flows of the given device.
86 + private ObjectNode json(CoreService coreService, ObjectMapper mapper,
87 + Device device, List<FlowEntry> flows) {
88 + ObjectNode result = mapper.createObjectNode();
89 + ArrayNode array = mapper.createArrayNode();
90 +
91 + for (FlowEntry flow : flows) {
92 + array.add(json(coreService, mapper, flow));
93 + }
94 +
95 + result.put("device", device.id().toString())
96 + .put("flowCount", flows.size())
97 + .put("flows", array);
98 + return result;
99 + }
100 +
101 + // Produces JSON structure with the specified flow data.
102 + private ObjectNode json(CoreService coreService, ObjectMapper mapper,
103 + FlowEntry flow) {
104 + ObjectNode result = mapper.createObjectNode();
105 + ArrayNode crit = mapper.createArrayNode();
106 + for (Criterion c : flow.selector().criteria()) {
107 + crit.add(c.toString());
108 + }
109 +
110 + ArrayNode instr = mapper.createArrayNode();
111 + for (Instruction i : flow.treatment().instructions()) {
112 + instr.add(i.toString());
113 + }
114 +
115 + result.put("flowId", Long.toHexString(flow.id().value()))
116 + .put("state", flow.state().toString())
117 + .put("bytes", flow.bytes())
118 + .put("packets", flow.packets())
119 + .put("life", flow.life())
120 + .put("appId", coreService.getAppId(flow.appId()).name());
121 + result.set("selector", crit);
122 + result.set("treatment", instr);
123 + return result;
124 + }
55 125
56 /** 126 /**
57 * Returns the list of devices sorted using the device ID URIs. 127 * Returns the list of devices sorted using the device ID URIs.
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
6 +import com.fasterxml.jackson.databind.node.ObjectNode;
3 import org.apache.karaf.shell.commands.Command; 7 import org.apache.karaf.shell.commands.Command;
4 import org.onlab.onos.cli.AbstractShellCommand; 8 import org.onlab.onos.cli.AbstractShellCommand;
5 import org.onlab.onos.cli.Comparators; 9 import org.onlab.onos.cli.Comparators;
6 import org.onlab.onos.net.Host; 10 import org.onlab.onos.net.Host;
7 import org.onlab.onos.net.host.HostService; 11 import org.onlab.onos.net.host.HostService;
12 +import org.onlab.packet.IpPrefix;
8 13
9 import java.util.Collections; 14 import java.util.Collections;
10 import java.util.List; 15 import java.util.List;
...@@ -24,10 +29,41 @@ public class HostsListCommand extends AbstractShellCommand { ...@@ -24,10 +29,41 @@ public class HostsListCommand extends AbstractShellCommand {
24 @Override 29 @Override
25 protected void execute() { 30 protected void execute() {
26 HostService service = get(HostService.class); 31 HostService service = get(HostService.class);
32 + if (outputJson()) {
33 + print("%s", json(getSortedHosts(service)));
34 + } else {
27 for (Host host : getSortedHosts(service)) { 35 for (Host host : getSortedHosts(service)) {
28 printHost(host); 36 printHost(host);
29 } 37 }
30 } 38 }
39 + }
40 +
41 + // Produces JSON structure.
42 + private static JsonNode json(Iterable<Host> hosts) {
43 + ObjectMapper mapper = new ObjectMapper();
44 + ArrayNode result = mapper.createArrayNode();
45 + for (Host host : hosts) {
46 + result.add(json(mapper, host));
47 + }
48 + return result;
49 + }
50 +
51 + // Produces JSON structure.
52 + private static JsonNode json(ObjectMapper mapper, Host host) {
53 + ObjectNode loc = LinksListCommand.json(mapper, host.location())
54 + .put("time", host.location().time());
55 + ArrayNode ips = mapper.createArrayNode();
56 + for (IpPrefix ip : host.ipAddresses()) {
57 + ips.add(ip.toString());
58 + }
59 + ObjectNode result = mapper.createObjectNode()
60 + .put("id", host.id().toString())
61 + .put("mac", host.mac().toString())
62 + .put("vlan", host.vlan().toString());
63 + result.set("location", loc);
64 + result.set("ips", ips);
65 + return result;
66 + }
31 67
32 /** 68 /**
33 * Returns the list of devices sorted using the device ID URIs. 69 * Returns the list of devices sorted using the device ID URIs.
...@@ -44,7 +80,7 @@ public class HostsListCommand extends AbstractShellCommand { ...@@ -44,7 +80,7 @@ public class HostsListCommand extends AbstractShellCommand {
44 /** 80 /**
45 * Prints information about a host. 81 * Prints information about a host.
46 * 82 *
47 - * @param host 83 + * @param host end-station host
48 */ 84 */
49 protected void printHost(Host host) { 85 protected void printHost(Host host) {
50 if (host != null) { 86 if (host != null) {
...@@ -54,4 +90,4 @@ public class HostsListCommand extends AbstractShellCommand { ...@@ -54,4 +90,4 @@ public class HostsListCommand extends AbstractShellCommand {
54 host.vlan(), host.ipAddresses()); 90 host.vlan(), host.ipAddresses());
55 } 91 }
56 } 92 }
57 - } 93 +}
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
6 +import com.fasterxml.jackson.databind.node.ObjectNode;
3 import org.apache.karaf.shell.commands.Argument; 7 import org.apache.karaf.shell.commands.Argument;
4 import org.apache.karaf.shell.commands.Command; 8 import org.apache.karaf.shell.commands.Command;
5 import org.onlab.onos.cli.AbstractShellCommand; 9 import org.onlab.onos.cli.AbstractShellCommand;
10 +import org.onlab.onos.net.ConnectPoint;
6 import org.onlab.onos.net.Link; 11 import org.onlab.onos.net.Link;
7 import org.onlab.onos.net.link.LinkService; 12 import org.onlab.onos.net.link.LinkService;
8 13
...@@ -27,10 +32,56 @@ public class LinksListCommand extends AbstractShellCommand { ...@@ -27,10 +32,56 @@ public class LinksListCommand extends AbstractShellCommand {
27 LinkService service = get(LinkService.class); 32 LinkService service = get(LinkService.class);
28 Iterable<Link> links = uri != null ? 33 Iterable<Link> links = uri != null ?
29 service.getDeviceLinks(deviceId(uri)) : service.getLinks(); 34 service.getDeviceLinks(deviceId(uri)) : service.getLinks();
35 + if (outputJson()) {
36 + print("%s", json(links));
37 + } else {
30 for (Link link : links) { 38 for (Link link : links) {
31 print(linkString(link)); 39 print(linkString(link));
32 } 40 }
33 } 41 }
42 + }
43 +
44 + /**
45 + * Produces a JSON array containing the specified links.
46 + *
47 + * @param links collection of links
48 + * @return JSON array
49 + */
50 + public static JsonNode json(Iterable<Link> links) {
51 + ObjectMapper mapper = new ObjectMapper();
52 + ArrayNode result = mapper.createArrayNode();
53 + for (Link link : links) {
54 + result.add(json(mapper, link));
55 + }
56 + return result;
57 + }
58 +
59 + /**
60 + * Produces a JSON object for the specified link.
61 + *
62 + * @param mapper object mapper
63 + * @param link link to encode
64 + * @return JSON object
65 + */
66 + public static ObjectNode json(ObjectMapper mapper, Link link) {
67 + ObjectNode result = mapper.createObjectNode();
68 + result.set("src", json(mapper, link.src()));
69 + result.set("dst", json(mapper, link.dst()));
70 + return result;
71 + }
72 +
73 + /**
74 + * Produces a JSON object for the specified connect point.
75 + *
76 + * @param mapper object mapper
77 + * @param connectPoint connection point to encode
78 + * @return JSON object
79 + */
80 + public static ObjectNode json(ObjectMapper mapper, ConnectPoint connectPoint) {
81 + return mapper.createObjectNode()
82 + .put("device", connectPoint.deviceId().toString())
83 + .put("port", connectPoint.port().toString());
84 + }
34 85
35 /** 86 /**
36 * Returns a formatted string representing the given link. 87 * Returns a formatted string representing the given link.
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.JsonNode;
4 +import com.fasterxml.jackson.databind.ObjectMapper;
5 +import com.fasterxml.jackson.databind.node.ArrayNode;
3 import org.apache.karaf.shell.commands.Argument; 6 import org.apache.karaf.shell.commands.Argument;
4 import org.apache.karaf.shell.commands.Command; 7 import org.apache.karaf.shell.commands.Command;
5 import org.onlab.onos.net.Link; 8 import org.onlab.onos.net.Link;
...@@ -32,10 +35,31 @@ public class PathListCommand extends TopologyCommand { ...@@ -32,10 +35,31 @@ public class PathListCommand extends TopologyCommand {
32 protected void execute() { 35 protected void execute() {
33 init(); 36 init();
34 Set<Path> paths = service.getPaths(topology, deviceId(src), deviceId(dst)); 37 Set<Path> paths = service.getPaths(topology, deviceId(src), deviceId(dst));
38 + if (outputJson()) {
39 + print("%s", json(paths));
40 + } else {
35 for (Path path : paths) { 41 for (Path path : paths) {
36 print(pathString(path)); 42 print(pathString(path));
37 } 43 }
38 } 44 }
45 + }
46 +
47 + /**
48 + * Produces a JSON array containing the specified paths.
49 + *
50 + * @param paths collection of paths
51 + * @return JSON array
52 + */
53 + public static JsonNode json(Iterable<Path> paths) {
54 + ObjectMapper mapper = new ObjectMapper();
55 + ArrayNode result = mapper.createArrayNode();
56 + for (Path path : paths) {
57 + result.add(LinksListCommand.json(mapper, path)
58 + .put("cost", path.cost())
59 + .set("links", LinksListCommand.json(path.links())));
60 + }
61 + return result;
62 + }
39 63
40 /** 64 /**
41 * Produces a formatted string representing the specified path. 65 * Produces a formatted string representing the specified path.
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import com.fasterxml.jackson.databind.ObjectMapper;
3 import org.apache.karaf.shell.commands.Command; 4 import org.apache.karaf.shell.commands.Command;
4 import org.onlab.onos.cli.AbstractShellCommand; 5 import org.onlab.onos.cli.AbstractShellCommand;
5 import org.onlab.onos.net.topology.Topology; 6 import org.onlab.onos.net.topology.Topology;
...@@ -30,8 +31,17 @@ public class TopologyCommand extends AbstractShellCommand { ...@@ -30,8 +31,17 @@ public class TopologyCommand extends AbstractShellCommand {
30 @Override 31 @Override
31 protected void execute() { 32 protected void execute() {
32 init(); 33 init();
34 + if (outputJson()) {
35 + print("%s", new ObjectMapper().createObjectNode()
36 + .put("time", topology.time())
37 + .put("deviceCount", topology.deviceCount())
38 + .put("linkCount", topology.linkCount())
39 + .put("clusterCount", topology.clusterCount())
40 + .put("pathCount", topology.pathCount()));
41 + } else {
33 print(FMT, topology.time(), topology.deviceCount(), topology.linkCount(), 42 print(FMT, topology.time(), topology.deviceCount(), topology.linkCount(),
34 topology.clusterCount(), topology.pathCount()); 43 topology.clusterCount(), topology.pathCount());
35 } 44 }
45 + }
36 46
37 } 47 }
......
...@@ -12,8 +12,12 @@ public final class ControllerNodeToNodeId ...@@ -12,8 +12,12 @@ public final class ControllerNodeToNodeId
12 12
13 @Override 13 @Override
14 public NodeId apply(ControllerNode input) { 14 public NodeId apply(ControllerNode input) {
15 + if (input == null) {
16 + return null;
17 + } else {
15 return input.id(); 18 return input.id();
16 } 19 }
20 + }
17 21
18 /** 22 /**
19 * Returns a Function to convert ControllerNode to NodeId. 23 * Returns a Function to convert ControllerNode to NodeId.
......
1 package org.onlab.onos.net.host; 1 package org.onlab.onos.net.host;
2 2
3 +import java.util.Collections;
4 +import java.util.Set;
5 +
3 import org.onlab.onos.net.AbstractDescription; 6 import org.onlab.onos.net.AbstractDescription;
4 import org.onlab.onos.net.HostLocation; 7 import org.onlab.onos.net.HostLocation;
5 import org.onlab.onos.net.SparseAnnotations; 8 import org.onlab.onos.net.SparseAnnotations;
...@@ -7,6 +10,8 @@ import org.onlab.packet.IpPrefix; ...@@ -7,6 +10,8 @@ import org.onlab.packet.IpPrefix;
7 import org.onlab.packet.MacAddress; 10 import org.onlab.packet.MacAddress;
8 import org.onlab.packet.VlanId; 11 import org.onlab.packet.VlanId;
9 12
13 +import com.google.common.collect.ImmutableSet;
14 +
10 import static com.google.common.base.MoreObjects.toStringHelper; 15 import static com.google.common.base.MoreObjects.toStringHelper;
11 16
12 /** 17 /**
...@@ -18,7 +23,7 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -18,7 +23,7 @@ public class DefaultHostDescription extends AbstractDescription
18 private final MacAddress mac; 23 private final MacAddress mac;
19 private final VlanId vlan; 24 private final VlanId vlan;
20 private final HostLocation location; 25 private final HostLocation location;
21 - private final IpPrefix ip; 26 + private final Set<IpPrefix> ip;
22 27
23 /** 28 /**
24 * Creates a host description using the supplied information. 29 * Creates a host description using the supplied information.
...@@ -31,7 +36,7 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -31,7 +36,7 @@ public class DefaultHostDescription extends AbstractDescription
31 public DefaultHostDescription(MacAddress mac, VlanId vlan, 36 public DefaultHostDescription(MacAddress mac, VlanId vlan,
32 HostLocation location, 37 HostLocation location,
33 SparseAnnotations... annotations) { 38 SparseAnnotations... annotations) {
34 - this(mac, vlan, location, null, annotations); 39 + this(mac, vlan, location, Collections.<IpPrefix>emptySet(), annotations);
35 } 40 }
36 41
37 /** 42 /**
...@@ -46,11 +51,26 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -46,11 +51,26 @@ public class DefaultHostDescription extends AbstractDescription
46 public DefaultHostDescription(MacAddress mac, VlanId vlan, 51 public DefaultHostDescription(MacAddress mac, VlanId vlan,
47 HostLocation location, IpPrefix ip, 52 HostLocation location, IpPrefix ip,
48 SparseAnnotations... annotations) { 53 SparseAnnotations... annotations) {
54 + this(mac, vlan, location, ImmutableSet.of(ip), annotations);
55 + }
56 +
57 + /**
58 + * Creates a host description using the supplied information.
59 + *
60 + * @param mac host MAC address
61 + * @param vlan host VLAN identifier
62 + * @param location host location
63 + * @param ip host IP addresses
64 + * @param annotations optional key/value annotations map
65 + */
66 + public DefaultHostDescription(MacAddress mac, VlanId vlan,
67 + HostLocation location, Set<IpPrefix> ip,
68 + SparseAnnotations... annotations) {
49 super(annotations); 69 super(annotations);
50 this.mac = mac; 70 this.mac = mac;
51 this.vlan = vlan; 71 this.vlan = vlan;
52 this.location = location; 72 this.location = location;
53 - this.ip = ip; 73 + this.ip = ImmutableSet.copyOf(ip);
54 } 74 }
55 75
56 @Override 76 @Override
...@@ -69,7 +89,7 @@ public class DefaultHostDescription extends AbstractDescription ...@@ -69,7 +89,7 @@ public class DefaultHostDescription extends AbstractDescription
69 } 89 }
70 90
71 @Override 91 @Override
72 - public IpPrefix ipAddress() { 92 + public Set<IpPrefix> ipAddress() {
73 return ip; 93 return ip;
74 } 94 }
75 95
......
1 package org.onlab.onos.net.host; 1 package org.onlab.onos.net.host;
2 2
3 +import java.util.Set;
4 +
3 import org.onlab.onos.net.Description; 5 import org.onlab.onos.net.Description;
4 import org.onlab.onos.net.HostLocation; 6 import org.onlab.onos.net.HostLocation;
5 import org.onlab.packet.IpPrefix; 7 import org.onlab.packet.IpPrefix;
...@@ -38,6 +40,6 @@ public interface HostDescription extends Description { ...@@ -38,6 +40,6 @@ public interface HostDescription extends Description {
38 * @return host IP address 40 * @return host IP address
39 */ 41 */
40 // FIXME: Switch to IpAddress 42 // FIXME: Switch to IpAddress
41 - IpPrefix ipAddress(); 43 + Set<IpPrefix> ipAddress();
42 44
43 } 45 }
......
1 package org.onlab.onos.cluster; 1 package org.onlab.onos.cluster;
2 2
3 +import static com.google.common.base.Predicates.notNull;
3 import static org.junit.Assert.*; 4 import static org.junit.Assert.*;
4 import static org.onlab.onos.cluster.ControllerNodeToNodeId.toNodeId; 5 import static org.onlab.onos.cluster.ControllerNodeToNodeId.toNodeId;
5 6
...@@ -30,12 +31,13 @@ public class ControllerNodeToNodeIdTest { ...@@ -30,12 +31,13 @@ public class ControllerNodeToNodeIdTest {
30 @Test 31 @Test
31 public final void testToNodeId() { 32 public final void testToNodeId() {
32 33
33 - final Iterable<ControllerNode> nodes = Arrays.asList(CN1, CN2, CN3); 34 + final Iterable<ControllerNode> nodes = Arrays.asList(CN1, CN2, CN3, null);
34 final List<NodeId> nodeIds = Arrays.asList(NID1, NID2, NID3); 35 final List<NodeId> nodeIds = Arrays.asList(NID1, NID2, NID3);
35 36
36 assertEquals(nodeIds, 37 assertEquals(nodeIds,
37 FluentIterable.from(nodes) 38 FluentIterable.from(nodes)
38 .transform(toNodeId()) 39 .transform(toNodeId())
40 + .filter(notNull())
39 .toList()); 41 .toList());
40 } 42 }
41 43
......
...@@ -8,6 +8,8 @@ import org.onlab.packet.IpPrefix; ...@@ -8,6 +8,8 @@ import org.onlab.packet.IpPrefix;
8 import org.onlab.packet.MacAddress; 8 import org.onlab.packet.MacAddress;
9 import org.onlab.packet.VlanId; 9 import org.onlab.packet.VlanId;
10 10
11 +import com.google.common.collect.ImmutableSet;
12 +
11 import static org.junit.Assert.assertEquals; 13 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertTrue; 14 import static org.junit.Assert.assertTrue;
13 15
...@@ -33,7 +35,7 @@ public class DefualtHostDecriptionTest { ...@@ -33,7 +35,7 @@ public class DefualtHostDecriptionTest {
33 assertEquals("incorrect mac", MAC, host.hwAddress()); 35 assertEquals("incorrect mac", MAC, host.hwAddress());
34 assertEquals("incorrect vlan", VLAN, host.vlan()); 36 assertEquals("incorrect vlan", VLAN, host.vlan());
35 assertEquals("incorrect location", LOC, host.location()); 37 assertEquals("incorrect location", LOC, host.location());
36 - assertEquals("incorrect ip's", IP, host.ipAddress()); 38 + assertEquals("incorrect ip's", ImmutableSet.of(IP), host.ipAddress());
37 assertTrue("incorrect toString", host.toString().contains("vlan=10")); 39 assertTrue("incorrect toString", host.toString().contains("vlan=10"));
38 } 40 }
39 41
......
1 /** 1 /**
2 - * 2 + * Miscellaneous core system implementations.
3 */ 3 */
4 package org.onlab.onos.impl; 4 package org.onlab.onos.impl;
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -355,7 +355,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -355,7 +355,7 @@ public class ProxyArpManager implements ProxyArpService {
355 355
356 arp.setTargetProtocolAddress(((ARP) request.getPayload()) 356 arp.setTargetProtocolAddress(((ARP) request.getPayload())
357 .getSenderProtocolAddress()); 357 .getSenderProtocolAddress());
358 - arp.setSenderProtocolAddress(srcIp.toRealInt()); 358 + arp.setSenderProtocolAddress(srcIp.toInt());
359 eth.setPayload(arp); 359 eth.setPayload(arp);
360 return eth; 360 return eth;
361 } 361 }
......
...@@ -515,12 +515,12 @@ public class GossipDeviceStore ...@@ -515,12 +515,12 @@ public class GossipDeviceStore
515 Map<PortNumber, Port> ports, 515 Map<PortNumber, Port> ports,
516 Set<PortNumber> processed) { 516 Set<PortNumber> processed) {
517 List<DeviceEvent> events = new ArrayList<>(); 517 List<DeviceEvent> events = new ArrayList<>();
518 - Iterator<PortNumber> iterator = ports.keySet().iterator(); 518 + Iterator<Entry<PortNumber, Port>> iterator = ports.entrySet().iterator();
519 while (iterator.hasNext()) { 519 while (iterator.hasNext()) {
520 - PortNumber portNumber = iterator.next(); 520 + Entry<PortNumber, Port> e = iterator.next();
521 + PortNumber portNumber = e.getKey();
521 if (!processed.contains(portNumber)) { 522 if (!processed.contains(portNumber)) {
522 - events.add(new DeviceEvent(PORT_REMOVED, device, 523 + events.add(new DeviceEvent(PORT_REMOVED, device, e.getValue()));
523 - ports.get(portNumber)));
524 iterator.remove(); 524 iterator.remove();
525 } 525 }
526 } 526 }
......
...@@ -4,6 +4,11 @@ import org.onlab.onos.store.cluster.messaging.MessageSubject; ...@@ -4,6 +4,11 @@ import org.onlab.onos.store.cluster.messaging.MessageSubject;
4 4
5 public final class GossipHostStoreMessageSubjects { 5 public final class GossipHostStoreMessageSubjects {
6 private GossipHostStoreMessageSubjects() {} 6 private GossipHostStoreMessageSubjects() {}
7 - public static final MessageSubject HOST_UPDATED = new MessageSubject("peer-host-updated"); 7 +
8 - public static final MessageSubject HOST_REMOVED = new MessageSubject("peer-host-removed"); 8 + public static final MessageSubject HOST_UPDATED
9 + = new MessageSubject("peer-host-updated");
10 + public static final MessageSubject HOST_REMOVED
11 + = new MessageSubject("peer-host-removed");
12 + public static final MessageSubject HOST_ANTI_ENTROPY_ADVERTISEMENT
13 + = new MessageSubject("host-enti-entropy-advertisement");;
9 } 14 }
......
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +
5 +import java.util.Map;
6 +
7 +import org.onlab.onos.cluster.NodeId;
8 +import org.onlab.onos.net.HostId;
9 +import org.onlab.onos.store.Timestamp;
10 +
11 +/**
12 + * Host AE Advertisement message.
13 + */
14 +public final class HostAntiEntropyAdvertisement {
15 +
16 + private final NodeId sender;
17 + private final Map<HostFragmentId, Timestamp> timestamps;
18 + private final Map<HostId, Timestamp> tombstones;
19 +
20 +
21 + public HostAntiEntropyAdvertisement(NodeId sender,
22 + Map<HostFragmentId, Timestamp> timestamps,
23 + Map<HostId, Timestamp> tombstones) {
24 + this.sender = checkNotNull(sender);
25 + this.timestamps = checkNotNull(timestamps);
26 + this.tombstones = checkNotNull(tombstones);
27 + }
28 +
29 + public NodeId sender() {
30 + return sender;
31 + }
32 +
33 + public Map<HostFragmentId, Timestamp> timestamps() {
34 + return timestamps;
35 + }
36 +
37 + public Map<HostId, Timestamp> tombstones() {
38 + return tombstones;
39 + }
40 +
41 + // For serializer
42 + @SuppressWarnings("unused")
43 + private HostAntiEntropyAdvertisement() {
44 + this.sender = null;
45 + this.timestamps = null;
46 + this.tombstones = null;
47 + }
48 +}
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import java.util.Objects;
4 +
5 +import org.onlab.onos.net.HostId;
6 +import org.onlab.onos.net.provider.ProviderId;
7 +
8 +import com.google.common.base.MoreObjects;
9 +
10 +/**
11 + * Identifier for HostDescription from a Provider.
12 + */
13 +public final class HostFragmentId {
14 + public final ProviderId providerId;
15 + public final HostId hostId;
16 +
17 + public HostFragmentId(HostId hostId, ProviderId providerId) {
18 + this.providerId = providerId;
19 + this.hostId = hostId;
20 + }
21 +
22 + public HostId hostId() {
23 + return hostId;
24 + }
25 +
26 + public ProviderId providerId() {
27 + return providerId;
28 + }
29 +
30 + @Override
31 + public int hashCode() {
32 + return Objects.hash(providerId, hostId);
33 + }
34 +
35 + @Override
36 + public boolean equals(Object obj) {
37 + if (this == obj) {
38 + return true;
39 + }
40 + if (!(obj instanceof HostFragmentId)) {
41 + return false;
42 + }
43 + HostFragmentId that = (HostFragmentId) obj;
44 + return Objects.equals(this.hostId, that.hostId) &&
45 + Objects.equals(this.providerId, that.providerId);
46 + }
47 +
48 + @Override
49 + public String toString() {
50 + return MoreObjects.toStringHelper(getClass())
51 + .add("providerId", providerId)
52 + .add("hostId", hostId)
53 + .toString();
54 + }
55 +
56 + // for serializer
57 + @SuppressWarnings("unused")
58 + private HostFragmentId() {
59 + this.providerId = null;
60 + this.hostId = null;
61 + }
62 +}
1 +/**
2 + * Implementation of host store using distributed p2p synchronization protocol.
3 + */
4 +package org.onlab.onos.store.host.impl;
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<project xmlns="http://maven.apache.org/POM/4.0.0"
3 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 - <modelVersion>4.0.0</modelVersion>
6 -
7 - <parent>
8 - <groupId>org.onlab.onos</groupId>
9 - <artifactId>onos-core-hz</artifactId>
10 - <version>1.0.0-SNAPSHOT</version>
11 - <relativePath>../pom.xml</relativePath>
12 - </parent>
13 -
14 - <artifactId>onos-core-hz-net</artifactId>
15 - <packaging>bundle</packaging>
16 -
17 - <description>ONOS Hazelcast based distributed store subsystems</description>
18 -
19 - <dependencies>
20 - <dependency>
21 - <groupId>org.onlab.onos</groupId>
22 - <artifactId>onos-api</artifactId>
23 - </dependency>
24 - <dependency>
25 - <groupId>org.onlab.onos</groupId>
26 - <artifactId>onos-core-hz-common</artifactId>
27 - <version>${project.version}</version>
28 - </dependency>
29 - <dependency>
30 - <groupId>org.onlab.onos</groupId>
31 - <artifactId>onos-core-hz-common</artifactId>
32 - <classifier>tests</classifier>
33 - <scope>test</scope>
34 - <version>${project.version}</version>
35 - </dependency>
36 - <dependency>
37 - <groupId>org.apache.felix</groupId>
38 - <artifactId>org.apache.felix.scr.annotations</artifactId>
39 - </dependency>
40 - <dependency>
41 - <groupId>com.hazelcast</groupId>
42 - <artifactId>hazelcast</artifactId>
43 - </dependency>
44 - </dependencies>
45 -
46 - <build>
47 - <plugins>
48 - <plugin>
49 - <groupId>org.apache.felix</groupId>
50 - <artifactId>maven-scr-plugin</artifactId>
51 - </plugin>
52 - </plugins>
53 - </build>
54 -
55 -</project>
1 -package org.onlab.onos.store.device.impl;
2 -
3 -import org.apache.felix.scr.annotations.Component;
4 -import org.apache.felix.scr.annotations.Service;
5 -import org.onlab.onos.mastership.MastershipTerm;
6 -import org.onlab.onos.net.DeviceId;
7 -import org.onlab.onos.net.device.DeviceClockProviderService;
8 -
9 -// FIXME: Code clone in onos-core-trivial, onos-core-hz-net
10 -/**
11 - * Dummy implementation of {@link DeviceClockProviderService}.
12 - */
13 -@Component(immediate = true)
14 -@Service
15 -public class NoOpClockProviderService implements DeviceClockProviderService {
16 -
17 - @Override
18 - public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
19 - }
20 -}
1 -package org.onlab.onos.store.flow.impl;
2 -
3 -import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
4 -import static org.slf4j.LoggerFactory.getLogger;
5 -
6 -import java.util.Collection;
7 -import java.util.Collections;
8 -
9 -import org.apache.felix.scr.annotations.Activate;
10 -import org.apache.felix.scr.annotations.Component;
11 -import org.apache.felix.scr.annotations.Deactivate;
12 -import org.apache.felix.scr.annotations.Service;
13 -import org.onlab.onos.ApplicationId;
14 -import org.onlab.onos.net.DeviceId;
15 -import org.onlab.onos.net.flow.DefaultFlowEntry;
16 -import org.onlab.onos.net.flow.FlowEntry;
17 -import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
18 -import org.onlab.onos.net.flow.FlowRule;
19 -import org.onlab.onos.net.flow.FlowRuleEvent;
20 -import org.onlab.onos.net.flow.FlowRuleEvent.Type;
21 -import org.onlab.onos.net.flow.FlowRuleStore;
22 -import org.onlab.onos.net.flow.FlowRuleStoreDelegate;
23 -import org.onlab.onos.store.AbstractStore;
24 -import org.slf4j.Logger;
25 -
26 -import com.google.common.collect.ArrayListMultimap;
27 -import com.google.common.collect.ImmutableSet;
28 -import com.google.common.collect.Multimap;
29 -
30 -/**
31 - * Manages inventory of flow rules using trivial in-memory implementation.
32 - */
33 -//FIXME I LIE. I AIN'T DISTRIBUTED
34 -@Component(immediate = true)
35 -@Service
36 -public class DistributedFlowRuleStore
37 - extends AbstractStore<FlowRuleEvent, FlowRuleStoreDelegate>
38 - implements FlowRuleStore {
39 -
40 - private final Logger log = getLogger(getClass());
41 -
42 - // store entries as a pile of rules, no info about device tables
43 - private final Multimap<DeviceId, FlowEntry> flowEntries =
44 - ArrayListMultimap.<DeviceId, FlowEntry>create();
45 -
46 - private final Multimap<Short, FlowRule> flowEntriesById =
47 - ArrayListMultimap.<Short, FlowRule>create();
48 -
49 - @Activate
50 - public void activate() {
51 - log.info("Started");
52 - }
53 -
54 - @Deactivate
55 - public void deactivate() {
56 - log.info("Stopped");
57 - }
58 -
59 -
60 - @Override
61 - public int getFlowRuleCount() {
62 - return flowEntries.size();
63 - }
64 -
65 - @Override
66 - public synchronized FlowEntry getFlowEntry(FlowRule rule) {
67 - for (FlowEntry f : flowEntries.get(rule.deviceId())) {
68 - if (f.equals(rule)) {
69 - return f;
70 - }
71 - }
72 - return null;
73 - }
74 -
75 - @Override
76 - public synchronized Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
77 - Collection<FlowEntry> rules = flowEntries.get(deviceId);
78 - if (rules == null) {
79 - return Collections.emptyList();
80 - }
81 - return ImmutableSet.copyOf(rules);
82 - }
83 -
84 - @Override
85 - public synchronized Iterable<FlowRule> getFlowRulesByAppId(ApplicationId appId) {
86 - Collection<FlowRule> rules = flowEntriesById.get(appId.id());
87 - if (rules == null) {
88 - return Collections.emptyList();
89 - }
90 - return ImmutableSet.copyOf(rules);
91 - }
92 -
93 - @Override
94 - public synchronized void storeFlowRule(FlowRule rule) {
95 - FlowEntry f = new DefaultFlowEntry(rule);
96 - DeviceId did = f.deviceId();
97 - if (!flowEntries.containsEntry(did, f)) {
98 - flowEntries.put(did, f);
99 - flowEntriesById.put(rule.appId(), f);
100 - }
101 - }
102 -
103 - @Override
104 - public synchronized void deleteFlowRule(FlowRule rule) {
105 - FlowEntry entry = getFlowEntry(rule);
106 - if (entry == null) {
107 - return;
108 - }
109 - entry.setState(FlowEntryState.PENDING_REMOVE);
110 - }
111 -
112 - @Override
113 - public synchronized FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule) {
114 - DeviceId did = rule.deviceId();
115 -
116 - // check if this new rule is an update to an existing entry
117 - FlowEntry stored = getFlowEntry(rule);
118 - if (stored != null) {
119 - stored.setBytes(rule.bytes());
120 - stored.setLife(rule.life());
121 - stored.setPackets(rule.packets());
122 - if (stored.state() == FlowEntryState.PENDING_ADD) {
123 - stored.setState(FlowEntryState.ADDED);
124 - return new FlowRuleEvent(Type.RULE_ADDED, rule);
125 - }
126 - return new FlowRuleEvent(Type.RULE_UPDATED, rule);
127 - }
128 -
129 - flowEntries.put(did, rule);
130 - return null;
131 - }
132 -
133 - @Override
134 - public synchronized FlowRuleEvent removeFlowRule(FlowEntry rule) {
135 - // This is where one could mark a rule as removed and still keep it in the store.
136 - if (flowEntries.remove(rule.deviceId(), rule)) {
137 - return new FlowRuleEvent(RULE_REMOVED, rule);
138 - } else {
139 - return null;
140 - }
141 - }
142 -}
1 -package org.onlab.onos.store.host.impl;
2 -
3 -import com.google.common.collect.HashMultimap;
4 -import com.google.common.collect.ImmutableSet;
5 -import com.google.common.collect.Multimap;
6 -import com.google.common.collect.Sets;
7 -import org.apache.felix.scr.annotations.Activate;
8 -import org.apache.felix.scr.annotations.Component;
9 -import org.apache.felix.scr.annotations.Deactivate;
10 -import org.apache.felix.scr.annotations.Service;
11 -import org.onlab.onos.net.Annotations;
12 -import org.onlab.onos.net.ConnectPoint;
13 -import org.onlab.onos.net.DefaultHost;
14 -import org.onlab.onos.net.DeviceId;
15 -import org.onlab.onos.net.Host;
16 -import org.onlab.onos.net.HostId;
17 -import org.onlab.onos.net.HostLocation;
18 -import org.onlab.onos.net.host.HostDescription;
19 -import org.onlab.onos.net.host.HostEvent;
20 -import org.onlab.onos.net.host.HostStore;
21 -import org.onlab.onos.net.host.HostStoreDelegate;
22 -import org.onlab.onos.net.host.PortAddresses;
23 -import org.onlab.onos.net.provider.ProviderId;
24 -import org.onlab.onos.store.AbstractStore;
25 -import org.onlab.packet.IpPrefix;
26 -import org.onlab.packet.MacAddress;
27 -import org.onlab.packet.VlanId;
28 -import org.slf4j.Logger;
29 -
30 -import java.util.HashSet;
31 -import java.util.Map;
32 -import java.util.Set;
33 -import java.util.concurrent.ConcurrentHashMap;
34 -
35 -import static org.onlab.onos.net.host.HostEvent.Type.*;
36 -import static org.slf4j.LoggerFactory.getLogger;
37 -
38 -/**
39 - * TEMPORARY: Manages inventory of end-station hosts using distributed
40 - * structures implementation.
41 - */
42 -//FIXME: I LIE I AM NOT DISTRIBUTED
43 -@Component(immediate = true)
44 -@Service
45 -public class DistributedHostStore
46 - extends AbstractStore<HostEvent, HostStoreDelegate>
47 - implements HostStore {
48 -
49 - private final Logger log = getLogger(getClass());
50 -
51 - // Host inventory
52 - private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
53 -
54 - // Hosts tracked by their location
55 - private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
56 -
57 - private final Map<ConnectPoint, PortAddresses> portAddresses =
58 - new ConcurrentHashMap<>();
59 -
60 - @Activate
61 - public void activate() {
62 - log.info("Started");
63 - }
64 -
65 - @Deactivate
66 - public void deactivate() {
67 - log.info("Stopped");
68 - }
69 -
70 - @Override
71 - public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
72 - HostDescription hostDescription) {
73 - StoredHost host = hosts.get(hostId);
74 - if (host == null) {
75 - return createHost(providerId, hostId, hostDescription);
76 - }
77 - return updateHost(providerId, host, hostDescription);
78 - }
79 -
80 - // creates a new host and sends HOST_ADDED
81 - private HostEvent createHost(ProviderId providerId, HostId hostId,
82 - HostDescription descr) {
83 - StoredHost newhost = new StoredHost(providerId, hostId,
84 - descr.hwAddress(),
85 - descr.vlan(),
86 - descr.location(),
87 - ImmutableSet.of(descr.ipAddress()));
88 - synchronized (this) {
89 - hosts.put(hostId, newhost);
90 - locations.put(descr.location(), newhost);
91 - }
92 - return new HostEvent(HOST_ADDED, newhost);
93 - }
94 -
95 - // checks for type of update to host, sends appropriate event
96 - private HostEvent updateHost(ProviderId providerId, StoredHost host,
97 - HostDescription descr) {
98 - HostEvent event;
99 - if (!host.location().equals(descr.location())) {
100 - host.setLocation(descr.location());
101 - return new HostEvent(HOST_MOVED, host);
102 - }
103 -
104 - if (host.ipAddresses().contains(descr.ipAddress())) {
105 - return null;
106 - }
107 -
108 - Set<IpPrefix> addresses = new HashSet<>(host.ipAddresses());
109 - addresses.add(descr.ipAddress());
110 - StoredHost updated = new StoredHost(providerId, host.id(),
111 - host.mac(), host.vlan(),
112 - descr.location(), addresses);
113 - event = new HostEvent(HOST_UPDATED, updated);
114 - synchronized (this) {
115 - hosts.put(host.id(), updated);
116 - locations.remove(host.location(), host);
117 - locations.put(updated.location(), updated);
118 - }
119 - return event;
120 - }
121 -
122 - @Override
123 - public HostEvent removeHost(HostId hostId) {
124 - synchronized (this) {
125 - Host host = hosts.remove(hostId);
126 - if (host != null) {
127 - locations.remove((host.location()), host);
128 - return new HostEvent(HOST_REMOVED, host);
129 - }
130 - return null;
131 - }
132 - }
133 -
134 - @Override
135 - public int getHostCount() {
136 - return hosts.size();
137 - }
138 -
139 - @Override
140 - public Iterable<Host> getHosts() {
141 - return ImmutableSet.<Host>copyOf(hosts.values());
142 - }
143 -
144 - @Override
145 - public Host getHost(HostId hostId) {
146 - return hosts.get(hostId);
147 - }
148 -
149 - @Override
150 - public Set<Host> getHosts(VlanId vlanId) {
151 - Set<Host> vlanset = new HashSet<>();
152 - for (Host h : hosts.values()) {
153 - if (h.vlan().equals(vlanId)) {
154 - vlanset.add(h);
155 - }
156 - }
157 - return vlanset;
158 - }
159 -
160 - @Override
161 - public Set<Host> getHosts(MacAddress mac) {
162 - Set<Host> macset = new HashSet<>();
163 - for (Host h : hosts.values()) {
164 - if (h.mac().equals(mac)) {
165 - macset.add(h);
166 - }
167 - }
168 - return macset;
169 - }
170 -
171 - @Override
172 - public Set<Host> getHosts(IpPrefix ip) {
173 - Set<Host> ipset = new HashSet<>();
174 - for (Host h : hosts.values()) {
175 - if (h.ipAddresses().contains(ip)) {
176 - ipset.add(h);
177 - }
178 - }
179 - return ipset;
180 - }
181 -
182 - @Override
183 - public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
184 - return ImmutableSet.copyOf(locations.get(connectPoint));
185 - }
186 -
187 - @Override
188 - public Set<Host> getConnectedHosts(DeviceId deviceId) {
189 - Set<Host> hostset = new HashSet<>();
190 - for (ConnectPoint p : locations.keySet()) {
191 - if (p.deviceId().equals(deviceId)) {
192 - hostset.addAll(locations.get(p));
193 - }
194 - }
195 - return hostset;
196 - }
197 -
198 - @Override
199 - public void updateAddressBindings(PortAddresses addresses) {
200 - synchronized (portAddresses) {
201 - PortAddresses existing = portAddresses.get(addresses.connectPoint());
202 - if (existing == null) {
203 - portAddresses.put(addresses.connectPoint(), addresses);
204 - } else {
205 - Set<IpPrefix> union = Sets.union(existing.ips(), addresses.ips())
206 - .immutableCopy();
207 -
208 - MacAddress newMac = (addresses.mac() == null) ? existing.mac()
209 - : addresses.mac();
210 -
211 - PortAddresses newAddresses =
212 - new PortAddresses(addresses.connectPoint(), union, newMac);
213 -
214 - portAddresses.put(newAddresses.connectPoint(), newAddresses);
215 - }
216 - }
217 - }
218 -
219 - @Override
220 - public void removeAddressBindings(PortAddresses addresses) {
221 - synchronized (portAddresses) {
222 - PortAddresses existing = portAddresses.get(addresses.connectPoint());
223 - if (existing != null) {
224 - Set<IpPrefix> difference =
225 - Sets.difference(existing.ips(), addresses.ips()).immutableCopy();
226 -
227 - // If they removed the existing mac, set the new mac to null.
228 - // Otherwise, keep the existing mac.
229 - MacAddress newMac = existing.mac();
230 - if (addresses.mac() != null && addresses.mac().equals(existing.mac())) {
231 - newMac = null;
232 - }
233 -
234 - PortAddresses newAddresses =
235 - new PortAddresses(addresses.connectPoint(), difference, newMac);
236 -
237 - portAddresses.put(newAddresses.connectPoint(), newAddresses);
238 - }
239 - }
240 - }
241 -
242 - @Override
243 - public void clearAddressBindings(ConnectPoint connectPoint) {
244 - synchronized (portAddresses) {
245 - portAddresses.remove(connectPoint);
246 - }
247 - }
248 -
249 - @Override
250 - public Set<PortAddresses> getAddressBindings() {
251 - synchronized (portAddresses) {
252 - return new HashSet<>(portAddresses.values());
253 - }
254 - }
255 -
256 - @Override
257 - public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) {
258 - PortAddresses addresses;
259 -
260 - synchronized (portAddresses) {
261 - addresses = portAddresses.get(connectPoint);
262 - }
263 -
264 - if (addresses == null) {
265 - addresses = new PortAddresses(connectPoint, null, null);
266 - }
267 -
268 - return addresses;
269 - }
270 -
271 - // Auxiliary extension to allow location to mutate.
272 - private class StoredHost extends DefaultHost {
273 - private HostLocation location;
274 -
275 - /**
276 - * Creates an end-station host using the supplied information.
277 - *
278 - * @param providerId provider identity
279 - * @param id host identifier
280 - * @param mac host MAC address
281 - * @param vlan host VLAN identifier
282 - * @param location host location
283 - * @param ips host IP addresses
284 - * @param annotations optional key/value annotations
285 - */
286 - public StoredHost(ProviderId providerId, HostId id,
287 - MacAddress mac, VlanId vlan, HostLocation location,
288 - Set<IpPrefix> ips, Annotations... annotations) {
289 - super(providerId, id, mac, vlan, location, ips, annotations);
290 - this.location = location;
291 - }
292 -
293 - void setLocation(HostLocation location) {
294 - this.location = location;
295 - }
296 -
297 - @Override
298 - public HostLocation location() {
299 - return location;
300 - }
301 - }
302 -}
1 -package org.onlab.onos.store.link.impl;
2 -
3 -import static com.google.common.cache.CacheBuilder.newBuilder;
4 -import static org.onlab.onos.net.Link.Type.DIRECT;
5 -import static org.onlab.onos.net.Link.Type.INDIRECT;
6 -import static org.onlab.onos.net.LinkKey.linkKey;
7 -import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
8 -import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
9 -import static org.onlab.onos.net.link.LinkEvent.Type.LINK_UPDATED;
10 -import static org.slf4j.LoggerFactory.getLogger;
11 -
12 -import java.util.HashSet;
13 -import java.util.Set;
14 -
15 -import org.apache.felix.scr.annotations.Activate;
16 -import org.apache.felix.scr.annotations.Component;
17 -import org.apache.felix.scr.annotations.Deactivate;
18 -import org.apache.felix.scr.annotations.Service;
19 -import org.onlab.onos.net.ConnectPoint;
20 -import org.onlab.onos.net.DefaultLink;
21 -import org.onlab.onos.net.DeviceId;
22 -import org.onlab.onos.net.Link;
23 -import org.onlab.onos.net.LinkKey;
24 -import org.onlab.onos.net.link.LinkDescription;
25 -import org.onlab.onos.net.link.LinkEvent;
26 -import org.onlab.onos.net.link.LinkStore;
27 -import org.onlab.onos.net.link.LinkStoreDelegate;
28 -import org.onlab.onos.net.provider.ProviderId;
29 -import org.onlab.onos.store.common.AbsentInvalidatingLoadingCache;
30 -import org.onlab.onos.store.common.AbstractHazelcastStore;
31 -import org.onlab.onos.store.common.OptionalCacheLoader;
32 -import org.slf4j.Logger;
33 -
34 -import com.google.common.base.Optional;
35 -import com.google.common.cache.LoadingCache;
36 -import com.google.common.collect.HashMultimap;
37 -import com.google.common.collect.ImmutableSet;
38 -import com.google.common.collect.Multimap;
39 -import com.google.common.collect.ImmutableSet.Builder;
40 -import com.hazelcast.core.IMap;
41 -
42 -//TODO: Add support for multiple provider and annotations
43 -/**
44 - * Manages inventory of infrastructure links using Hazelcast-backed map.
45 - */
46 -@Component(immediate = true)
47 -@Service
48 -public class DistributedLinkStore
49 - extends AbstractHazelcastStore<LinkEvent, LinkStoreDelegate>
50 - implements LinkStore {
51 -
52 - private final Logger log = getLogger(getClass());
53 -
54 - // Link inventory
55 - private IMap<byte[], byte[]> rawLinks;
56 - private LoadingCache<LinkKey, Optional<DefaultLink>> links;
57 -
58 - // TODO synchronize?
59 - // Egress and ingress link sets
60 - private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create();
61 - private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create();
62 -
63 - private String linksListener;
64 -
65 - @Override
66 - @Activate
67 - public void activate() {
68 - super.activate();
69 -
70 - boolean includeValue = true;
71 -
72 - // TODO decide on Map name scheme to avoid collision
73 - rawLinks = theInstance.getMap("links");
74 - final OptionalCacheLoader<LinkKey, DefaultLink> linkLoader
75 - = new OptionalCacheLoader<>(serializer, rawLinks);
76 - links = new AbsentInvalidatingLoadingCache<>(newBuilder().build(linkLoader));
77 - // refresh/populate cache based on notification from other instance
78 - linksListener = rawLinks.addEntryListener(new RemoteLinkEventHandler(links), includeValue);
79 -
80 - loadLinkCache();
81 -
82 - log.info("Started");
83 - }
84 -
85 - @Deactivate
86 - public void deactivate() {
87 - rawLinks.removeEntryListener(linksListener);
88 - log.info("Stopped");
89 - }
90 -
91 - private void loadLinkCache() {
92 - for (byte[] keyBytes : rawLinks.keySet()) {
93 - final LinkKey id = deserialize(keyBytes);
94 - links.refresh(id);
95 - }
96 - }
97 -
98 - @Override
99 - public int getLinkCount() {
100 - return links.asMap().size();
101 - }
102 -
103 - @Override
104 - public Iterable<Link> getLinks() {
105 - Builder<Link> builder = ImmutableSet.builder();
106 - for (Optional<DefaultLink> e : links.asMap().values()) {
107 - if (e.isPresent()) {
108 - builder.add(e.get());
109 - }
110 - }
111 - return builder.build();
112 - }
113 -
114 - @Override
115 - public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
116 - return ImmutableSet.copyOf(srcLinks.get(deviceId));
117 - }
118 -
119 - @Override
120 - public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
121 - return ImmutableSet.copyOf(dstLinks.get(deviceId));
122 - }
123 -
124 - @Override
125 - public Link getLink(ConnectPoint src, ConnectPoint dst) {
126 - return links.getUnchecked(linkKey(src, dst)).orNull();
127 - }
128 -
129 - @Override
130 - public Set<Link> getEgressLinks(ConnectPoint src) {
131 - Set<Link> egress = new HashSet<>();
132 - for (Link link : srcLinks.get(src.deviceId())) {
133 - if (link.src().equals(src)) {
134 - egress.add(link);
135 - }
136 - }
137 - return egress;
138 - }
139 -
140 - @Override
141 - public Set<Link> getIngressLinks(ConnectPoint dst) {
142 - Set<Link> ingress = new HashSet<>();
143 - for (Link link : dstLinks.get(dst.deviceId())) {
144 - if (link.dst().equals(dst)) {
145 - ingress.add(link);
146 - }
147 - }
148 - return ingress;
149 - }
150 -
151 - @Override
152 - public LinkEvent createOrUpdateLink(ProviderId providerId,
153 - LinkDescription linkDescription) {
154 - LinkKey key = linkKey(linkDescription.src(), linkDescription.dst());
155 - Optional<DefaultLink> link = links.getUnchecked(key);
156 - if (!link.isPresent()) {
157 - return createLink(providerId, key, linkDescription);
158 - }
159 - return updateLink(providerId, link.get(), key, linkDescription);
160 - }
161 -
162 - // Creates and stores the link and returns the appropriate event.
163 - private LinkEvent createLink(ProviderId providerId, LinkKey key,
164 - LinkDescription linkDescription) {
165 - DefaultLink link = new DefaultLink(providerId, key.src(), key.dst(),
166 - linkDescription.type());
167 - synchronized (this) {
168 - final byte[] keyBytes = serialize(key);
169 - rawLinks.put(keyBytes, serialize(link));
170 - links.asMap().putIfAbsent(key, Optional.of(link));
171 -
172 - addNewLink(link);
173 - }
174 - return new LinkEvent(LINK_ADDED, link);
175 - }
176 -
177 - // update Egress and ingress link sets
178 - private void addNewLink(DefaultLink link) {
179 - synchronized (this) {
180 - srcLinks.put(link.src().deviceId(), link);
181 - dstLinks.put(link.dst().deviceId(), link);
182 - }
183 - }
184 -
185 - // Updates, if necessary the specified link and returns the appropriate event.
186 - private LinkEvent updateLink(ProviderId providerId, DefaultLink link,
187 - LinkKey key, LinkDescription linkDescription) {
188 - // FIXME confirm Link update condition is OK
189 - if (link.type() == INDIRECT && linkDescription.type() == DIRECT) {
190 - synchronized (this) {
191 -
192 - DefaultLink updated =
193 - new DefaultLink(providerId, link.src(), link.dst(),
194 - linkDescription.type());
195 - final byte[] keyBytes = serialize(key);
196 - rawLinks.put(keyBytes, serialize(updated));
197 - links.asMap().replace(key, Optional.of(link), Optional.of(updated));
198 -
199 - replaceLink(link, updated);
200 - return new LinkEvent(LINK_UPDATED, updated);
201 - }
202 - }
203 - return null;
204 - }
205 -
206 - // update Egress and ingress link sets
207 - private void replaceLink(DefaultLink link, DefaultLink updated) {
208 - synchronized (this) {
209 - srcLinks.remove(link.src().deviceId(), link);
210 - dstLinks.remove(link.dst().deviceId(), link);
211 -
212 - srcLinks.put(link.src().deviceId(), updated);
213 - dstLinks.put(link.dst().deviceId(), updated);
214 - }
215 - }
216 -
217 - @Override
218 - public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
219 - synchronized (this) {
220 - LinkKey key = linkKey(src, dst);
221 - byte[] keyBytes = serialize(key);
222 - Link link = deserialize(rawLinks.remove(keyBytes));
223 - links.invalidate(key);
224 - if (link != null) {
225 - removeLink(link);
226 - return new LinkEvent(LINK_REMOVED, link);
227 - }
228 - return null;
229 - }
230 - }
231 -
232 - // update Egress and ingress link sets
233 - private void removeLink(Link link) {
234 - synchronized (this) {
235 - srcLinks.remove(link.src().deviceId(), link);
236 - dstLinks.remove(link.dst().deviceId(), link);
237 - }
238 - }
239 -
240 - private class RemoteLinkEventHandler extends RemoteCacheEventHandler<LinkKey, DefaultLink> {
241 - public RemoteLinkEventHandler(LoadingCache<LinkKey, Optional<DefaultLink>> cache) {
242 - super(cache);
243 - }
244 -
245 - @Override
246 - protected void onAdd(LinkKey key, DefaultLink newVal) {
247 - addNewLink(newVal);
248 - notifyDelegate(new LinkEvent(LINK_ADDED, newVal));
249 - }
250 -
251 - @Override
252 - protected void onUpdate(LinkKey key, DefaultLink oldVal, DefaultLink newVal) {
253 - replaceLink(oldVal, newVal);
254 - notifyDelegate(new LinkEvent(LINK_UPDATED, newVal));
255 - }
256 -
257 - @Override
258 - protected void onRemove(LinkKey key, DefaultLink val) {
259 - removeLink(val);
260 - notifyDelegate(new LinkEvent(LINK_REMOVED, val));
261 - }
262 - }
263 -}
1 -package org.onlab.onos.store.topology.impl;
2 -
3 -import org.onlab.graph.AdjacencyListsGraph;
4 -import org.onlab.onos.net.topology.TopologyEdge;
5 -import org.onlab.onos.net.topology.TopologyGraph;
6 -import org.onlab.onos.net.topology.TopologyVertex;
7 -
8 -import java.util.Set;
9 -
10 -/**
11 - * Default implementation of an immutable topology graph based on a generic
12 - * implementation of adjacency lists graph.
13 - */
14 -public class DefaultTopologyGraph
15 - extends AdjacencyListsGraph<TopologyVertex, TopologyEdge>
16 - implements TopologyGraph {
17 -
18 - /**
19 - * Creates a topology graph comprising of the specified vertexes and edges.
20 - *
21 - * @param vertexes set of graph vertexes
22 - * @param edges set of graph edges
23 - */
24 - public DefaultTopologyGraph(Set<TopologyVertex> vertexes, Set<TopologyEdge> edges) {
25 - super(vertexes, edges);
26 - }
27 -
28 -}
1 -package org.onlab.onos.store.topology.impl;
2 -
3 -import static org.slf4j.LoggerFactory.getLogger;
4 -
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.Service;
12 -import org.onlab.onos.event.Event;
13 -import org.onlab.onos.net.ConnectPoint;
14 -import org.onlab.onos.net.DeviceId;
15 -import org.onlab.onos.net.Link;
16 -import org.onlab.onos.net.Path;
17 -import org.onlab.onos.net.provider.ProviderId;
18 -import org.onlab.onos.net.topology.ClusterId;
19 -import org.onlab.onos.net.topology.GraphDescription;
20 -import org.onlab.onos.net.topology.LinkWeight;
21 -import org.onlab.onos.net.topology.Topology;
22 -import org.onlab.onos.net.topology.TopologyCluster;
23 -import org.onlab.onos.net.topology.TopologyEvent;
24 -import org.onlab.onos.net.topology.TopologyGraph;
25 -import org.onlab.onos.net.topology.TopologyStore;
26 -import org.onlab.onos.net.topology.TopologyStoreDelegate;
27 -import org.onlab.onos.store.AbstractStore;
28 -import org.slf4j.Logger;
29 -
30 -/**
31 - * TEMPORARY: Manages inventory of topology snapshots using distributed
32 - * structures implementation.
33 - */
34 -//FIXME: I LIE I AM NOT DISTRIBUTED
35 -@Component(immediate = true)
36 -@Service
37 -public class DistributedTopologyStore
38 -extends AbstractStore<TopologyEvent, TopologyStoreDelegate>
39 -implements TopologyStore {
40 -
41 - private final Logger log = getLogger(getClass());
42 -
43 - private volatile DefaultTopology current;
44 -
45 - @Activate
46 - public void activate() {
47 - log.info("Started");
48 - }
49 -
50 - @Deactivate
51 - public void deactivate() {
52 - log.info("Stopped");
53 - }
54 - @Override
55 - public Topology currentTopology() {
56 - return current;
57 - }
58 -
59 - @Override
60 - public boolean isLatest(Topology topology) {
61 - // Topology is current only if it is the same as our current topology
62 - return topology == current;
63 - }
64 -
65 - @Override
66 - public TopologyGraph getGraph(Topology topology) {
67 - return defaultTopology(topology).getGraph();
68 - }
69 -
70 - @Override
71 - public Set<TopologyCluster> getClusters(Topology topology) {
72 - return defaultTopology(topology).getClusters();
73 - }
74 -
75 - @Override
76 - public TopologyCluster getCluster(Topology topology, ClusterId clusterId) {
77 - return defaultTopology(topology).getCluster(clusterId);
78 - }
79 -
80 - @Override
81 - public Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster) {
82 - return defaultTopology(topology).getClusterDevices(cluster);
83 - }
84 -
85 - @Override
86 - public Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster) {
87 - return defaultTopology(topology).getClusterLinks(cluster);
88 - }
89 -
90 - @Override
91 - public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
92 - return defaultTopology(topology).getPaths(src, dst);
93 - }
94 -
95 - @Override
96 - public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
97 - LinkWeight weight) {
98 - return defaultTopology(topology).getPaths(src, dst, weight);
99 - }
100 -
101 - @Override
102 - public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) {
103 - return defaultTopology(topology).isInfrastructure(connectPoint);
104 - }
105 -
106 - @Override
107 - public boolean isBroadcastPoint(Topology topology, ConnectPoint connectPoint) {
108 - return defaultTopology(topology).isBroadcastPoint(connectPoint);
109 - }
110 -
111 - @Override
112 - public TopologyEvent updateTopology(ProviderId providerId,
113 - GraphDescription graphDescription,
114 - List<Event> reasons) {
115 - // First off, make sure that what we're given is indeed newer than
116 - // what we already have.
117 - if (current != null && graphDescription.timestamp() < current.time()) {
118 - return null;
119 - }
120 -
121 - // Have the default topology construct self from the description data.
122 - DefaultTopology newTopology =
123 - new DefaultTopology(providerId, graphDescription);
124 -
125 - // Promote the new topology to current and return a ready-to-send event.
126 - synchronized (this) {
127 - current = newTopology;
128 - return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED,
129 - current, reasons);
130 - }
131 - }
132 -
133 - // Validates the specified topology and returns it as a default
134 - private DefaultTopology defaultTopology(Topology topology) {
135 - if (topology instanceof DefaultTopology) {
136 - return (DefaultTopology) topology;
137 - }
138 - throw new IllegalArgumentException("Topology class " + topology.getClass() +
139 - " not supported");
140 - }
141 -
142 -}
1 -package org.onlab.onos.store.topology.impl;
2 -
3 -import org.onlab.onos.net.DeviceId;
4 -
5 -import java.util.Objects;
6 -
7 -/**
8 - * Key for filing pre-computed paths between source and destination devices.
9 - */
10 -class PathKey {
11 - private final DeviceId src;
12 - private final DeviceId dst;
13 -
14 - /**
15 - * Creates a path key from the given source/dest pair.
16 - * @param src source device
17 - * @param dst destination device
18 - */
19 - PathKey(DeviceId src, DeviceId dst) {
20 - this.src = src;
21 - this.dst = dst;
22 - }
23 -
24 - @Override
25 - public int hashCode() {
26 - return Objects.hash(src, dst);
27 - }
28 -
29 - @Override
30 - public boolean equals(Object obj) {
31 - if (this == obj) {
32 - return true;
33 - }
34 - if (obj instanceof PathKey) {
35 - final PathKey other = (PathKey) obj;
36 - return Objects.equals(this.src, other.src) && Objects.equals(this.dst, other.dst);
37 - }
38 - return false;
39 - }
40 -}
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
17 <modules> 17 <modules>
18 <module>common</module> 18 <module>common</module>
19 <module>cluster</module> 19 <module>cluster</module>
20 - <module>net</module>
21 </modules> 20 </modules>
22 21
23 <dependencies> 22 <dependencies>
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +import org.onlab.onos.net.HostLocation;
5 +import org.onlab.onos.net.PortNumber;
6 +
7 +import com.esotericsoftware.kryo.Kryo;
8 +import com.esotericsoftware.kryo.Serializer;
9 +import com.esotericsoftware.kryo.io.Input;
10 +import com.esotericsoftware.kryo.io.Output;
11 +
12 +/**
13 +* Kryo Serializer for {@link HostLocation}.
14 +*/
15 +public class HostLocationSerializer extends Serializer<HostLocation> {
16 +
17 + /**
18 + * Creates {@link HostLocation} serializer instance.
19 + */
20 + public HostLocationSerializer() {
21 + // non-null, immutable
22 + super(false, true);
23 + }
24 +
25 + @Override
26 + public void write(Kryo kryo, Output output, HostLocation object) {
27 + kryo.writeClassAndObject(output, object.deviceId());
28 + kryo.writeClassAndObject(output, object.port());
29 + output.writeLong(object.time());
30 + }
31 +
32 + @Override
33 + public HostLocation read(Kryo kryo, Input input, Class<HostLocation> type) {
34 + DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input);
35 + PortNumber portNumber = (PortNumber) kryo.readClassAndObject(input);
36 + long time = input.readLong();
37 + return new HostLocation(deviceId, portNumber, time);
38 + }
39 +
40 +}
...@@ -20,8 +20,7 @@ public class IpAddressSerializer extends Serializer<IpAddress> { ...@@ -20,8 +20,7 @@ public class IpAddressSerializer extends Serializer<IpAddress> {
20 } 20 }
21 21
22 @Override 22 @Override
23 - public void write(Kryo kryo, Output output, 23 + public void write(Kryo kryo, Output output, IpAddress object) {
24 - IpAddress object) {
25 byte[] octs = object.toOctets(); 24 byte[] octs = object.toOctets();
26 output.writeInt(octs.length); 25 output.writeInt(octs.length);
27 output.writeBytes(octs); 26 output.writeBytes(octs);
...@@ -29,11 +28,10 @@ public class IpAddressSerializer extends Serializer<IpAddress> { ...@@ -29,11 +28,10 @@ public class IpAddressSerializer extends Serializer<IpAddress> {
29 } 28 }
30 29
31 @Override 30 @Override
32 - public IpAddress read(Kryo kryo, Input input, 31 + public IpAddress read(Kryo kryo, Input input, Class<IpAddress> type) {
33 - Class<IpAddress> type) { 32 + final int octLen = input.readInt();
34 - int octLen = input.readInt();
35 byte[] octs = new byte[octLen]; 33 byte[] octs = new byte[octLen];
36 - input.read(octs); 34 + input.readBytes(octs);
37 int prefLen = input.readInt(); 35 int prefLen = input.readInt();
38 return IpAddress.valueOf(octs, prefLen); 36 return IpAddress.valueOf(octs, prefLen);
39 } 37 }
......
...@@ -34,7 +34,7 @@ public final class IpPrefixSerializer extends Serializer<IpPrefix> { ...@@ -34,7 +34,7 @@ public final class IpPrefixSerializer extends Serializer<IpPrefix> {
34 Class<IpPrefix> type) { 34 Class<IpPrefix> type) {
35 int octLen = input.readInt(); 35 int octLen = input.readInt();
36 byte[] octs = new byte[octLen]; 36 byte[] octs = new byte[octLen];
37 - input.read(octs); 37 + input.readBytes(octs);
38 int prefLen = input.readInt(); 38 int prefLen = input.readInt();
39 return IpPrefix.valueOf(octs, prefLen); 39 return IpPrefix.valueOf(octs, prefLen);
40 } 40 }
......
...@@ -17,21 +17,28 @@ import org.onlab.onos.net.DefaultPort; ...@@ -17,21 +17,28 @@ import org.onlab.onos.net.DefaultPort;
17 import org.onlab.onos.net.Device; 17 import org.onlab.onos.net.Device;
18 import org.onlab.onos.net.DeviceId; 18 import org.onlab.onos.net.DeviceId;
19 import org.onlab.onos.net.Element; 19 import org.onlab.onos.net.Element;
20 +import org.onlab.onos.net.HostId;
21 +import org.onlab.onos.net.HostLocation;
20 import org.onlab.onos.net.Link; 22 import org.onlab.onos.net.Link;
21 import org.onlab.onos.net.LinkKey; 23 import org.onlab.onos.net.LinkKey;
22 import org.onlab.onos.net.Port; 24 import org.onlab.onos.net.Port;
23 import org.onlab.onos.net.PortNumber; 25 import org.onlab.onos.net.PortNumber;
24 import org.onlab.onos.net.device.DefaultDeviceDescription; 26 import org.onlab.onos.net.device.DefaultDeviceDescription;
25 import org.onlab.onos.net.device.DefaultPortDescription; 27 import org.onlab.onos.net.device.DefaultPortDescription;
28 +import org.onlab.onos.net.host.DefaultHostDescription;
29 +import org.onlab.onos.net.host.HostDescription;
26 import org.onlab.onos.net.link.DefaultLinkDescription; 30 import org.onlab.onos.net.link.DefaultLinkDescription;
27 import org.onlab.onos.net.provider.ProviderId; 31 import org.onlab.onos.net.provider.ProviderId;
28 import org.onlab.onos.store.Timestamp; 32 import org.onlab.onos.store.Timestamp;
29 import org.onlab.packet.IpAddress; 33 import org.onlab.packet.IpAddress;
30 import org.onlab.packet.IpPrefix; 34 import org.onlab.packet.IpPrefix;
35 +import org.onlab.packet.MacAddress;
36 +import org.onlab.packet.VlanId;
31 import org.onlab.util.KryoPool; 37 import org.onlab.util.KryoPool;
32 38
33 import com.google.common.collect.ImmutableList; 39 import com.google.common.collect.ImmutableList;
34 import com.google.common.collect.ImmutableMap; 40 import com.google.common.collect.ImmutableMap;
41 +import com.google.common.collect.ImmutableSet;
35 42
36 public final class KryoPoolUtil { 43 public final class KryoPoolUtil {
37 44
...@@ -41,6 +48,8 @@ public final class KryoPoolUtil { ...@@ -41,6 +48,8 @@ public final class KryoPoolUtil {
41 public static final KryoPool MISC = KryoPool.newBuilder() 48 public static final KryoPool MISC = KryoPool.newBuilder()
42 .register(IpPrefix.class, new IpPrefixSerializer()) 49 .register(IpPrefix.class, new IpPrefixSerializer())
43 .register(IpAddress.class, new IpAddressSerializer()) 50 .register(IpAddress.class, new IpAddressSerializer())
51 + .register(MacAddress.class, new MacAddressSerializer())
52 + .register(VlanId.class)
44 .build(); 53 .build();
45 54
46 // TODO: Populate other classes 55 // TODO: Populate other classes
...@@ -51,6 +60,7 @@ public final class KryoPoolUtil { ...@@ -51,6 +60,7 @@ public final class KryoPoolUtil {
51 .register(MISC) 60 .register(MISC)
52 .register(ImmutableMap.class, new ImmutableMapSerializer()) 61 .register(ImmutableMap.class, new ImmutableMapSerializer())
53 .register(ImmutableList.class, new ImmutableListSerializer()) 62 .register(ImmutableList.class, new ImmutableListSerializer())
63 + .register(ImmutableSet.class, new ImmutableSetSerializer())
54 .register( 64 .register(
55 // 65 //
56 ArrayList.class, 66 ArrayList.class,
...@@ -69,8 +79,10 @@ public final class KryoPoolUtil { ...@@ -69,8 +79,10 @@ public final class KryoPoolUtil {
69 DefaultPortDescription.class, 79 DefaultPortDescription.class,
70 Element.class, 80 Element.class,
71 Link.Type.class, 81 Link.Type.class,
72 - Timestamp.class 82 + Timestamp.class,
73 - 83 + HostId.class,
84 + HostDescription.class,
85 + DefaultHostDescription.class
74 ) 86 )
75 .register(URI.class, new URISerializer()) 87 .register(URI.class, new URISerializer())
76 .register(NodeId.class, new NodeIdSerializer()) 88 .register(NodeId.class, new NodeIdSerializer())
...@@ -82,6 +94,8 @@ public final class KryoPoolUtil { ...@@ -82,6 +94,8 @@ public final class KryoPoolUtil {
82 .register(ConnectPoint.class, new ConnectPointSerializer()) 94 .register(ConnectPoint.class, new ConnectPointSerializer())
83 .register(DefaultLink.class, new DefaultLinkSerializer()) 95 .register(DefaultLink.class, new DefaultLinkSerializer())
84 .register(MastershipTerm.class, new MastershipTermSerializer()) 96 .register(MastershipTerm.class, new MastershipTermSerializer())
97 + .register(MastershipRole.class, new MastershipRoleSerializer())
98 + .register(HostLocation.class, new HostLocationSerializer())
85 99
86 .build(); 100 .build();
87 101
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.packet.MacAddress;
4 +
5 +import com.esotericsoftware.kryo.Kryo;
6 +import com.esotericsoftware.kryo.Serializer;
7 +import com.esotericsoftware.kryo.io.Input;
8 +import com.esotericsoftware.kryo.io.Output;
9 +
10 +/**
11 + * Kryo Serializer for {@link MacAddress}.
12 + */
13 +public class MacAddressSerializer extends Serializer<MacAddress> {
14 +
15 + /**
16 + * Creates {@link MacAddress} serializer instance.
17 + */
18 + public MacAddressSerializer() {
19 + super(false, true);
20 + }
21 +
22 + @Override
23 + public void write(Kryo kryo, Output output, MacAddress object) {
24 + output.writeBytes(object.getAddress());
25 + }
26 +
27 + @Override
28 + public MacAddress read(Kryo kryo, Input input, Class<MacAddress> type) {
29 + return MacAddress.valueOf(input.readBytes(MacAddress.MAC_ADDRESS_LENGTH));
30 + }
31 +
32 +}
...@@ -84,7 +84,7 @@ public class SimpleHostStore ...@@ -84,7 +84,7 @@ public class SimpleHostStore
84 descr.hwAddress(), 84 descr.hwAddress(),
85 descr.vlan(), 85 descr.vlan(),
86 descr.location(), 86 descr.location(),
87 - ImmutableSet.of(descr.ipAddress())); 87 + ImmutableSet.copyOf(descr.ipAddress()));
88 synchronized (this) { 88 synchronized (this) {
89 hosts.put(hostId, newhost); 89 hosts.put(hostId, newhost);
90 locations.put(descr.location(), newhost); 90 locations.put(descr.location(), newhost);
...@@ -101,12 +101,12 @@ public class SimpleHostStore ...@@ -101,12 +101,12 @@ public class SimpleHostStore
101 return new HostEvent(HOST_MOVED, host); 101 return new HostEvent(HOST_MOVED, host);
102 } 102 }
103 103
104 - if (host.ipAddresses().contains(descr.ipAddress())) { 104 + if (host.ipAddresses().containsAll(descr.ipAddress())) {
105 return null; 105 return null;
106 } 106 }
107 107
108 Set<IpPrefix> addresses = new HashSet<>(host.ipAddresses()); 108 Set<IpPrefix> addresses = new HashSet<>(host.ipAddresses());
109 - addresses.add(descr.ipAddress()); 109 + addresses.addAll(descr.ipAddress());
110 StoredHost updated = new StoredHost(providerId, host.id(), 110 StoredHost updated = new StoredHost(providerId, host.id(),
111 host.mac(), host.vlan(), 111 host.mac(), host.vlan(),
112 descr.location(), addresses); 112 descr.location(), addresses);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
30 30
31 <bundle>mvn:org.codehaus.jackson/jackson-core-asl/1.9.13</bundle> 31 <bundle>mvn:org.codehaus.jackson/jackson-core-asl/1.9.13</bundle>
32 <bundle>mvn:org.codehaus.jackson/jackson-mapper-asl/1.9.13</bundle> 32 <bundle>mvn:org.codehaus.jackson/jackson-mapper-asl/1.9.13</bundle>
33 + <bundle>mvn:org.onlab.onos/onlab-thirdparty/1.0.0-SNAPSHOT</bundle>
33 </feature> 34 </feature>
34 35
35 <feature name="onos-thirdparty-web" version="1.0.0" 36 <feature name="onos-thirdparty-web" version="1.0.0"
......
...@@ -107,6 +107,12 @@ ...@@ -107,6 +107,12 @@
107 </dependency> 107 </dependency>
108 108
109 <dependency> 109 <dependency>
110 + <groupId>com.googlecode.concurrent-trees</groupId>
111 + <artifactId>concurrent-trees</artifactId>
112 + <version>2.4.0</version>
113 + </dependency>
114 +
115 + <dependency>
110 <groupId>commons-lang</groupId> 116 <groupId>commons-lang</groupId>
111 <artifactId>commons-lang</artifactId> 117 <artifactId>commons-lang</artifactId>
112 <version>2.6</version> 118 <version>2.6</version>
...@@ -164,6 +170,12 @@ ...@@ -164,6 +170,12 @@
164 <scope>provided</scope> 170 <scope>provided</scope>
165 </dependency> 171 </dependency>
166 <dependency> 172 <dependency>
173 + <groupId>org.osgi</groupId>
174 + <artifactId>org.osgi.compendium</artifactId>
175 + <version>4.3.1</version>
176 + <scope>provided</scope>
177 + </dependency>
178 + <dependency>
167 <groupId>org.apache.felix</groupId> 179 <groupId>org.apache.felix</groupId>
168 <artifactId>org.apache.felix.scr.annotations</artifactId> 180 <artifactId>org.apache.felix.scr.annotations</artifactId>
169 <version>1.9.8</version> 181 <version>1.9.8</version>
...@@ -260,6 +272,13 @@ ...@@ -260,6 +272,13 @@
260 <artifactId>onos-of-api</artifactId> 272 <artifactId>onos-of-api</artifactId>
261 <version>${project.version}</version> 273 <version>${project.version}</version>
262 </dependency> 274 </dependency>
275 +
276 + <dependency>
277 + <groupId>org.onlab.onos</groupId>
278 + <artifactId>onlab-thirdparty</artifactId>
279 + <version>${project.version}</version>
280 + </dependency>
281 +
263 <dependency> 282 <dependency>
264 <groupId>org.onlab.onos</groupId> 283 <groupId>org.onlab.onos</groupId>
265 <artifactId>onos-of-api</artifactId> 284 <artifactId>onos-of-api</artifactId>
......
...@@ -161,10 +161,10 @@ public class FlowModBuilder { ...@@ -161,10 +161,10 @@ public class FlowModBuilder {
161 switch (l3m.subtype()) { 161 switch (l3m.subtype()) {
162 case IP_DST: 162 case IP_DST:
163 ip = (ModIPInstruction) i; 163 ip = (ModIPInstruction) i;
164 - return factory.actions().setNwDst(IPv4Address.of(ip.ip().toRealInt())); 164 + return factory.actions().setNwDst(IPv4Address.of(ip.ip().toInt()));
165 case IP_SRC: 165 case IP_SRC:
166 ip = (ModIPInstruction) i; 166 ip = (ModIPInstruction) i;
167 - return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toRealInt())); 167 + return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toInt()));
168 default: 168 default:
169 log.warn("Unimplemented action type {}.", l3m.subtype()); 169 log.warn("Unimplemented action type {}.", l3m.subtype());
170 break; 170 break;
...@@ -220,21 +220,21 @@ public class FlowModBuilder { ...@@ -220,21 +220,21 @@ public class FlowModBuilder {
220 case IPV4_DST: 220 case IPV4_DST:
221 ip = (IPCriterion) c; 221 ip = (IPCriterion) c;
222 if (ip.ip().isMasked()) { 222 if (ip.ip().isMasked()) {
223 - Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()), 223 + Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
224 - IPv4Address.of(ip.ip().netmask().toRealInt())); 224 + IPv4Address.of(ip.ip().netmask().toInt()));
225 mBuilder.setMasked(MatchField.IPV4_DST, maskedIp); 225 mBuilder.setMasked(MatchField.IPV4_DST, maskedIp);
226 } else { 226 } else {
227 - mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toRealInt())); 227 + mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toInt()));
228 } 228 }
229 break; 229 break;
230 case IPV4_SRC: 230 case IPV4_SRC:
231 ip = (IPCriterion) c; 231 ip = (IPCriterion) c;
232 if (ip.ip().isMasked()) { 232 if (ip.ip().isMasked()) {
233 - Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()), 233 + Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toInt()),
234 - IPv4Address.of(ip.ip().netmask().toRealInt())); 234 + IPv4Address.of(ip.ip().netmask().toInt()));
235 mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp); 235 mBuilder.setMasked(MatchField.IPV4_SRC, maskedIp);
236 } else { 236 } else {
237 - mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toRealInt())); 237 + mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toInt()));
238 } 238 }
239 break; 239 break;
240 case IP_PROTO: 240 case IP_PROTO:
......
...@@ -339,9 +339,14 @@ public class LinkDiscovery implements TimerTask { ...@@ -339,9 +339,14 @@ public class LinkDiscovery implements TimerTask {
339 final Iterator<Integer> fastIterator = this.fastPorts.iterator(); 339 final Iterator<Integer> fastIterator = this.fastPorts.iterator();
340 while (fastIterator.hasNext()) { 340 while (fastIterator.hasNext()) {
341 final Integer portNumber = fastIterator.next(); 341 final Integer portNumber = fastIterator.next();
342 + OFPortDesc port = findPort(portNumber);
343 + if (port == null) {
344 + // port can be null
345 + // #removePort modifies `ports` outside synchronized block
346 + continue;
347 + }
342 final int probeCount = this.portProbeCount.get(portNumber) 348 final int probeCount = this.portProbeCount.get(portNumber)
343 .getAndIncrement(); 349 .getAndIncrement();
344 - OFPortDesc port = findPort(portNumber);
345 if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) { 350 if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) {
346 this.log.debug("sending fast probe to port"); 351 this.log.debug("sending fast probe to port");
347 352
......
...@@ -25,6 +25,9 @@ export ONOS_STAGE=$ONOS_STAGE_ROOT/$ONOS_BITS ...@@ -25,6 +25,9 @@ export ONOS_STAGE=$ONOS_STAGE_ROOT/$ONOS_BITS
25 export ONOS_TAR=$ONOS_STAGE.tar.gz 25 export ONOS_TAR=$ONOS_STAGE.tar.gz
26 26
27 # Defaults for ONOS testing using remote machines. 27 # Defaults for ONOS testing using remote machines.
28 +if [ -n "${ONOS_CELL}" -a -f $ONOS_ROOT/tools/test/cells/${ONOS_CELL} ]; then
29 + . $ONOS_ROOT/tools/test/cells/${ONOS_CELL}
30 +fi
28 export ONOS_INSTALL_DIR="/opt/onos" # Installation directory on remote 31 export ONOS_INSTALL_DIR="/opt/onos" # Installation directory on remote
29 export OCI="${OCI:-192.168.56.101}" # ONOS Controller Instance 32 export OCI="${OCI:-192.168.56.101}" # ONOS Controller Instance
30 export ONOS_USER="sdn" # ONOS user on remote system 33 export ONOS_USER="sdn" # ONOS user on remote system
......
...@@ -6,7 +6,13 @@ ...@@ -6,7 +6,13 @@
6 export ONOS_ROOT=${ONOS_ROOT:-~/onos-next} 6 export ONOS_ROOT=${ONOS_ROOT:-~/onos-next}
7 7
8 # Setup some environmental context for developers 8 # Setup some environmental context for developers
9 -export JAVA_HOME=${JAVA_HOME:-$(/usr/libexec/java_home -v 1.7)} 9 +if [ -z "${JAVA_HOME}" ]; then
10 + if [ -x /usr/libexec/java_home ]; then
11 + export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
12 + elif [ -d /usr/lib/jvm/java-7-openjdk-amd64 ]; then
13 + export JAVA_HOME="/usr/lib/jvm/java-7-openjdk-amd64"
14 + fi
15 +fi
10 export MAVEN=${MAVEN:-~/Applications/apache-maven-3.2.2} 16 export MAVEN=${MAVEN:-~/Applications/apache-maven-3.2.2}
11 export KARAF=${KARAF:-~/Applications/apache-karaf-3.0.1} 17 export KARAF=${KARAF:-~/Applications/apache-karaf-3.0.1}
12 export KARAF_LOG=$KARAF/data/log/karaf.log 18 export KARAF_LOG=$KARAF/data/log/karaf.log
...@@ -15,7 +21,6 @@ export KARAF_LOG=$KARAF/data/log/karaf.log ...@@ -15,7 +21,6 @@ export KARAF_LOG=$KARAF/data/log/karaf.log
15 export PATH="$PATH:$ONOS_ROOT/tools/dev/bin:$ONOS_ROOT/tools/test/bin" 21 export PATH="$PATH:$ONOS_ROOT/tools/dev/bin:$ONOS_ROOT/tools/test/bin"
16 export PATH="$PATH:$ONOS_ROOT/tools/build" 22 export PATH="$PATH:$ONOS_ROOT/tools/build"
17 export PATH="$PATH:$MAVEN/bin:$KARAF/bin" 23 export PATH="$PATH:$MAVEN/bin:$KARAF/bin"
18 -export PATH="$PATH:."
19 24
20 # Convenience utility to warp to various ONOS source projects 25 # Convenience utility to warp to various ONOS source projects
21 # e.g. 'o api', 'o dev', 'o' 26 # e.g. 'o api', 'o dev', 'o'
......
...@@ -2,13 +2,15 @@ package org.onlab.packet; ...@@ -2,13 +2,15 @@ package org.onlab.packet;
2 2
3 import java.util.Arrays; 3 import java.util.Arrays;
4 4
5 +
6 +
5 /** 7 /**
6 * A class representing an IPv4 address. 8 * A class representing an IPv4 address.
7 * <p/> 9 * <p/>
8 * TODO this class is a clone of IpPrefix and still needs to be modified to 10 * TODO this class is a clone of IpPrefix and still needs to be modified to
9 * look more like an IpAddress. 11 * look more like an IpAddress.
10 */ 12 */
11 -public final class IpAddress { 13 +public final class IpAddress implements Comparable<IpAddress> {
12 14
13 // TODO a comparator for netmasks? E.g. for sorting by prefix match order. 15 // TODO a comparator for netmasks? E.g. for sorting by prefix match order.
14 16
...@@ -121,7 +123,7 @@ public final class IpAddress { ...@@ -121,7 +123,7 @@ public final class IpAddress {
121 123
122 int mask = DEFAULT_MASK; 124 int mask = DEFAULT_MASK;
123 if (parts.length == 2) { 125 if (parts.length == 2) {
124 - mask = Integer.valueOf(parts[1]); 126 + mask = Integer.parseInt(parts[1]);
125 if (mask > MAX_INET_MASK) { 127 if (mask > MAX_INET_MASK) {
126 throw new IllegalArgumentException( 128 throw new IllegalArgumentException(
127 "Value of subnet mask cannot exceed " 129 "Value of subnet mask cannot exceed "
...@@ -174,14 +176,6 @@ public final class IpAddress { ...@@ -174,14 +176,6 @@ public final class IpAddress {
174 * @return the IP address's value as an integer 176 * @return the IP address's value as an integer
175 */ 177 */
176 public int toInt() { 178 public int toInt() {
177 - int address = 0;
178 - for (int i = 0; i < INET_LEN; i++) {
179 - address |= octets[i] << ((INET_LEN - (i + 1)) * 8);
180 - }
181 - return address;
182 - }
183 -
184 - public int toRealInt() {
185 int val = 0; 179 int val = 0;
186 for (int i = 0; i < octets.length; i++) { 180 for (int i = 0; i < octets.length; i++) {
187 val <<= 8; 181 val <<= 8;
...@@ -191,6 +185,15 @@ public final class IpAddress { ...@@ -191,6 +185,15 @@ public final class IpAddress {
191 } 185 }
192 186
193 /** 187 /**
188 + * Converts the IP address to a /32 IP prefix.
189 + *
190 + * @return the new IP prefix
191 + */
192 + public IpPrefix toPrefix() {
193 + return IpPrefix.valueOf(octets, MAX_INET_MASK);
194 + }
195 +
196 + /**
194 * Helper for computing the mask value from CIDR. 197 * Helper for computing the mask value from CIDR.
195 * 198 *
196 * @return an integer bitmask 199 * @return an integer bitmask
...@@ -280,6 +283,13 @@ public final class IpAddress { ...@@ -280,6 +283,13 @@ public final class IpAddress {
280 } 283 }
281 284
282 @Override 285 @Override
286 + public int compareTo(IpAddress o) {
287 + Long lv = ((long) this.toInt()) & 0xffffffffL;
288 + Long rv = ((long) o.toInt()) & 0xffffffffL;
289 + return lv.compareTo(rv);
290 + }
291 +
292 + @Override
283 public int hashCode() { 293 public int hashCode() {
284 final int prime = 31; 294 final int prime = 31;
285 int result = 1; 295 int result = 1;
......
...@@ -120,7 +120,7 @@ public final class IpPrefix { ...@@ -120,7 +120,7 @@ public final class IpPrefix {
120 120
121 int mask = DEFAULT_MASK; 121 int mask = DEFAULT_MASK;
122 if (parts.length == 2) { 122 if (parts.length == 2) {
123 - mask = Integer.valueOf(parts[1]); 123 + mask = Integer.parseInt(parts[1]);
124 if (mask > MAX_INET_MASK) { 124 if (mask > MAX_INET_MASK) {
125 throw new IllegalArgumentException( 125 throw new IllegalArgumentException(
126 "Value of subnet mask cannot exceed " 126 "Value of subnet mask cannot exceed "
...@@ -173,14 +173,6 @@ public final class IpPrefix { ...@@ -173,14 +173,6 @@ public final class IpPrefix {
173 * @return the IP address's value as an integer 173 * @return the IP address's value as an integer
174 */ 174 */
175 public int toInt() { 175 public int toInt() {
176 - int address = 0;
177 - for (int i = 0; i < INET_LEN; i++) {
178 - address |= octets[i] << ((INET_LEN - (i + 1)) * 8);
179 - }
180 - return address;
181 - }
182 -
183 - public int toRealInt() {
184 int val = 0; 176 int val = 0;
185 for (int i = 0; i < octets.length; i++) { 177 for (int i = 0; i < octets.length; i++) {
186 val <<= 8; 178 val <<= 8;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
23 <module>nio</module> 23 <module>nio</module>
24 <module>osgi</module> 24 <module>osgi</module>
25 <module>rest</module> 25 <module>rest</module>
26 + <module>thirdparty</module>
26 </modules> 27 </modules>
27 28
28 <dependencies> 29 <dependencies>
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onlab-utils</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onlab-thirdparty</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONLab third-party dependencies</description>
18 +
19 + <dependencies>
20 + <dependency>
21 + <groupId>com.googlecode.concurrent-trees</groupId>
22 + <artifactId>concurrent-trees</artifactId>
23 + <version>2.4.0</version>
24 + </dependency>
25 + </dependencies>
26 +
27 + <build>
28 + <plugins>
29 + <plugin>
30 + <groupId>org.apache.maven.plugins</groupId>
31 + <artifactId>maven-shade-plugin</artifactId>
32 + <version>2.3</version>
33 + <configuration>
34 + <filters>
35 + <filter>
36 + <artifact>com.googlecode.concurrent-trees:concurrent-trees</artifact>
37 + <includes>
38 + <include>com/googlecode/**</include>
39 + </includes>
40 +
41 + </filter>
42 + <filter>
43 + <artifact>com.google.guava:guava</artifact>
44 + <excludes>
45 + <exclude>**</exclude>
46 + </excludes>
47 + </filter>
48 + </filters>
49 + </configuration>
50 + <executions>
51 + <execution>
52 + <phase>package</phase>
53 + <goals>
54 + <goal>shade</goal>
55 + </goals>
56 + </execution>
57 + </executions>
58 + </plugin>
59 + <plugin>
60 + <groupId>org.apache.felix</groupId>
61 + <artifactId>maven-bundle-plugin</artifactId>
62 + <configuration>
63 + <instructions>
64 + <Export-Package>
65 + com.googlecode.concurrenttrees.*
66 + </Export-Package>
67 + </instructions>
68 + </configuration>
69 + </plugin>
70 + </plugins>
71 + </build>
72 +
73 +</project>
1 +package org.onlab.thirdparty;
2 +
3 +
4 +/**
5 + * Empty class required to get the onlab-thirdparty module to build properly.
6 + * <p/>
7 + * TODO Figure out how to remove this.
8 + */
9 +public class OnlabThirdparty {
10 +
11 +}