Ayaka Koshibe

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

Showing 88 changed files with 2181 additions and 552 deletions
...@@ -2,35 +2,40 @@ ...@@ -2,35 +2,40 @@
2 <project xmlns="http://maven.apache.org/POM/4.0.0" 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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"> 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> 5 + <modelVersion>4.0.0</modelVersion>
6 6
7 - <parent> 7 + <parent>
8 - <groupId>org.onlab.onos</groupId> 8 + <groupId>org.onlab.onos</groupId>
9 - <artifactId>onos-apps</artifactId> 9 + <artifactId>onos-apps</artifactId>
10 - <version>1.0.0-SNAPSHOT</version> 10 + <version>1.0.0-SNAPSHOT</version>
11 - <relativePath>../pom.xml</relativePath> 11 + <relativePath>../pom.xml</relativePath>
12 - </parent> 12 + </parent>
13 13
14 - <artifactId>onos-app-sdnip</artifactId> 14 + <artifactId>onos-app-sdnip</artifactId>
15 - <packaging>bundle</packaging> 15 + <packaging>bundle</packaging>
16 16
17 - <description>SDN-IP peering application</description> 17 + <description>SDN-IP peering application</description>
18 18
19 - <dependencies> 19 + <dependencies>
20 - <dependency> 20 + <dependency>
21 - <groupId>org.codehaus.jackson</groupId> 21 + <groupId>org.codehaus.jackson</groupId>
22 - <artifactId>jackson-core-asl</artifactId> 22 + <artifactId>jackson-core-asl</artifactId>
23 - </dependency> 23 + </dependency>
24 - <dependency> 24 + <dependency>
25 - <groupId>org.codehaus.jackson</groupId> 25 + <groupId>org.codehaus.jackson</groupId>
26 - <artifactId>jackson-mapper-asl</artifactId> 26 + <artifactId>jackson-mapper-asl</artifactId>
27 - </dependency> 27 + </dependency>
28 - <dependency> 28 + <dependency>
29 - <groupId>com.fasterxml.jackson.core</groupId> 29 + <groupId>com.fasterxml.jackson.core</groupId>
30 - <artifactId>jackson-annotations</artifactId> 30 + <artifactId>jackson-annotations</artifactId>
31 - <version>2.4.2</version> 31 + <version>2.4.2</version>
32 - <scope>provided</scope> 32 + <scope>provided</scope>
33 - </dependency> 33 + </dependency>
34 - </dependencies> 34 +
35 + <dependency>
36 + <groupId>com.google.guava</groupId>
37 + <artifactId>guava</artifactId>
38 + </dependency>
39 + </dependencies>
35 40
36 </project> 41 </project>
......
1 +package org.onlab.onos.sdnip;
2 +
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +
5 +import java.util.Set;
6 +
7 +import org.apache.commons.lang.NotImplementedException;
8 +import org.onlab.onos.net.ConnectPoint;
9 +import org.onlab.onos.net.host.HostService;
10 +import org.onlab.onos.net.host.PortAddresses;
11 +import org.onlab.onos.sdnip.config.Interface;
12 +import org.onlab.packet.IpAddress;
13 +
14 +import com.google.common.collect.Sets;
15 +
16 +
17 +
18 +/**
19 + * Provides IntefaceService using PortAddresses data from the HostService.
20 + */
21 +public class HostServiceBasedInterfaceService implements InterfaceService {
22 +
23 + private final HostService hostService;
24 +
25 + public HostServiceBasedInterfaceService(HostService hostService) {
26 + this.hostService = checkNotNull(hostService);
27 + }
28 +
29 + @Override
30 + public Set<Interface> getInterfaces() {
31 + Set<PortAddresses> addresses = hostService.getAddressBindings();
32 + Set<Interface> interfaces = Sets.newHashSetWithExpectedSize(addresses.size());
33 + for (PortAddresses a : addresses) {
34 + interfaces.add(new Interface(a));
35 + }
36 + return interfaces;
37 + }
38 +
39 + @Override
40 + public Interface getInterface(ConnectPoint connectPoint) {
41 + checkNotNull(connectPoint);
42 +
43 + PortAddresses portAddresses =
44 + hostService.getAddressBindingsForPort(connectPoint);
45 +
46 + if (!portAddresses.ips().isEmpty()) {
47 + return new Interface(portAddresses);
48 + }
49 +
50 + return null;
51 + }
52 +
53 + @Override
54 + public Interface getMatchingInterface(IpAddress ipAddress) {
55 + // TODO implement
56 + throw new NotImplementedException("getMatchingInteface is not yet implemented");
57 + }
58 +
59 +}
1 +package org.onlab.onos.sdnip;
2 +
3 +import java.util.Set;
4 +
5 +import org.onlab.onos.net.ConnectPoint;
6 +import org.onlab.onos.sdnip.config.Interface;
7 +import org.onlab.packet.IpAddress;
8 +
9 +/**
10 + * Provides information about the interfaces in the network.
11 + */
12 +public interface InterfaceService {
13 + /**
14 + * Retrieves the entire set of interfaces in the network.
15 + *
16 + * @return the set of interfaces
17 + */
18 + Set<Interface> getInterfaces();
19 +
20 + /**
21 + * Retrieves the interface associated with the given connect point.
22 + *
23 + * @param connectPoint the connect point to retrieve interface information
24 + * for
25 + * @return the interface
26 + */
27 + Interface getInterface(ConnectPoint connectPoint);
28 +
29 + /**
30 + * Retrieves the interface that matches the given IP address. Matching
31 + * means that the IP address is in one of the interface's assigned subnets.
32 + *
33 + * @param ipAddress IP address to match
34 + * @return the matching interface
35 + */
36 + Interface getMatchingInterface(IpAddress ipAddress);
37 +}
1 +package org.onlab.onos.sdnip;
2 +
3 +import java.util.List;
4 +
5 +import org.onlab.onos.net.ConnectPoint;
6 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
7 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
8 +import org.onlab.onos.net.flow.TrafficSelector;
9 +import org.onlab.onos.net.flow.TrafficTreatment;
10 +import org.onlab.onos.net.intent.IntentId;
11 +import org.onlab.onos.net.intent.IntentService;
12 +import org.onlab.onos.net.intent.PointToPointIntent;
13 +import org.onlab.onos.sdnip.config.BgpPeer;
14 +import org.onlab.onos.sdnip.config.BgpSpeaker;
15 +import org.onlab.onos.sdnip.config.Interface;
16 +import org.onlab.onos.sdnip.config.InterfaceAddress;
17 +import org.onlab.onos.sdnip.config.SdnIpConfigService;
18 +import org.onlab.packet.Ethernet;
19 +import org.onlab.packet.IPv4;
20 +import org.onlab.packet.IpAddress;
21 +import org.onlab.packet.IpPrefix;
22 +import org.slf4j.Logger;
23 +import org.slf4j.LoggerFactory;
24 +
25 +/**
26 + * Manages the connectivity requirements between peers.
27 + */
28 +public class PeerConnectivity {
29 +
30 + private static final Logger log = LoggerFactory.getLogger(
31 + PeerConnectivity.class);
32 +
33 + // TODO these shouldn't be defined here
34 + private static final short BGP_PORT = 179;
35 + private static final int IPV4_BIT_LENGTH = 32;
36 +
37 + private final SdnIpConfigService configInfoService;
38 + private final InterfaceService interfaceService;
39 + private final IntentService intentService;
40 +
41 + // TODO this sucks.
42 + private int intentId = 0;
43 +
44 + public PeerConnectivity(SdnIpConfigService configInfoService,
45 + InterfaceService interfaceService, IntentService intentService) {
46 + this.configInfoService = configInfoService;
47 + this.interfaceService = interfaceService;
48 + this.intentService = intentService;
49 + }
50 +
51 + public void start() {
52 + // TODO are any of these errors?
53 + if (interfaceService.getInterfaces().isEmpty()) {
54 +
55 + log.warn("The interface in configuration file is empty. "
56 + + "Thus, the SDN-IP application can not be started.");
57 + } else if (configInfoService.getBgpPeers().isEmpty()) {
58 +
59 + log.warn("The BGP peer in configuration file is empty."
60 + + "Thus, the SDN-IP application can not be started.");
61 + } else if (configInfoService.getBgpSpeakers() == null) {
62 +
63 + log.error("The BGP speaker in configuration file is empty. "
64 + + "Thus, the SDN-IP application can not be started.");
65 + return;
66 + }
67 +
68 + setupBgpPaths();
69 + setupIcmpPaths();
70 + }
71 +
72 + /**
73 + * Sets up paths for all {@link BgpSpeaker}s and all external peers.
74 + * <p/>
75 + * Run a loop for all BGP speakers and a loop for all BGP peers outside.
76 + * Push intents for paths from each BGP speaker to all peers. Push intents
77 + * for paths from all peers to each BGP speaker.
78 + */
79 + private void setupBgpPaths() {
80 + for (BgpSpeaker bgpSpeaker : configInfoService.getBgpSpeakers()
81 + .values()) {
82 + log.debug("Start to set up BGP paths for BGP speaker: {}",
83 + bgpSpeaker);
84 + ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
85 +
86 + List<InterfaceAddress> interfaceAddresses =
87 + bgpSpeaker.interfaceAddresses();
88 +
89 + for (BgpPeer bgpPeer : configInfoService.getBgpPeers().values()) {
90 +
91 + log.debug("Start to set up BGP paths between BGP speaker: {} "
92 + + "to BGP peer: {}", bgpSpeaker, bgpPeer);
93 +
94 + Interface peerInterface = interfaceService.getInterface(
95 + bgpPeer.connectPoint());
96 + if (peerInterface == null) {
97 + log.error("Can not find the corresponding Interface from "
98 + + "configuration for BGP peer {}",
99 + bgpPeer.ipAddress());
100 + continue;
101 + }
102 +
103 + IpAddress bgpdAddress = null;
104 + for (InterfaceAddress interfaceAddress : interfaceAddresses) {
105 + if (interfaceAddress.connectPoint().equals(
106 + peerInterface.connectPoint())) {
107 + bgpdAddress = interfaceAddress.ipAddress();
108 + break;
109 + }
110 + }
111 + if (bgpdAddress == null) {
112 + log.debug("There is no interface IP address for bgpPeer: {}"
113 + + " on interface {}", bgpPeer, bgpPeer.connectPoint());
114 + return;
115 + }
116 +
117 + IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
118 + ConnectPoint bgpdPeerConnectPoint = peerInterface.connectPoint();
119 +
120 + // install intent for BGP path from BGPd to BGP peer matching
121 + // destination TCP port 179
122 +
123 + // TODO: The usage of PacketMatchBuilder will be improved, then we
124 + // only need to new the PacketMatchBuilder once.
125 + // By then, the code here will be improved accordingly.
126 + TrafficSelector selector = DefaultTrafficSelector.builder()
127 + .matchEthType(Ethernet.TYPE_IPV4)
128 + .matchIPProtocol(IPv4.PROTOCOL_TCP)
129 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
130 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
131 + .matchTcpDst(BGP_PORT)
132 + .build();
133 +
134 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
135 + .build();
136 +
137 + PointToPointIntent intentMatchDstTcpPort = new PointToPointIntent(
138 + nextIntentId(), selector, treatment,
139 + bgpdConnectPoint, bgpdPeerConnectPoint);
140 + intentService.submit(intentMatchDstTcpPort);
141 + log.debug("Submitted BGP path intent matching dst TCP port 179 "
142 + + "from BGPd {} to peer {}: {}",
143 + bgpdAddress, bgpdPeerAddress, intentMatchDstTcpPort);
144 +
145 + // install intent for BGP path from BGPd to BGP peer matching
146 + // source TCP port 179
147 + selector = DefaultTrafficSelector.builder()
148 + .matchEthType(Ethernet.TYPE_IPV4)
149 + .matchIPProtocol(IPv4.PROTOCOL_TCP)
150 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
151 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
152 + .matchTcpSrc(BGP_PORT)
153 + .build();
154 +
155 + PointToPointIntent intentMatchSrcTcpPort = new PointToPointIntent(
156 + nextIntentId(), selector, treatment,
157 + bgpdConnectPoint, bgpdPeerConnectPoint);
158 + intentService.submit(intentMatchSrcTcpPort);
159 + log.debug("Submitted BGP path intent matching src TCP port 179"
160 + + "from BGPd {} to peer {}: {}",
161 + bgpdAddress, bgpdPeerAddress, intentMatchSrcTcpPort);
162 +
163 + // install intent for reversed BGP path from BGP peer to BGPd
164 + // matching destination TCP port 179
165 + selector = DefaultTrafficSelector.builder()
166 + .matchEthType(Ethernet.TYPE_IPV4)
167 + .matchIPProtocol(IPv4.PROTOCOL_TCP)
168 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
169 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
170 + .matchTcpDst(BGP_PORT)
171 + .build();
172 +
173 + PointToPointIntent reversedIntentMatchDstTcpPort = new PointToPointIntent(
174 + nextIntentId(), selector, treatment,
175 + bgpdPeerConnectPoint, bgpdConnectPoint);
176 + intentService.submit(reversedIntentMatchDstTcpPort);
177 + log.debug("Submitted BGP path intent matching dst TCP port 179"
178 + + "from BGP peer {} to BGPd {} : {}",
179 + bgpdPeerAddress, bgpdAddress, reversedIntentMatchDstTcpPort);
180 +
181 + // install intent for reversed BGP path from BGP peer to BGPd
182 + // matching source TCP port 179
183 + selector = DefaultTrafficSelector.builder()
184 + .matchEthType(Ethernet.TYPE_IPV4)
185 + .matchIPProtocol(IPv4.PROTOCOL_TCP)
186 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
187 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
188 + .matchTcpSrc(BGP_PORT)
189 + .build();
190 +
191 + PointToPointIntent reversedIntentMatchSrcTcpPort = new PointToPointIntent(
192 + nextIntentId(), selector, treatment,
193 + bgpdPeerConnectPoint, bgpdConnectPoint);
194 + intentService.submit(reversedIntentMatchSrcTcpPort);
195 + log.debug("Submitted BGP path intent matching src TCP port 179"
196 + + "from BGP peer {} to BGPd {} : {}",
197 + bgpdPeerAddress, bgpdAddress, reversedIntentMatchSrcTcpPort);
198 +
199 + }
200 + }
201 + }
202 +
203 + /**
204 + * Sets up ICMP paths between each {@link BgpSpeaker} and all BGP peers
205 + * located in other external networks.
206 + * <p/>
207 + * Run a loop for all BGP speakers and a loop for all BGP Peers. Push
208 + * intents for paths from each BGP speaker to all peers. Push intents
209 + * for paths from all peers to each BGP speaker.
210 + */
211 + private void setupIcmpPaths() {
212 + for (BgpSpeaker bgpSpeaker : configInfoService.getBgpSpeakers()
213 + .values()) {
214 + log.debug("Start to set up ICMP paths for BGP speaker: {}",
215 + bgpSpeaker);
216 + ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
217 + List<InterfaceAddress> interfaceAddresses = bgpSpeaker
218 + .interfaceAddresses();
219 +
220 + for (BgpPeer bgpPeer : configInfoService.getBgpPeers().values()) {
221 +
222 + Interface peerInterface = interfaceService.getInterface(
223 + bgpPeer.connectPoint());
224 +
225 + if (peerInterface == null) {
226 + log.error("Can not find the corresponding Interface from "
227 + + "configuration for BGP peer {}",
228 + bgpPeer.ipAddress());
229 + continue;
230 + }
231 + IpAddress bgpdAddress = null;
232 + for (InterfaceAddress interfaceAddress : interfaceAddresses) {
233 + if (interfaceAddress.connectPoint().equals(
234 + peerInterface.connectPoint())) {
235 + bgpdAddress = interfaceAddress.ipAddress();
236 + break;
237 + }
238 +
239 + }
240 + if (bgpdAddress == null) {
241 + log.debug("There is no IP address for bgpPeer: {} on "
242 + + "interface port: {}", bgpPeer,
243 + bgpPeer.connectPoint());
244 + return;
245 + }
246 +
247 + IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
248 + ConnectPoint bgpdPeerConnectPoint = peerInterface.connectPoint();
249 +
250 + // install intent for ICMP path from BGPd to BGP peer
251 + TrafficSelector selector = DefaultTrafficSelector.builder()
252 + .matchEthType(Ethernet.TYPE_IPV4)
253 + .matchIPProtocol(IPv4.PROTOCOL_ICMP)
254 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
255 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
256 + .build();
257 +
258 + TrafficTreatment treatment = DefaultTrafficTreatment.builder()
259 + .build();
260 +
261 + PointToPointIntent intent = new PointToPointIntent(
262 + nextIntentId(), selector, treatment,
263 + bgpdConnectPoint, bgpdPeerConnectPoint);
264 + intentService.submit(intent);
265 + log.debug("Submitted ICMP path intent from BGPd {} to peer {} :"
266 + + " {}", bgpdAddress, bgpdPeerAddress, intent);
267 +
268 + // install intent for reversed ICMP path from BGP peer to BGPd
269 + selector = DefaultTrafficSelector.builder()
270 + .matchEthType(Ethernet.TYPE_IPV4)
271 + .matchIPProtocol(IPv4.PROTOCOL_ICMP)
272 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toRealInt(), IPV4_BIT_LENGTH))
273 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toRealInt(), IPV4_BIT_LENGTH))
274 + .build();
275 +
276 + PointToPointIntent reversedIntent = new PointToPointIntent(
277 + nextIntentId(), selector, treatment,
278 + bgpdPeerConnectPoint, bgpdConnectPoint);
279 + intentService.submit(reversedIntent);
280 + log.debug("Submitted ICMP path intent from BGP peer {} to BGPd"
281 + + " {} : {}",
282 + bgpdPeerAddress, bgpdAddress, reversedIntent);
283 + }
284 + }
285 + }
286 +
287 + private IntentId nextIntentId() {
288 + return new IntentId(intentId++);
289 + }
290 +}
...@@ -5,6 +5,11 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,6 +5,11 @@ import static org.slf4j.LoggerFactory.getLogger;
5 import org.apache.felix.scr.annotations.Activate; 5 import org.apache.felix.scr.annotations.Activate;
6 import org.apache.felix.scr.annotations.Component; 6 import org.apache.felix.scr.annotations.Component;
7 import org.apache.felix.scr.annotations.Deactivate; 7 import org.apache.felix.scr.annotations.Deactivate;
8 +import org.apache.felix.scr.annotations.Reference;
9 +import org.apache.felix.scr.annotations.ReferenceCardinality;
10 +import org.onlab.onos.net.host.HostService;
11 +import org.onlab.onos.net.intent.IntentService;
12 +import org.onlab.onos.sdnip.config.SdnIpConfigReader;
8 import org.slf4j.Logger; 13 import org.slf4j.Logger;
9 14
10 /** 15 /**
...@@ -15,9 +20,27 @@ public class SdnIp { ...@@ -15,9 +20,27 @@ public class SdnIp {
15 20
16 private final Logger log = getLogger(getClass()); 21 private final Logger log = getLogger(getClass());
17 22
23 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
24 + protected IntentService intentService;
25 +
26 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
27 + protected HostService hostService;
28 +
29 + private SdnIpConfigReader config;
30 + private PeerConnectivity peerConnectivity;
31 +
18 @Activate 32 @Activate
19 protected void activate() { 33 protected void activate() {
20 log.debug("SDN-IP started"); 34 log.debug("SDN-IP started");
35 +
36 + config = new SdnIpConfigReader();
37 + config.init();
38 +
39 + InterfaceService interfaceService = new HostServiceBasedInterfaceService(hostService);
40 +
41 + peerConnectivity = new PeerConnectivity(config, interfaceService, intentService);
42 + peerConnectivity.start();
43 +
21 } 44 }
22 45
23 @Deactivate 46 @Deactivate
......
1 +package org.onlab.onos.sdnip.config;
2 +
3 +import java.util.Objects;
4 +
5 +import org.codehaus.jackson.annotate.JsonProperty;
6 +import org.onlab.onos.net.ConnectPoint;
7 +import org.onlab.onos.net.DeviceId;
8 +import org.onlab.onos.net.PortNumber;
9 +import org.onlab.packet.IpAddress;
10 +
11 +import com.google.common.base.MoreObjects;
12 +
13 +/**
14 + * Configuration details for a BGP peer.
15 + */
16 +public class BgpPeer {
17 + private final ConnectPoint connectPoint;
18 + private final IpAddress ipAddress;
19 +
20 + /**
21 + * Creates a new BgpPeer.
22 + *
23 + * @param dpid the DPID of the switch the peer is attached at, as a String
24 + * @param port the port the peer is attached at
25 + * @param ipAddress the IP address of the peer as a String
26 + */
27 + public BgpPeer(@JsonProperty("attachmentDpid") String dpid,
28 + @JsonProperty("attachmentPort") int port,
29 + @JsonProperty("ipAddress") String ipAddress) {
30 + this.connectPoint = new ConnectPoint(
31 + DeviceId.deviceId(SdnIpConfigReader.dpidToUri(dpid)),
32 + PortNumber.portNumber(port));
33 + this.ipAddress = IpAddress.valueOf(ipAddress);
34 + }
35 +
36 + /**
37 + * Gets the connection point of the peer.
38 + *
39 + * @return the connection point
40 + */
41 + public ConnectPoint connectPoint() {
42 + return connectPoint;
43 + }
44 +
45 + /**
46 + * Gets the IP address of the peer.
47 + *
48 + * @return the IP address
49 + */
50 + public IpAddress ipAddress() {
51 + return ipAddress;
52 + }
53 +
54 + @Override
55 + public int hashCode() {
56 + return Objects.hash(connectPoint, ipAddress);
57 + }
58 +
59 + @Override
60 + public boolean equals(Object obj) {
61 + if (obj == this) {
62 + return true;
63 + }
64 +
65 + if (!(obj instanceof BgpPeer)) {
66 + return false;
67 + }
68 +
69 + BgpPeer that = (BgpPeer) obj;
70 + return Objects.equals(this.connectPoint, that.connectPoint)
71 + && Objects.equals(this.ipAddress, that.ipAddress);
72 + }
73 +
74 + @Override
75 + public String toString() {
76 + return MoreObjects.toStringHelper(getClass())
77 + .add("connectPoint", connectPoint)
78 + .add("ipAddress", ipAddress)
79 + .toString();
80 + }
81 +}
1 +package org.onlab.onos.sdnip.config;
2 +
3 +import java.util.List;
4 +import java.util.Objects;
5 +
6 +import org.codehaus.jackson.annotate.JsonCreator;
7 +import org.codehaus.jackson.annotate.JsonProperty;
8 +import org.onlab.onos.net.ConnectPoint;
9 +import org.onlab.onos.net.DeviceId;
10 +import org.onlab.onos.net.PortNumber;
11 +import org.onlab.packet.MacAddress;
12 +
13 +import com.google.common.base.MoreObjects;
14 +
15 +/**
16 + * Represents a BGP daemon in SDN network.
17 + * <p/>
18 + * Each BGP speaker has a attachment point, which includes a switch DPID and a
19 + * switch port. Each BGP speaker has one MAC address and several IP addresses,
20 + * which are used to peer with BGP peers outside the SDN network. For each
21 + * peer outside the SDN network, we configure a different IP address to BGP
22 + * speaker inside the SDN network.
23 + * <p/>
24 + * Each BGP speaker has a name, which is a unique identifying String that is
25 + * used to reference this speaker in the configuration.
26 + */
27 +public class BgpSpeaker {
28 + private final String name;
29 + private final ConnectPoint connectPoint;
30 + private final MacAddress macAddress;
31 + private List<InterfaceAddress> interfaceAddresses;
32 +
33 + /**
34 + * Class constructor used by the JSON library to create an object.
35 + *
36 + * @param name the name of the BGP speaker inside SDN network
37 + * @param attachmentDpid the DPID where the BGP speaker is attached to
38 + * @param attachmentPort the port where the BGP speaker is attached to
39 + * @param macAddress the MAC address of the BGP speaker
40 + */
41 + @JsonCreator
42 + public BgpSpeaker(@JsonProperty("name") String name,
43 + @JsonProperty("attachmentDpid") String attachmentDpid,
44 + @JsonProperty("attachmentPort") int attachmentPort,
45 + @JsonProperty("macAddress") String macAddress) {
46 +
47 + this.name = name;
48 + this.macAddress = MacAddress.valueOf(macAddress);
49 + this.connectPoint = new ConnectPoint(
50 + DeviceId.deviceId(SdnIpConfigReader.dpidToUri(attachmentDpid)),
51 + PortNumber.portNumber(attachmentPort));
52 + }
53 +
54 + /**
55 + * Sets the addresses we configured for the BGP speaker on all virtual
56 + * {@link Interface}s.
57 + *
58 + * @param interfaceAddresses a list of IP addresses of the BGP speaker
59 + * configured on all virtual interfaces
60 + */
61 + @JsonProperty("interfaceAddresses")
62 + public void setInterfaceAddresses(
63 + List<InterfaceAddress> interfaceAddresses) {
64 + this.interfaceAddresses = interfaceAddresses;
65 + }
66 +
67 + /**
68 + * Gets the BGP speaker name.
69 + *
70 + * @return the BGP speaker name
71 + */
72 + public String name() {
73 + return name;
74 + }
75 +
76 + /**
77 + * Gets the connect point where the BGP speaker is attached.
78 + *
79 + * @return the connect point
80 + */
81 + public ConnectPoint connectPoint() {
82 + return connectPoint;
83 + }
84 +
85 + /**
86 + * Gets the MAC address of the BGP speaker.
87 + *
88 + * @return the MAC address
89 + */
90 + public MacAddress macAddress() {
91 + return macAddress;
92 + }
93 +
94 + /**
95 + * Gets all IP addresses configured on all {@link Interface}s of the
96 + * BGP speaker.
97 + *
98 + * @return a list of IP addresses of the BGP speaker configured on all
99 + * virtual interfaces
100 + */
101 + public List<InterfaceAddress> interfaceAddresses() {
102 + return interfaceAddresses;
103 + }
104 +
105 + @Override
106 + public boolean equals(Object other) {
107 + if (!(other instanceof BgpSpeaker)) {
108 + return false;
109 + }
110 +
111 + BgpSpeaker otherBgpSpeaker = (BgpSpeaker) other;
112 +
113 + return name.equals(otherBgpSpeaker.name) &&
114 + connectPoint.equals(
115 + otherBgpSpeaker.connectPoint) &&
116 + macAddress.equals(otherBgpSpeaker.macAddress) &&
117 + interfaceAddresses.equals(otherBgpSpeaker.interfaceAddresses);
118 + }
119 +
120 + @Override
121 + public int hashCode() {
122 + return Objects.hash(name, connectPoint, macAddress,
123 + interfaceAddresses);
124 +
125 + }
126 +
127 + @Override
128 + public String toString() {
129 + return MoreObjects.toStringHelper(getClass())
130 + .add("speakerName", name)
131 + .add("connectPoint", connectPoint)
132 + .add("macAddress", macAddress)
133 + .add("interfaceAddresses", interfaceAddresses)
134 + .toString();
135 + }
136 +}
1 +package org.onlab.onos.sdnip.config;
2 +
3 +import java.util.Collections;
4 +import java.util.List;
5 +
6 +import org.codehaus.jackson.annotate.JsonProperty;
7 +
8 +/**
9 + * Contains the configuration data for SDN-IP that has been read from a
10 + * JSON-formatted configuration file.
11 + */
12 +public class Configuration {
13 + // We call the BGP routers in our SDN network the BGP speakers, and call
14 + // the BGP routers outside our SDN network the BGP peers.
15 + private List<BgpSpeaker> bgpSpeakers;
16 + private List<BgpPeer> peers;
17 +
18 + /**
19 + * Default constructor.
20 + */
21 + public Configuration() {
22 + }
23 +
24 + /**
25 + * Gets a list of bgpSpeakers in the system, represented by
26 + * {@link BgpSpeaker} objects.
27 + *
28 + * @return the list of BGP speakers
29 + */
30 + public List<BgpSpeaker> getBgpSpeakers() {
31 + return Collections.unmodifiableList(bgpSpeakers);
32 + }
33 +
34 + /**
35 + * Sets a list of bgpSpeakers in the system.
36 + *
37 + * @param bgpSpeakers the list of BGP speakers
38 + */
39 + @JsonProperty("bgpSpeakers")
40 + public void setBgpSpeakers(List<BgpSpeaker> bgpSpeakers) {
41 + this.bgpSpeakers = bgpSpeakers;
42 + }
43 +
44 + /**
45 + * Gets a list of BGP peers we are configured to peer with. Peers are
46 + * represented by {@link BgpPeer} objects.
47 + *
48 + * @return the list of BGP peers
49 + */
50 + public List<BgpPeer> getPeers() {
51 + return Collections.unmodifiableList(peers);
52 + }
53 +
54 + /**
55 + * Sets a list of BGP peers we are configured to peer with.
56 + *
57 + * @param peers the list of BGP peers
58 + */
59 + @JsonProperty("bgpPeers")
60 + public void setPeers(List<BgpPeer> peers) {
61 + this.peers = peers;
62 + }
63 +
64 +}
1 +package org.onlab.onos.sdnip.config;
2 +
3 +import java.util.Objects;
4 +import java.util.Set;
5 +
6 +import org.onlab.onos.net.ConnectPoint;
7 +import org.onlab.onos.net.host.PortAddresses;
8 +import org.onlab.packet.IpPrefix;
9 +import org.onlab.packet.MacAddress;
10 +
11 +import com.google.common.base.MoreObjects;
12 +import com.google.common.collect.Sets;
13 +
14 +/**
15 + * An Interface is a set of addresses that are logically mapped to a switch
16 + * port in the network.
17 + */
18 +public class Interface {
19 + private final ConnectPoint connectPoint;
20 + private final Set<IpPrefix> ipAddresses;
21 + private final MacAddress macAddress;
22 +
23 + /**
24 + * Creates an Interface based on a connection point, a set of IP addresses
25 + * and a MAC address.
26 + *
27 + * @param connectPoint the connect point this interface is mapped to
28 + * @param prefixAddress the IP addresses for the interface
29 + * @param macAddress the MAC address of the interface
30 + */
31 + public Interface(ConnectPoint connectPoint, Set<IpPrefix> prefixAddress,
32 + MacAddress macAddress) {
33 + this.connectPoint = connectPoint;
34 + this.ipAddresses = Sets.newHashSet(prefixAddress);
35 + this.macAddress = macAddress;
36 + }
37 +
38 + /**
39 + * Creates an Interface based on a PortAddresses object.
40 + *
41 + * @param portAddresses the PortAddresses object to turn into an Interface
42 + */
43 + public Interface(PortAddresses portAddresses) {
44 + connectPoint = portAddresses.connectPoint();
45 + ipAddresses = Sets.newHashSet(portAddresses.ips());
46 + macAddress = portAddresses.mac();
47 + }
48 +
49 + /**
50 + * Retrieves the connection point that this interface maps to.
51 + *
52 + * @return the connection point
53 + */
54 + public ConnectPoint connectPoint() {
55 + return connectPoint;
56 + }
57 +
58 + /**
59 + * Retrieves the set of IP addresses that are assigned to the interface.
60 + *
61 + * @return the set of IP addresses
62 + */
63 + public Set<IpPrefix> ips() {
64 + return ipAddresses;
65 + }
66 +
67 + /**
68 + * Retrieves the MAC address that is assigned to the interface.
69 + *
70 + * @return the MAC address
71 + */
72 + public MacAddress mac() {
73 + return macAddress;
74 + }
75 +
76 + @Override
77 + public boolean equals(Object other) {
78 + if (!(other instanceof Interface)) {
79 + return false;
80 + }
81 +
82 + Interface otherInterface = (Interface) other;
83 +
84 + return connectPoint.equals(otherInterface.connectPoint) &&
85 + ipAddresses.equals(otherInterface.ipAddresses) &&
86 + macAddress.equals(otherInterface.macAddress);
87 + }
88 +
89 + @Override
90 + public int hashCode() {
91 + return Objects.hash(connectPoint, ipAddresses, macAddress);
92 + }
93 +
94 + @Override
95 + public String toString() {
96 + return MoreObjects.toStringHelper(getClass())
97 + .add("connectPoint", connectPoint)
98 + .add("ipAddresses", ipAddresses)
99 + .add("macAddress", macAddress)
100 + .toString();
101 + }
102 +}
1 +package org.onlab.onos.sdnip.config;
2 +
3 +import java.util.Objects;
4 +
5 +import org.codehaus.jackson.annotate.JsonProperty;
6 +import org.onlab.onos.net.ConnectPoint;
7 +import org.onlab.onos.net.DeviceId;
8 +import org.onlab.onos.net.PortNumber;
9 +import org.onlab.packet.IpAddress;
10 +
11 +import com.google.common.base.MoreObjects;
12 +
13 +/**
14 + * Represents an address of a {@link BgpSpeaker} configured on an
15 + * {@link Interface}.
16 + * <p/>
17 + * Each InterfaceAddress includes the interface name and an IP address.
18 + */
19 +public class InterfaceAddress {
20 + private final ConnectPoint connectPoint;
21 + private final IpAddress ipAddress;
22 +
23 + /**
24 + * Creates an InterfaceAddress object.
25 + *
26 + * @param dpid the DPID of the interface as a String
27 + * @param port the port of the interface
28 + * @param ipAddress the IP address of a {@link BgpSpeaker} configured on
29 + * the interface
30 + */
31 + public InterfaceAddress(@JsonProperty("interfaceDpid") String dpid,
32 + @JsonProperty("interfacePort") int port,
33 + @JsonProperty("ipAddress") String ipAddress) {
34 + this.connectPoint = new ConnectPoint(
35 + DeviceId.deviceId(SdnIpConfigReader.dpidToUri(dpid)),
36 + PortNumber.portNumber(port));
37 + this.ipAddress = IpAddress.valueOf(ipAddress);
38 + }
39 +
40 + /**
41 + * Gets the connection point of the peer.
42 + *
43 + * @return the connection point
44 + */
45 + public ConnectPoint connectPoint() {
46 + return connectPoint;
47 + }
48 +
49 + /**
50 + * Gets the IP address of a BGP speaker configured on an {@link Interface}.
51 + *
52 + * @return the IP address
53 + */
54 + public IpAddress ipAddress() {
55 + return ipAddress;
56 + }
57 +
58 + @Override
59 + public int hashCode() {
60 + return Objects.hash(connectPoint, ipAddress);
61 + }
62 +
63 + @Override
64 + public boolean equals(Object obj) {
65 + if (obj == this) {
66 + return true;
67 + }
68 +
69 + if (!(obj instanceof InterfaceAddress)) {
70 + return false;
71 + }
72 +
73 + InterfaceAddress that = (InterfaceAddress) obj;
74 + return Objects.equals(this.connectPoint, that.connectPoint)
75 + && Objects.equals(this.ipAddress, that.ipAddress);
76 + }
77 +
78 + @Override
79 + public String toString() {
80 + return MoreObjects.toStringHelper(getClass())
81 + .add("connectPoint", connectPoint)
82 + .add("ipAddress", ipAddress)
83 + .toString();
84 + }
85 +}
1 +package org.onlab.onos.sdnip.config;
2 +
3 +import java.io.File;
4 +import java.io.IOException;
5 +import java.util.Collections;
6 +import java.util.Map;
7 +import java.util.concurrent.ConcurrentHashMap;
8 +
9 +import org.codehaus.jackson.map.ObjectMapper;
10 +import org.onlab.packet.IpAddress;
11 +import org.slf4j.Logger;
12 +import org.slf4j.LoggerFactory;
13 +
14 +/**
15 + * SDN-IP Config Reader provides IConfigInfoService
16 + * by reading from an SDN-IP configuration file.
17 + * It must be enabled on the nodes within the cluster
18 + * not running SDN-IP.
19 + * <p/>
20 + * TODO: As a long term solution, a module providing
21 + * general network configuration to ONOS nodes should be used.
22 + */
23 +public class SdnIpConfigReader implements SdnIpConfigService {
24 +
25 + private static final Logger log = LoggerFactory.getLogger(SdnIpConfigReader.class);
26 +
27 + private static final String DEFAULT_CONFIG_FILE = "config/sdnip.json";
28 + private String configFileName = DEFAULT_CONFIG_FILE;
29 + //private Map<String, Interface> interfaces;
30 + // We call the BGP routers in our SDN network the BGP speakers, and call
31 + // the BGP routers outside our SDN network the BGP peers.
32 + private Map<String, BgpSpeaker> bgpSpeakers;
33 + private Map<IpAddress, BgpPeer> bgpPeers;
34 + //private InvertedRadixTree<Interface> interfaceRoutes;
35 +
36 + /**
37 + * Reads the info contained in the configuration file.
38 + *
39 + * @param configFilename The name of configuration file for SDN-IP application.
40 + */
41 + private void readConfiguration(String configFilename) {
42 + File gatewaysFile = new File(configFilename);
43 + ObjectMapper mapper = new ObjectMapper();
44 +
45 + try {
46 + Configuration config = mapper.readValue(gatewaysFile, Configuration.class);
47 + /*interfaces = new ConcurrentHashMap<>();
48 + for (Interface intf : config.getInterfaces()) {
49 + interfaces.put(intf.getName(), intf);
50 + }*/
51 + bgpSpeakers = new ConcurrentHashMap<>();
52 + for (BgpSpeaker speaker : config.getBgpSpeakers()) {
53 + bgpSpeakers.put(speaker.name(), speaker);
54 + }
55 + bgpPeers = new ConcurrentHashMap<>();
56 + for (BgpPeer peer : config.getPeers()) {
57 + bgpPeers.put(peer.ipAddress(), peer);
58 + }
59 + } catch (IOException e) {
60 + log.error("Error reading JSON file", e);
61 + //throw new ConfigurationRuntimeException("Error in JSON file", e);
62 + }
63 +
64 + // Populate the interface InvertedRadixTree
65 + /*for (Interface intf : interfaces.values()) {
66 + Ip4Prefix prefix = intf.getIp4Prefix();
67 + String binaryString = RouteEntry.createBinaryString(prefix);
68 + interfaceRoutes.put(binaryString, intf);
69 + }*/
70 + }
71 +
72 + /**
73 + * To find the Interface which has longest matchable IP prefix (sub-network
74 + * prefix) to next hop IP address.
75 + *
76 + * @param address the IP address of next hop router
77 + * @return the Interface which has longest matchable IP prefix
78 + */
79 + /*private Interface longestInterfacePrefixMatch(IpAddress address) {
80 + Ip4Prefix prefixToSearchFor =
81 + new Ip4Prefix(address, (short) Ip4Address.BIT_LENGTH);
82 + String binaryString = RouteEntry.createBinaryString(prefixToSearchFor);
83 +
84 + Iterator<Interface> it =
85 + interfaceRoutes.getValuesForKeysPrefixing(binaryString).iterator();
86 + Interface intf = null;
87 + // Find the last prefix, which will be the longest prefix
88 + while (it.hasNext()) {
89 + intf = it.next();
90 + }
91 +
92 + return intf;
93 + }*/
94 +
95 + /*@Override
96 + public Interface getOutgoingInterface(IpAddress dstIpAddress) {
97 + return longestInterfacePrefixMatch(dstIpAddress);
98 + }*/
99 +
100 + public void init() {
101 + //interfaceRoutes = new ConcurrentInvertedRadixTree<>(
102 + //new DefaultByteArrayNodeFactory());
103 +
104 + // Reading config values
105 + /*String configFilenameParameter = context.getConfigParams(this).get("configfile");
106 + if (configFilenameParameter != null) {
107 + currentConfigFilename = configFilenameParameter;
108 + }*/
109 + log.debug("Config file set to {}", configFileName);
110 +
111 + readConfiguration(configFileName);
112 + }
113 +
114 + /*@Override
115 + public Map<String, Interface> getInterfaces() {
116 + return Collections.unmodifiableMap(interfaces);
117 + }*/
118 +
119 + @Override
120 + public Map<String, BgpSpeaker> getBgpSpeakers() {
121 + return Collections.unmodifiableMap(bgpSpeakers);
122 + }
123 +
124 + @Override
125 + public Map<IpAddress, BgpPeer> getBgpPeers() {
126 + return Collections.unmodifiableMap(bgpPeers);
127 + }
128 +
129 + static String dpidToUri(String dpid) {
130 + return "of:" + dpid.replace(":", "");
131 + }
132 +}
1 +package org.onlab.onos.sdnip.config;
2 +
3 +import java.util.Map;
4 +
5 +import org.onlab.packet.IpAddress;
6 +
7 +/**
8 + * Provides information about the layer 3 properties of the network.
9 + * This is based on IP addresses configured on ports in the network.
10 + */
11 +public interface SdnIpConfigService {
12 +
13 + /**
14 + * Gets the list of virtual external-facing interfaces.
15 + *
16 + * @return the map of interface names to interface objects
17 + */
18 + //public Map<String, Interface> getInterfaces();
19 +
20 + /**
21 + * Gets the list of BGP speakers inside the SDN network.
22 + *
23 + * @return the map of BGP speaker names to BGP speaker objects
24 + */
25 + public Map<String, BgpSpeaker> getBgpSpeakers();
26 +
27 + /**
28 + * Gets the list of configured BGP peers.
29 + *
30 + * @return the map from peer IP address to BgpPeer object
31 + */
32 + public Map<IpAddress, BgpPeer> getBgpPeers();
33 +
34 + /**
35 + * Gets the Interface object for the interface that packets
36 + * to dstIpAddress will be sent out of. Returns null if dstIpAddress is not
37 + * in a directly connected network, or if no interfaces are configured.
38 + *
39 + * @param dstIpAddress destination IP address that we want to match to
40 + * an outgoing interface
41 + * @return the Interface object if one is found, otherwise null
42 + */
43 + //public Interface getOutgoingInterface(IpAddress dstIpAddress);
44 +
45 +}
1 +/**
2 + * SDN-IP configuration.
3 + */
4 +package org.onlab.onos.sdnip.config;
...\ No newline at end of file ...\ No newline at end of file
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
45 <action class="org.onlab.onos.cli.net.DeviceRoleCommand"/> 45 <action class="org.onlab.onos.cli.net.DeviceRoleCommand"/>
46 <completers> 46 <completers>
47 <ref component-id="deviceIdCompleter"/> 47 <ref component-id="deviceIdCompleter"/>
48 - <ref component-id="roleCompleter"/> 48 + <ref component-id="nodeIdCompleter"/>
49 <ref component-id="roleCompleter"/> 49 <ref component-id="roleCompleter"/>
50 <null/> 50 <null/>
51 </completers> 51 </completers>
......
...@@ -20,6 +20,7 @@ public class DefaultHost extends AbstractElement implements Host { ...@@ -20,6 +20,7 @@ public class DefaultHost extends AbstractElement implements Host {
20 private final MacAddress mac; 20 private final MacAddress mac;
21 private final VlanId vlan; 21 private final VlanId vlan;
22 private final HostLocation location; 22 private final HostLocation location;
23 + // FIXME: should be IpAddress
23 private final Set<IpPrefix> ips; 24 private final Set<IpPrefix> ips;
24 25
25 /** 26 /**
......
...@@ -38,6 +38,7 @@ public interface Host extends Element { ...@@ -38,6 +38,7 @@ public interface Host extends Element {
38 * 38 *
39 * @return set of IP addresses; empty if no IP address is bound 39 * @return set of IP addresses; empty if no IP address is bound
40 */ 40 */
41 + // FIXME: Switch to IpAddress
41 Set<IpPrefix> ipAddresses(); 42 Set<IpPrefix> ipAddresses();
42 43
43 /** 44 /**
......
...@@ -4,8 +4,6 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -4,8 +4,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
4 4
5 import java.util.Objects; 5 import java.util.Objects;
6 6
7 -import org.onlab.onos.net.link.LinkDescription;
8 -
9 import com.google.common.base.MoreObjects; 7 import com.google.common.base.MoreObjects;
10 8
11 // TODO Consider renaming. 9 // TODO Consider renaming.
...@@ -69,16 +67,6 @@ public final class LinkKey { ...@@ -69,16 +67,6 @@ public final class LinkKey {
69 return new LinkKey(link.src(), link.dst()); 67 return new LinkKey(link.src(), link.dst());
70 } 68 }
71 69
72 - /**
73 - * Creates a link identifier for the specified link.
74 - *
75 - * @param desc link description
76 - * @return a link identifier
77 - */
78 - public static LinkKey linkKey(LinkDescription desc) {
79 - return new LinkKey(desc.src(), desc.dst());
80 - }
81 -
82 @Override 70 @Override
83 public int hashCode() { 71 public int hashCode() {
84 return Objects.hash(src(), dst); 72 return Objects.hash(src(), dst);
......
1 package org.onlab.onos.net.host; 1 package org.onlab.onos.net.host;
2 2
3 -import java.util.Set;
4 -
5 import org.onlab.onos.net.ConnectPoint; 3 import org.onlab.onos.net.ConnectPoint;
6 import org.onlab.onos.net.HostId; 4 import org.onlab.onos.net.HostId;
7 5
...@@ -47,20 +45,4 @@ public interface HostAdminService { ...@@ -47,20 +45,4 @@ public interface HostAdminService {
47 */ 45 */
48 void clearAddresses(ConnectPoint connectPoint); 46 void clearAddresses(ConnectPoint connectPoint);
49 47
50 - /**
51 - * Returns the addresses information for all connection points.
52 - *
53 - * @return the set of address bindings for all connection points
54 - */
55 - Set<PortAddresses> getAddressBindings();
56 -
57 - /**
58 - * Retrieves the addresses that have been bound to the given connection
59 - * point.
60 - *
61 - * @param connectPoint the connection point to retrieve address bindings
62 - * for
63 - * @return addresses bound to the port
64 - */
65 - PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint);
66 } 48 }
......
...@@ -37,6 +37,7 @@ public interface HostDescription extends Description { ...@@ -37,6 +37,7 @@ public interface HostDescription extends Description {
37 * 37 *
38 * @return host IP address 38 * @return host IP address
39 */ 39 */
40 + // FIXME: Switch to IpAddress
40 IpPrefix ipAddress(); 41 IpPrefix ipAddress();
41 42
42 } 43 }
......
...@@ -110,6 +110,23 @@ public interface HostService { ...@@ -110,6 +110,23 @@ public interface HostService {
110 void requestMac(IpAddress ip); 110 void requestMac(IpAddress ip);
111 111
112 /** 112 /**
113 + * Returns the addresses information for all connection points.
114 + *
115 + * @return the set of address bindings for all connection points
116 + */
117 + Set<PortAddresses> getAddressBindings();
118 +
119 + /**
120 + * Retrieves the addresses that have been bound to the given connection
121 + * point.
122 + *
123 + * @param connectPoint the connection point to retrieve address bindings
124 + * for
125 + * @return addresses bound to the port
126 + */
127 + PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint);
128 +
129 + /**
113 * Adds the specified host listener. 130 * Adds the specified host listener.
114 * 131 *
115 * @param listener host listener 132 * @param listener host listener
......
...@@ -29,6 +29,7 @@ public interface HostStore extends Store<HostEvent, HostStoreDelegate> { ...@@ -29,6 +29,7 @@ public interface HostStore extends Store<HostEvent, HostStoreDelegate> {
29 HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId, 29 HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
30 HostDescription hostDescription); 30 HostDescription hostDescription);
31 31
32 + // FIXME: API to remove only IpAddress is missing
32 /** 33 /**
33 * Removes the specified host from the inventory. 34 * Removes the specified host from the inventory.
34 * 35 *
...@@ -81,6 +82,7 @@ public interface HostStore extends Store<HostEvent, HostStoreDelegate> { ...@@ -81,6 +82,7 @@ public interface HostStore extends Store<HostEvent, HostStoreDelegate> {
81 * @param ip ip address 82 * @param ip ip address
82 * @return set of hosts with the given IP 83 * @return set of hosts with the given IP
83 */ 84 */
85 + // FIXME: Switch to IpAddress
84 Set<Host> getHosts(IpPrefix ip); 86 Set<Host> getHosts(IpPrefix ip);
85 87
86 /** 88 /**
......
...@@ -17,6 +17,7 @@ import com.google.common.base.MoreObjects; ...@@ -17,6 +17,7 @@ import com.google.common.base.MoreObjects;
17 public class PortAddresses { 17 public class PortAddresses {
18 18
19 private final ConnectPoint connectPoint; 19 private final ConnectPoint connectPoint;
20 + // TODO: Should this be IpAddress or IpPrefix?
20 private final Set<IpPrefix> ipAddresses; 21 private final Set<IpPrefix> ipAddresses;
21 private final MacAddress macAddress; 22 private final MacAddress macAddress;
22 23
......
1 package org.onlab.onos.net.proxyarp; 1 package org.onlab.onos.net.proxyarp;
2 2
3 +import org.onlab.onos.net.ConnectPoint;
3 import org.onlab.onos.net.packet.PacketContext; 4 import org.onlab.onos.net.packet.PacketContext;
4 import org.onlab.packet.Ethernet; 5 import org.onlab.packet.Ethernet;
5 import org.onlab.packet.IpPrefix; 6 import org.onlab.packet.IpPrefix;
...@@ -23,8 +24,9 @@ public interface ProxyArpService { ...@@ -23,8 +24,9 @@ public interface ProxyArpService {
23 * will be flooded at all edge ports. 24 * will be flooded at all edge ports.
24 * 25 *
25 * @param eth an arp request 26 * @param eth an arp request
27 + * @param inPort the port the request was received on
26 */ 28 */
27 - void reply(Ethernet eth); 29 + void reply(Ethernet eth, ConnectPoint inPort);
28 30
29 /** 31 /**
30 * Forwards an ARP request to its destination. Floods at the edge the ARP request if the 32 * Forwards an ARP request to its destination. Floods at the edge the ARP request if the
......
...@@ -75,4 +75,14 @@ public class HostServiceAdapter implements HostService { ...@@ -75,4 +75,14 @@ public class HostServiceAdapter implements HostService {
75 public void removeListener(HostListener listener) { 75 public void removeListener(HostListener listener) {
76 } 76 }
77 77
78 + @Override
79 + public Set<PortAddresses> getAddressBindings() {
80 + return null;
81 + }
82 +
83 + @Override
84 + public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) {
85 + return null;
86 + }
87 +
78 } 88 }
......
...@@ -5,6 +5,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -5,6 +5,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
5 import static org.slf4j.LoggerFactory.getLogger; 5 import static org.slf4j.LoggerFactory.getLogger;
6 6
7 import java.nio.ByteBuffer; 7 import java.nio.ByteBuffer;
8 +import java.util.Collections;
8 import java.util.List; 9 import java.util.List;
9 import java.util.Map.Entry; 10 import java.util.Map.Entry;
10 import java.util.Set; 11 import java.util.Set;
...@@ -15,6 +16,7 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -15,6 +16,7 @@ import org.apache.felix.scr.annotations.Deactivate;
15 import org.apache.felix.scr.annotations.Reference; 16 import org.apache.felix.scr.annotations.Reference;
16 import org.apache.felix.scr.annotations.ReferenceCardinality; 17 import org.apache.felix.scr.annotations.ReferenceCardinality;
17 import org.apache.felix.scr.annotations.Service; 18 import org.apache.felix.scr.annotations.Service;
19 +import org.onlab.onos.net.ConnectPoint;
18 import org.onlab.onos.net.Device; 20 import org.onlab.onos.net.Device;
19 import org.onlab.onos.net.Host; 21 import org.onlab.onos.net.Host;
20 import org.onlab.onos.net.HostId; 22 import org.onlab.onos.net.HostId;
...@@ -27,6 +29,7 @@ import org.onlab.onos.net.device.DeviceService; ...@@ -27,6 +29,7 @@ import org.onlab.onos.net.device.DeviceService;
27 import org.onlab.onos.net.flow.DefaultTrafficTreatment; 29 import org.onlab.onos.net.flow.DefaultTrafficTreatment;
28 import org.onlab.onos.net.flow.TrafficTreatment; 30 import org.onlab.onos.net.flow.TrafficTreatment;
29 import org.onlab.onos.net.host.HostService; 31 import org.onlab.onos.net.host.HostService;
32 +import org.onlab.onos.net.host.PortAddresses;
30 import org.onlab.onos.net.link.LinkEvent; 33 import org.onlab.onos.net.link.LinkEvent;
31 import org.onlab.onos.net.link.LinkListener; 34 import org.onlab.onos.net.link.LinkListener;
32 import org.onlab.onos.net.link.LinkService; 35 import org.onlab.onos.net.link.LinkService;
...@@ -37,7 +40,9 @@ import org.onlab.onos.net.packet.PacketService; ...@@ -37,7 +40,9 @@ import org.onlab.onos.net.packet.PacketService;
37 import org.onlab.onos.net.proxyarp.ProxyArpService; 40 import org.onlab.onos.net.proxyarp.ProxyArpService;
38 import org.onlab.packet.ARP; 41 import org.onlab.packet.ARP;
39 import org.onlab.packet.Ethernet; 42 import org.onlab.packet.Ethernet;
43 +import org.onlab.packet.IpAddress;
40 import org.onlab.packet.IpPrefix; 44 import org.onlab.packet.IpPrefix;
45 +import org.onlab.packet.MacAddress;
41 import org.onlab.packet.VlanId; 46 import org.onlab.packet.VlanId;
42 import org.slf4j.Logger; 47 import org.slf4j.Logger;
43 48
...@@ -101,12 +106,46 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -101,12 +106,46 @@ public class ProxyArpManager implements ProxyArpService {
101 } 106 }
102 107
103 @Override 108 @Override
104 - public void reply(Ethernet eth) { 109 + public void reply(Ethernet eth, ConnectPoint inPort) {
105 checkNotNull(eth, REQUEST_NULL); 110 checkNotNull(eth, REQUEST_NULL);
106 checkArgument(eth.getEtherType() == Ethernet.TYPE_ARP, 111 checkArgument(eth.getEtherType() == Ethernet.TYPE_ARP,
107 REQUEST_NOT_ARP); 112 REQUEST_NOT_ARP);
108 ARP arp = (ARP) eth.getPayload(); 113 ARP arp = (ARP) eth.getPayload();
109 checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST); 114 checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST);
115 + checkNotNull(inPort);
116 +
117 + // If the source address matches one of our external addresses
118 + // it could be a request from an internal host to an external
119 + // address. Forward it over to the correct port.
120 + IpAddress source = IpAddress.valueOf(arp.getSenderProtocolAddress());
121 + PortAddresses sourceAddresses = findOutsidePortInSubnet(source);
122 + if (sourceAddresses != null && !isOutsidePort(inPort)) {
123 + for (IpPrefix subnet : sourceAddresses.ips()) {
124 + if (subnet.toIpAddress().equals(source)) {
125 + sendTo(eth, sourceAddresses.connectPoint());
126 + return;
127 + }
128 + }
129 + }
130 +
131 + // If the request came from outside the network, only reply if it was
132 + // for one of our external addresses.
133 + if (isOutsidePort(inPort)) {
134 + IpAddress target = IpAddress.valueOf(arp.getTargetProtocolAddress());
135 + PortAddresses addresses = hostService.getAddressBindingsForPort(inPort);
136 +
137 + for (IpPrefix interfaceAddress : addresses.ips()) {
138 + if (interfaceAddress.toIpAddress().equals(target)) {
139 + Ethernet arpReply = buildArpReply(interfaceAddress,
140 + addresses.mac(), eth);
141 + sendTo(arpReply, inPort);
142 + }
143 + }
144 +
145 + return;
146 + }
147 +
148 + // Continue with normal proxy ARP case
110 149
111 VlanId vlan = VlanId.vlanId(eth.getVlanID()); 150 VlanId vlan = VlanId.vlanId(eth.getVlanID());
112 Set<Host> hosts = hostService.getHostsByIp(IpPrefix.valueOf(arp 151 Set<Host> hosts = hostService.getHostsByIp(IpPrefix.valueOf(arp
...@@ -128,12 +167,62 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -128,12 +167,62 @@ public class ProxyArpManager implements ProxyArpService {
128 return; 167 return;
129 } 168 }
130 169
131 - Ethernet arpReply = buildArpReply(dst, eth); 170 + Ethernet arpReply = buildArpReply(dst.ipAddresses().iterator().next(),
171 + dst.mac(), eth);
132 // TODO: check send status with host service. 172 // TODO: check send status with host service.
173 + sendTo(arpReply, src.location());
174 + }
175 +
176 + /**
177 + * Outputs the given packet out the given port.
178 + *
179 + * @param packet the packet to send
180 + * @param outPort the port to send it out
181 + */
182 + private void sendTo(Ethernet packet, ConnectPoint outPort) {
183 + if (internalPorts.containsEntry(
184 + deviceService.getDevice(outPort.deviceId()), outPort.port())) {
185 + // Sanity check to make sure we don't send the packet out an
186 + // internal port and create a loop (could happen due to
187 + // misconfiguration).
188 + return;
189 + }
190 +
133 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder(); 191 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
134 - builder.setOutput(src.location().port()); 192 + builder.setOutput(outPort.port());
135 - packetService.emit(new DefaultOutboundPacket(src.location().deviceId(), 193 + packetService.emit(new DefaultOutboundPacket(outPort.deviceId(),
136 - builder.build(), ByteBuffer.wrap(arpReply.serialize()))); 194 + builder.build(), ByteBuffer.wrap(packet.serialize())));
195 + }
196 +
197 + /**
198 + * Finds the port with an address in the subnet of the target address, if
199 + * one exists.
200 + *
201 + * @param target the target address to find a matching external port for
202 + * @return a PortAddresses object containing the external addresses if one
203 + * was found, otherwise null.
204 + */
205 + private PortAddresses findOutsidePortInSubnet(IpAddress target) {
206 + for (PortAddresses addresses : hostService.getAddressBindings()) {
207 + for (IpPrefix prefix : addresses.ips()) {
208 + if (prefix.contains(target)) {
209 + return new PortAddresses(addresses.connectPoint(),
210 + Collections.singleton(prefix), addresses.mac());
211 + }
212 + }
213 + }
214 + return null;
215 + }
216 +
217 + /**
218 + * Returns whether the given port is an outside-facing port with an IP
219 + * address configured.
220 + *
221 + * @param port the port to check
222 + * @return true if the port is an outside-facing port, otherwise false
223 + */
224 + private boolean isOutsidePort(ConnectPoint port) {
225 + return !hostService.getAddressBindingsForPort(port).ips().isEmpty();
137 } 226 }
138 227
139 @Override 228 @Override
...@@ -167,7 +256,7 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -167,7 +256,7 @@ public class ProxyArpManager implements ProxyArpService {
167 if (arp.getOpCode() == ARP.OP_REPLY) { 256 if (arp.getOpCode() == ARP.OP_REPLY) {
168 forward(ethPkt); 257 forward(ethPkt);
169 } else if (arp.getOpCode() == ARP.OP_REQUEST) { 258 } else if (arp.getOpCode() == ARP.OP_REQUEST) {
170 - reply(ethPkt); 259 + reply(ethPkt, context.inPacket().receivedFrom());
171 } 260 }
172 context.block(); 261 context.block();
173 return true; 262 return true;
...@@ -185,12 +274,16 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -185,12 +274,16 @@ public class ProxyArpManager implements ProxyArpService {
185 274
186 synchronized (externalPorts) { 275 synchronized (externalPorts) {
187 for (Entry<Device, PortNumber> entry : externalPorts.entries()) { 276 for (Entry<Device, PortNumber> entry : externalPorts.entries()) {
277 + ConnectPoint cp = new ConnectPoint(entry.getKey().id(), entry.getValue());
278 + if (isOutsidePort(cp)) {
279 + continue;
280 + }
281 +
188 builder = DefaultTrafficTreatment.builder(); 282 builder = DefaultTrafficTreatment.builder();
189 builder.setOutput(entry.getValue()); 283 builder.setOutput(entry.getValue());
190 packetService.emit(new DefaultOutboundPacket(entry.getKey().id(), 284 packetService.emit(new DefaultOutboundPacket(entry.getKey().id(),
191 builder.build(), buf)); 285 builder.build(), buf));
192 } 286 }
193 -
194 } 287 }
195 } 288 }
196 289
...@@ -234,15 +327,19 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -234,15 +327,19 @@ public class ProxyArpManager implements ProxyArpService {
234 } 327 }
235 328
236 /** 329 /**
237 - * Builds an arp reply based on a request. 330 + * Builds an ARP reply based on a request.
238 - * @param h the host we want to send to 331 + *
239 - * @param request the arp request we got 332 + * @param srcIp the IP address to use as the reply source
240 - * @return an ethernet frame containing the arp reply 333 + * @param srcMac the MAC address to use as the reply source
334 + * @param request the ARP request we got
335 + * @return an Ethernet frame containing the ARP reply
241 */ 336 */
242 - private Ethernet buildArpReply(Host h, Ethernet request) { 337 + private Ethernet buildArpReply(IpPrefix srcIp, MacAddress srcMac,
338 + Ethernet request) {
339 +
243 Ethernet eth = new Ethernet(); 340 Ethernet eth = new Ethernet();
244 eth.setDestinationMACAddress(request.getSourceMACAddress()); 341 eth.setDestinationMACAddress(request.getSourceMACAddress());
245 - eth.setSourceMACAddress(h.mac().getAddress()); 342 + eth.setSourceMACAddress(srcMac.getAddress());
246 eth.setEtherType(Ethernet.TYPE_ARP); 343 eth.setEtherType(Ethernet.TYPE_ARP);
247 eth.setVlanID(request.getVlanID()); 344 eth.setVlanID(request.getVlanID());
248 345
...@@ -253,12 +350,12 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -253,12 +350,12 @@ public class ProxyArpManager implements ProxyArpService {
253 350
254 arp.setProtocolAddressLength((byte) IpPrefix.INET_LEN); 351 arp.setProtocolAddressLength((byte) IpPrefix.INET_LEN);
255 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH); 352 arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
256 - arp.setSenderHardwareAddress(h.mac().getAddress()); 353 + arp.setSenderHardwareAddress(srcMac.getAddress());
257 arp.setTargetHardwareAddress(request.getSourceMACAddress()); 354 arp.setTargetHardwareAddress(request.getSourceMACAddress());
258 355
259 arp.setTargetProtocolAddress(((ARP) request.getPayload()) 356 arp.setTargetProtocolAddress(((ARP) request.getPayload())
260 .getSenderProtocolAddress()); 357 .getSenderProtocolAddress());
261 - arp.setSenderProtocolAddress(h.ipAddresses().iterator().next().toRealInt()); 358 + arp.setSenderProtocolAddress(srcIp.toRealInt());
262 eth.setPayload(arp); 359 eth.setPayload(arp);
263 return eth; 360 return eth;
264 } 361 }
......
...@@ -13,6 +13,7 @@ import java.util.Arrays; ...@@ -13,6 +13,7 @@ import java.util.Arrays;
13 import java.util.Collections; 13 import java.util.Collections;
14 import java.util.Comparator; 14 import java.util.Comparator;
15 import java.util.List; 15 import java.util.List;
16 +import java.util.Set;
16 17
17 import org.junit.Before; 18 import org.junit.Before;
18 import org.junit.Test; 19 import org.junit.Test;
...@@ -31,6 +32,7 @@ import org.onlab.onos.net.device.DeviceService; ...@@ -31,6 +32,7 @@ import org.onlab.onos.net.device.DeviceService;
31 import org.onlab.onos.net.flow.instructions.Instruction; 32 import org.onlab.onos.net.flow.instructions.Instruction;
32 import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction; 33 import org.onlab.onos.net.flow.instructions.Instructions.OutputInstruction;
33 import org.onlab.onos.net.host.HostService; 34 import org.onlab.onos.net.host.HostService;
35 +import org.onlab.onos.net.host.PortAddresses;
34 import org.onlab.onos.net.link.LinkListener; 36 import org.onlab.onos.net.link.LinkListener;
35 import org.onlab.onos.net.link.LinkService; 37 import org.onlab.onos.net.link.LinkService;
36 import org.onlab.onos.net.packet.OutboundPacket; 38 import org.onlab.onos.net.packet.OutboundPacket;
...@@ -50,12 +52,13 @@ import com.google.common.collect.Sets; ...@@ -50,12 +52,13 @@ import com.google.common.collect.Sets;
50 */ 52 */
51 public class ProxyArpManagerTest { 53 public class ProxyArpManagerTest {
52 54
53 - private static final int NUM_DEVICES = 4; 55 + private static final int NUM_DEVICES = 6;
54 private static final int NUM_PORTS_PER_DEVICE = 3; 56 private static final int NUM_PORTS_PER_DEVICE = 3;
55 - private static final int NUM_FLOOD_PORTS = 4; 57 + private static final int NUM_ADDRESS_PORTS = NUM_DEVICES / 2;
58 + private static final int NUM_FLOOD_PORTS = 3;
56 59
57 - private static final IpPrefix IP1 = IpPrefix.valueOf("10.0.0.1/24"); 60 + private static final IpPrefix IP1 = IpPrefix.valueOf("192.168.1.1/24");
58 - private static final IpPrefix IP2 = IpPrefix.valueOf("10.0.0.2/24"); 61 + private static final IpPrefix IP2 = IpPrefix.valueOf("192.168.1.2/24");
59 62
60 private static final ProviderId PID = new ProviderId("of", "foo"); 63 private static final ProviderId PID = new ProviderId("of", "foo");
61 64
...@@ -104,6 +107,9 @@ public class ProxyArpManagerTest { ...@@ -104,6 +107,9 @@ public class ProxyArpManagerTest {
104 * The default topology is a unidirectional ring topology. Each switch has 107 * The default topology is a unidirectional ring topology. Each switch has
105 * 3 ports. Ports 2 and 3 have the links to neighbor switches, and port 1 108 * 3 ports. Ports 2 and 3 have the links to neighbor switches, and port 1
106 * is free (edge port). 109 * is free (edge port).
110 + * The first half of the switches have IP addresses configured on their
111 + * free ports (port 1). The second half of the switches have no IP
112 + * addresses configured.
107 */ 113 */
108 private void createTopology() { 114 private void createTopology() {
109 deviceService = createMock(DeviceService.class); 115 deviceService = createMock(DeviceService.class);
...@@ -114,6 +120,7 @@ public class ProxyArpManagerTest { ...@@ -114,6 +120,7 @@ public class ProxyArpManagerTest {
114 120
115 createDevices(NUM_DEVICES, NUM_PORTS_PER_DEVICE); 121 createDevices(NUM_DEVICES, NUM_PORTS_PER_DEVICE);
116 createLinks(NUM_DEVICES); 122 createLinks(NUM_DEVICES);
123 + addAddressBindings();
117 } 124 }
118 125
119 /** 126 /**
...@@ -138,10 +145,11 @@ public class ProxyArpManagerTest { ...@@ -138,10 +145,11 @@ public class ProxyArpManagerTest {
138 ports.add(port); 145 ports.add(port);
139 } 146 }
140 147
141 - expect(deviceService.getPorts(devId)).andReturn(ports); 148 + expect(deviceService.getPorts(devId)).andReturn(ports).anyTimes();
149 + expect(deviceService.getDevice(devId)).andReturn(device).anyTimes();
142 } 150 }
143 151
144 - expect(deviceService.getDevices()).andReturn(devices); 152 + expect(deviceService.getDevices()).andReturn(devices).anyTimes();
145 replay(deviceService); 153 replay(deviceService);
146 } 154 }
147 155
...@@ -173,6 +181,31 @@ public class ProxyArpManagerTest { ...@@ -173,6 +181,31 @@ public class ProxyArpManagerTest {
173 replay(linkService); 181 replay(linkService);
174 } 182 }
175 183
184 + private void addAddressBindings() {
185 + Set<PortAddresses> addresses = Sets.newHashSet();
186 +
187 + for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) {
188 + ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
189 + IpPrefix prefix1 = IpPrefix.valueOf("10.0." + (2 * i - 1) + ".1/24");
190 + IpPrefix prefix2 = IpPrefix.valueOf("10.0." + (2 * i) + ".1/24");
191 + PortAddresses pa = new PortAddresses(cp,
192 + Sets.newHashSet(prefix1, prefix2), MacAddress.valueOf(i));
193 + addresses.add(pa);
194 +
195 + expect(hostService.getAddressBindingsForPort(cp))
196 + .andReturn(pa).anyTimes();
197 + }
198 +
199 + expect(hostService.getAddressBindings()).andReturn(addresses).anyTimes();
200 +
201 + for (int i = 1; i <= NUM_FLOOD_PORTS; i++) {
202 + ConnectPoint cp = new ConnectPoint(getDeviceId(i + NUM_ADDRESS_PORTS),
203 + P1);
204 + expect(hostService.getAddressBindingsForPort(cp))
205 + .andReturn(new PortAddresses(cp, null, null)).anyTimes();
206 + }
207 + }
208 +
176 /** 209 /**
177 * Tests {@link ProxyArpManager#known(IpPrefix)} in the case where the 210 * Tests {@link ProxyArpManager#known(IpPrefix)} in the case where the
178 * IP address is not known. 211 * IP address is not known.
...@@ -210,10 +243,10 @@ public class ProxyArpManagerTest { ...@@ -210,10 +243,10 @@ public class ProxyArpManagerTest {
210 */ 243 */
211 @Test 244 @Test
212 public void testReplyKnown() { 245 public void testReplyKnown() {
213 - Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN1, LOC2, 246 + Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(4),
214 Collections.singleton(IP1)); 247 Collections.singleton(IP1));
215 248
216 - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1, 249 + Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5),
217 Collections.singleton(IP2)); 250 Collections.singleton(IP2));
218 251
219 expect(hostService.getHostsByIp(IpPrefix.valueOf(IP1.toOctets()))) 252 expect(hostService.getHostsByIp(IpPrefix.valueOf(IP1.toOctets())))
...@@ -224,11 +257,11 @@ public class ProxyArpManagerTest { ...@@ -224,11 +257,11 @@ public class ProxyArpManagerTest {
224 257
225 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); 258 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
226 259
227 - proxyArp.reply(arpRequest); 260 + proxyArp.reply(arpRequest, getLocation(5));
228 261
229 assertEquals(1, packetService.packets.size()); 262 assertEquals(1, packetService.packets.size());
230 Ethernet arpReply = buildArp(ARP.OP_REPLY, MAC1, MAC2, IP1, IP2); 263 Ethernet arpReply = buildArp(ARP.OP_REPLY, MAC1, MAC2, IP1, IP2);
231 - verifyPacketOut(arpReply, LOC1, packetService.packets.get(0)); 264 + verifyPacketOut(arpReply, getLocation(5), packetService.packets.get(0));
232 } 265 }
233 266
234 /** 267 /**
...@@ -238,7 +271,7 @@ public class ProxyArpManagerTest { ...@@ -238,7 +271,7 @@ public class ProxyArpManagerTest {
238 */ 271 */
239 @Test 272 @Test
240 public void testReplyUnknown() { 273 public void testReplyUnknown() {
241 - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1, 274 + Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5),
242 Collections.singleton(IP2)); 275 Collections.singleton(IP2));
243 276
244 expect(hostService.getHostsByIp(IpPrefix.valueOf(IP1.toOctets()))) 277 expect(hostService.getHostsByIp(IpPrefix.valueOf(IP1.toOctets())))
...@@ -249,7 +282,7 @@ public class ProxyArpManagerTest { ...@@ -249,7 +282,7 @@ public class ProxyArpManagerTest {
249 282
250 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); 283 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
251 284
252 - proxyArp.reply(arpRequest); 285 + proxyArp.reply(arpRequest, getLocation(5));
253 286
254 verifyFlood(arpRequest); 287 verifyFlood(arpRequest);
255 } 288 }
...@@ -262,10 +295,10 @@ public class ProxyArpManagerTest { ...@@ -262,10 +295,10 @@ public class ProxyArpManagerTest {
262 */ 295 */
263 @Test 296 @Test
264 public void testReplyDifferentVlan() { 297 public void testReplyDifferentVlan() {
265 - Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN2, LOC2, 298 + Host replyer = new DefaultHost(PID, HID1, MAC1, VLAN2, getLocation(4),
266 Collections.singleton(IP1)); 299 Collections.singleton(IP1));
267 300
268 - Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1, 301 + Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(5),
269 Collections.singleton(IP2)); 302 Collections.singleton(IP2));
270 303
271 expect(hostService.getHostsByIp(IpPrefix.valueOf(IP1.toOctets()))) 304 expect(hostService.getHostsByIp(IpPrefix.valueOf(IP1.toOctets())))
...@@ -276,11 +309,84 @@ public class ProxyArpManagerTest { ...@@ -276,11 +309,84 @@ public class ProxyArpManagerTest {
276 309
277 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1); 310 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
278 311
279 - proxyArp.reply(arpRequest); 312 + proxyArp.reply(arpRequest, getLocation(5));
280 313
281 verifyFlood(arpRequest); 314 verifyFlood(arpRequest);
282 } 315 }
283 316
317 + @Test
318 + public void testReplyToRequestForUs() {
319 + IpPrefix theirIp = IpPrefix.valueOf("10.0.1.254/24");
320 + IpPrefix ourFirstIp = IpPrefix.valueOf("10.0.1.1/24");
321 + IpPrefix ourSecondIp = IpPrefix.valueOf("10.0.2.1/24");
322 + MacAddress ourMac = MacAddress.valueOf(1L);
323 +
324 + Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1,
325 + Collections.singleton(theirIp));
326 +
327 + expect(hostService.getHost(HID2)).andReturn(requestor);
328 + replay(hostService);
329 +
330 + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, theirIp, ourFirstIp);
331 +
332 + proxyArp.reply(arpRequest, LOC1);
333 +
334 + assertEquals(1, packetService.packets.size());
335 + Ethernet arpReply = buildArp(ARP.OP_REPLY, ourMac, MAC2, ourFirstIp, theirIp);
336 + verifyPacketOut(arpReply, LOC1, packetService.packets.get(0));
337 +
338 + // Test a request for the second address on that port
339 + packetService.packets.clear();
340 + arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, theirIp, ourSecondIp);
341 +
342 + proxyArp.reply(arpRequest, LOC1);
343 +
344 + assertEquals(1, packetService.packets.size());
345 + arpReply = buildArp(ARP.OP_REPLY, ourMac, MAC2, ourSecondIp, theirIp);
346 + verifyPacketOut(arpReply, LOC1, packetService.packets.get(0));
347 + }
348 +
349 + @Test
350 + public void testReplyExternalPortBadRequest() {
351 + replay(hostService); // no further host service expectations
352 +
353 + IpPrefix theirIp = IpPrefix.valueOf("10.0.1.254/24");
354 +
355 + // Request for a valid external IP address but coming in the wrong port
356 + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC1, null, theirIp,
357 + IpPrefix.valueOf("10.0.3.1"));
358 + proxyArp.reply(arpRequest, LOC1);
359 + assertEquals(0, packetService.packets.size());
360 +
361 + // Request for a valid internal IP address but coming in an external port
362 + packetService.packets.clear();
363 + arpRequest = buildArp(ARP.OP_REQUEST, MAC1, null, theirIp, IP1);
364 + proxyArp.reply(arpRequest, LOC1);
365 + assertEquals(0, packetService.packets.size());
366 + }
367 +
368 + @Test
369 + public void testReplyToRequestFromUs() {
370 + replay(hostService); // no further host service expectations
371 +
372 + IpPrefix ourIp = IpPrefix.valueOf("10.0.1.1/24");
373 + MacAddress ourMac = MacAddress.valueOf(1L);
374 + IpPrefix theirIp = IpPrefix.valueOf("10.0.1.100/24");
375 +
376 + // This is a request from something inside our network (like a BGP
377 + // daemon) to an external host.
378 + Ethernet arpRequest = buildArp(ARP.OP_REQUEST, ourMac, null, ourIp, theirIp);
379 + proxyArp.reply(arpRequest, getLocation(5));
380 +
381 + assertEquals(1, packetService.packets.size());
382 + verifyPacketOut(arpRequest, getLocation(1), packetService.packets.get(0));
383 +
384 + // The same request from a random external port should fail
385 + packetService.packets.clear();
386 + proxyArp.reply(arpRequest, getLocation(2));
387 + assertEquals(0, packetService.packets.size());
388 + }
389 +
284 /** 390 /**
285 * Tests {@link ProxyArpManager#forward(Ethernet)} in the case where the 391 * Tests {@link ProxyArpManager#forward(Ethernet)} in the case where the
286 * destination host is known. 392 * destination host is known.
...@@ -338,7 +444,8 @@ public class ProxyArpManagerTest { ...@@ -338,7 +444,8 @@ public class ProxyArpManagerTest {
338 }); 444 });
339 445
340 for (int i = 0; i < NUM_FLOOD_PORTS; i++) { 446 for (int i = 0; i < NUM_FLOOD_PORTS; i++) {
341 - ConnectPoint cp = new ConnectPoint(getDeviceId(i + 1), PortNumber.portNumber(1)); 447 + ConnectPoint cp = new ConnectPoint(getDeviceId(NUM_ADDRESS_PORTS + i + 1),
448 + PortNumber.portNumber(1));
342 449
343 OutboundPacket outboundPacket = packetService.packets.get(i); 450 OutboundPacket outboundPacket = packetService.packets.get(i);
344 verifyPacketOut(packet, cp, outboundPacket); 451 verifyPacketOut(packet, cp, outboundPacket);
...@@ -372,6 +479,10 @@ public class ProxyArpManagerTest { ...@@ -372,6 +479,10 @@ public class ProxyArpManagerTest {
372 return DeviceId.deviceId("" + i); 479 return DeviceId.deviceId("" + i);
373 } 480 }
374 481
482 + private static HostLocation getLocation(int i) {
483 + return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
484 + }
485 +
375 /** 486 /**
376 * Builds an ARP packet with the given parameters. 487 * Builds an ARP packet with the given parameters.
377 * 488 *
......
1 package org.onlab.onos.net.topology.impl; 1 package org.onlab.onos.net.topology.impl;
2 2
3 import com.google.common.collect.ImmutableSet; 3 import com.google.common.collect.ImmutableSet;
4 +
4 import org.junit.After; 5 import org.junit.After;
5 import org.junit.Before; 6 import org.junit.Before;
6 import org.junit.Test; 7 import org.junit.Test;
...@@ -21,10 +22,12 @@ import org.onlab.onos.net.topology.TopologyProviderService; ...@@ -21,10 +22,12 @@ import org.onlab.onos.net.topology.TopologyProviderService;
21 22
22 import java.util.List; 23 import java.util.List;
23 import java.util.Set; 24 import java.util.Set;
25 +import java.util.concurrent.Phaser;
26 +import java.util.concurrent.TimeUnit;
27 +import java.util.concurrent.TimeoutException;
24 28
25 -import static org.junit.Assert.assertEquals; 29 +import static org.junit.Assert.*;
26 -import static org.junit.Assert.assertNotNull; 30 +import static org.hamcrest.Matchers.*;
27 -import static org.onlab.junit.TestTools.assertAfter;
28 import static org.onlab.onos.net.NetTestTools.device; 31 import static org.onlab.onos.net.NetTestTools.device;
29 import static org.onlab.onos.net.NetTestTools.link; 32 import static org.onlab.onos.net.NetTestTools.link;
30 import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED; 33 import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_ADDED;
...@@ -41,6 +44,9 @@ public class DefaultTopologyProviderTest { ...@@ -41,6 +44,9 @@ public class DefaultTopologyProviderTest {
41 private TestLinkService linkService = new TestLinkService(); 44 private TestLinkService linkService = new TestLinkService();
42 private TestTopoProviderService providerService; 45 private TestTopoProviderService providerService;
43 46
47 + // phase corresponds to number of topologyChanged called
48 + private Phaser topologyChangedCounts = new Phaser(1);
49 +
44 @Before 50 @Before
45 public void setUp() { 51 public void setUp() {
46 provider.deviceService = deviceService; 52 provider.deviceService = deviceService;
...@@ -66,26 +72,23 @@ public class DefaultTopologyProviderTest { ...@@ -66,26 +72,23 @@ public class DefaultTopologyProviderTest {
66 } 72 }
67 73
68 @Test 74 @Test
69 - public void basics() { 75 + public void basics() throws InterruptedException, TimeoutException {
70 - assertAfter(100, new Runnable() { 76 + assertEquals(1, topologyChangedCounts.awaitAdvanceInterruptibly(0, 1, TimeUnit.SECONDS));
71 - @Override 77 + validateSubmission();
72 - public void run() {
73 - validateSubmission();
74 - }
75 - });
76 } 78 }
77 79
78 @Test 80 @Test
79 - public void eventDriven() { 81 + public void eventDriven() throws InterruptedException, TimeoutException {
80 - assertAfter(100, new Runnable() { 82 + assertEquals(1, topologyChangedCounts.awaitAdvanceInterruptibly(0, 1, TimeUnit.SECONDS));
81 - @Override 83 + validateSubmission();
82 - public void run() { 84 +
83 - validateSubmission(); 85 + deviceService.post(new DeviceEvent(DEVICE_ADDED, device("z"), null));
84 - deviceService.post(new DeviceEvent(DEVICE_ADDED, device("z"), null)); 86 + linkService.post(new LinkEvent(LINK_ADDED, link("z", 1, "a", 4)));
85 - linkService.post(new LinkEvent(LINK_ADDED, link("z", 1, "a", 4))); 87 + assertThat(topologyChangedCounts.awaitAdvanceInterruptibly(1, 1, TimeUnit.SECONDS),
86 - validateSubmission(); 88 + is(greaterThanOrEqualTo(2)));
87 - } 89 + // Note: posting event, to trigger topologyChanged call,
88 - }); 90 + // but dummy topology will not change.
91 + validateSubmission();
89 } 92 }
90 93
91 94
...@@ -119,6 +122,7 @@ public class DefaultTopologyProviderTest { ...@@ -119,6 +122,7 @@ public class DefaultTopologyProviderTest {
119 @Override 122 @Override
120 public void topologyChanged(GraphDescription graphDescription, List<Event> reasons) { 123 public void topologyChanged(GraphDescription graphDescription, List<Event> reasons) {
121 graphDesc = graphDescription; 124 graphDesc = graphDescription;
125 + topologyChangedCounts.arrive();
122 } 126 }
123 } 127 }
124 128
......
...@@ -18,7 +18,6 @@ import org.onlab.onos.cluster.DefaultControllerNode; ...@@ -18,7 +18,6 @@ import org.onlab.onos.cluster.DefaultControllerNode;
18 import org.onlab.onos.cluster.NodeId; 18 import org.onlab.onos.cluster.NodeId;
19 import org.onlab.onos.store.AbstractStore; 19 import org.onlab.onos.store.AbstractStore;
20 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationAdminService; 20 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationAdminService;
21 -import org.onlab.onos.store.cluster.messaging.impl.ClusterCommunicationManager;
22 import org.onlab.packet.IpPrefix; 21 import org.onlab.packet.IpPrefix;
23 import org.slf4j.Logger; 22 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory; 23 import org.slf4j.LoggerFactory;
...@@ -48,7 +47,7 @@ public class DistributedClusterStore ...@@ -48,7 +47,7 @@ public class DistributedClusterStore
48 private final Map<NodeId, State> states = new ConcurrentHashMap<>(); 47 private final Map<NodeId, State> states = new ConcurrentHashMap<>();
49 private final Cache<NodeId, ControllerNode> livenessCache = CacheBuilder.newBuilder() 48 private final Cache<NodeId, ControllerNode> livenessCache = CacheBuilder.newBuilder()
50 .maximumSize(1000) 49 .maximumSize(1000)
51 - .expireAfterWrite(ClusterCommunicationManager.HEART_BEAT_INTERVAL_MILLIS * 3, TimeUnit.MILLISECONDS) 50 + .expireAfterWrite(/*ClusterCommunicationManager.HEART_BEAT_INTERVAL_MILLIS * */3, TimeUnit.MILLISECONDS)
52 .removalListener(new LivenessCacheRemovalListener()).build(); 51 .removalListener(new LivenessCacheRemovalListener()).build();
53 52
54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 53 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......
1 -package org.onlab.onos.store.cluster.messaging;
2 -
3 -import org.onlab.onos.cluster.ControllerNode;
4 -import org.onlab.onos.store.cluster.impl.ClusterNodesDelegate;
5 -
6 -// TODO: This service interface can be removed, once we properly start
7 -// using ClusterService
8 -/**
9 - * Service for administering communications manager.
10 - */
11 -public interface ClusterCommunicationAdminService {
12 -
13 - /**
14 - * Initialize.
15 - */
16 - void initialize(ControllerNode localNode, ClusterNodesDelegate nodesDelegate);
17 -
18 - /**
19 - * Adds the node to the list of monitored nodes.
20 - *
21 - * @param node node to be added
22 - */
23 - void addNode(ControllerNode node);
24 -
25 - /**
26 - * Removes the node from the list of monitored nodes.
27 - *
28 - * @param node node to be removed
29 - */
30 - void removeNode(ControllerNode node);
31 -}
...\ No newline at end of file ...\ No newline at end of file
1 -package org.onlab.onos.store.cluster.messaging;
2 -
3 -// FIXME: not used any more? remove
4 -/**
5 - * Service for encoding &amp; decoding intra-cluster message payload.
6 - */
7 -public interface SerializationService {
8 -
9 - /**
10 - * Decodes the specified byte buffer to obtain the message within.
11 - *
12 - * @param buffer byte buffer with message(s)
13 - * @return parsed message
14 - */
15 - <T> T decode(byte[] data);
16 -
17 - /**
18 - * Encodes the specified message into the given byte buffer.
19 - *
20 - * @param message message to be encoded
21 - * @param buffer byte buffer to receive the message data
22 - */
23 - byte[] encode(Object message);
24 -
25 -}
...@@ -4,8 +4,6 @@ import static com.google.common.base.Preconditions.checkArgument; ...@@ -4,8 +4,6 @@ import static com.google.common.base.Preconditions.checkArgument;
4 4
5 import java.io.IOException; 5 import java.io.IOException;
6 import java.util.Set; 6 import java.util.Set;
7 -import java.util.Timer;
8 -import java.util.TimerTask;
9 import org.apache.felix.scr.annotations.Activate; 7 import org.apache.felix.scr.annotations.Activate;
10 import org.apache.felix.scr.annotations.Component; 8 import org.apache.felix.scr.annotations.Component;
11 import org.apache.felix.scr.annotations.Deactivate; 9 import org.apache.felix.scr.annotations.Deactivate;
...@@ -16,9 +14,6 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -16,9 +14,6 @@ import org.onlab.onos.cluster.ClusterService;
16 import org.onlab.onos.cluster.ControllerNode; 14 import org.onlab.onos.cluster.ControllerNode;
17 import org.onlab.onos.cluster.NodeId; 15 import org.onlab.onos.cluster.NodeId;
18 import org.onlab.onos.store.cluster.impl.ClusterMembershipEvent; 16 import org.onlab.onos.store.cluster.impl.ClusterMembershipEvent;
19 -import org.onlab.onos.store.cluster.impl.ClusterMembershipEventType;
20 -import org.onlab.onos.store.cluster.impl.ClusterNodesDelegate;
21 -import org.onlab.onos.store.cluster.messaging.ClusterCommunicationAdminService;
22 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; 17 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
23 import org.onlab.onos.store.cluster.messaging.ClusterMessage; 18 import org.onlab.onos.store.cluster.messaging.ClusterMessage;
24 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; 19 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
...@@ -39,19 +34,13 @@ import org.slf4j.LoggerFactory; ...@@ -39,19 +34,13 @@ import org.slf4j.LoggerFactory;
39 @Component(immediate = true) 34 @Component(immediate = true)
40 @Service 35 @Service
41 public class ClusterCommunicationManager 36 public class ClusterCommunicationManager
42 - implements ClusterCommunicationService, ClusterCommunicationAdminService { 37 + implements ClusterCommunicationService {
43 38
44 private final Logger log = LoggerFactory.getLogger(getClass()); 39 private final Logger log = LoggerFactory.getLogger(getClass());
45 40
46 - private ControllerNode localNode;
47 -
48 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 41 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 private ClusterService clusterService; 42 private ClusterService clusterService;
50 43
51 - private ClusterNodesDelegate nodesDelegate;
52 - private final Timer timer = new Timer("onos-controller-heatbeats");
53 - public static final long HEART_BEAT_INTERVAL_MILLIS = 1000L;
54 -
55 // TODO: This probably should not be a OSGi service. 44 // TODO: This probably should not be a OSGi service.
56 private MessagingService messagingService; 45 private MessagingService messagingService;
57 46
...@@ -72,7 +61,7 @@ public class ClusterCommunicationManager ...@@ -72,7 +61,7 @@ public class ClusterCommunicationManager
72 61
73 @Activate 62 @Activate
74 public void activate() { 63 public void activate() {
75 - localNode = clusterService.getLocalNode(); 64 + ControllerNode localNode = clusterService.getLocalNode();
76 NettyMessagingService netty = new NettyMessagingService(localNode.tcpPort()); 65 NettyMessagingService netty = new NettyMessagingService(localNode.tcpPort());
77 // FIXME: workaround until it becomes a service. 66 // FIXME: workaround until it becomes a service.
78 try { 67 try {
...@@ -92,8 +81,9 @@ public class ClusterCommunicationManager ...@@ -92,8 +81,9 @@ public class ClusterCommunicationManager
92 } 81 }
93 82
94 @Override 83 @Override
95 - public boolean broadcast(ClusterMessage message) { 84 + public boolean broadcast(ClusterMessage message) throws IOException {
96 boolean ok = true; 85 boolean ok = true;
86 + final ControllerNode localNode = clusterService.getLocalNode();
97 for (ControllerNode node : clusterService.getNodes()) { 87 for (ControllerNode node : clusterService.getNodes()) {
98 if (!node.equals(localNode)) { 88 if (!node.equals(localNode)) {
99 ok = unicast(message, node.id()) && ok; 89 ok = unicast(message, node.id()) && ok;
...@@ -103,8 +93,9 @@ public class ClusterCommunicationManager ...@@ -103,8 +93,9 @@ public class ClusterCommunicationManager
103 } 93 }
104 94
105 @Override 95 @Override
106 - public boolean multicast(ClusterMessage message, Set<NodeId> nodes) { 96 + public boolean multicast(ClusterMessage message, Set<NodeId> nodes) throws IOException {
107 boolean ok = true; 97 boolean ok = true;
98 + final ControllerNode localNode = clusterService.getLocalNode();
108 for (NodeId nodeId : nodes) { 99 for (NodeId nodeId : nodes) {
109 if (!nodeId.equals(localNode.id())) { 100 if (!nodeId.equals(localNode.id())) {
110 ok = unicast(message, nodeId) && ok; 101 ok = unicast(message, nodeId) && ok;
...@@ -114,7 +105,7 @@ public class ClusterCommunicationManager ...@@ -114,7 +105,7 @@ public class ClusterCommunicationManager
114 } 105 }
115 106
116 @Override 107 @Override
117 - public boolean unicast(ClusterMessage message, NodeId toNodeId) { 108 + public boolean unicast(ClusterMessage message, NodeId toNodeId) throws IOException {
118 ControllerNode node = clusterService.getNode(toNodeId); 109 ControllerNode node = clusterService.getNode(toNodeId);
119 checkArgument(node != null, "Unknown nodeId: %s", toNodeId); 110 checkArgument(node != null, "Unknown nodeId: %s", toNodeId);
120 Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort()); 111 Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort());
...@@ -124,9 +115,8 @@ public class ClusterCommunicationManager ...@@ -124,9 +115,8 @@ public class ClusterCommunicationManager
124 return true; 115 return true;
125 } catch (IOException e) { 116 } catch (IOException e) {
126 log.error("Failed to send cluster message to nodeId: " + toNodeId, e); 117 log.error("Failed to send cluster message to nodeId: " + toNodeId, e);
118 + throw e;
127 } 119 }
128 -
129 - return false;
130 } 120 }
131 121
132 @Override 122 @Override
...@@ -135,61 +125,6 @@ public class ClusterCommunicationManager ...@@ -135,61 +125,6 @@ public class ClusterCommunicationManager
135 messagingService.registerHandler(subject.value(), new InternalClusterMessageHandler(subscriber)); 125 messagingService.registerHandler(subject.value(), new InternalClusterMessageHandler(subscriber));
136 } 126 }
137 127
138 - @Override
139 - public void initialize(ControllerNode localNode,
140 - ClusterNodesDelegate delegate) {
141 - this.localNode = localNode;
142 - this.nodesDelegate = delegate;
143 - this.addSubscriber(new MessageSubject("CLUSTER_MEMBERSHIP_EVENT"), new ClusterMemebershipEventHandler());
144 - timer.schedule(new KeepAlive(), 0, HEART_BEAT_INTERVAL_MILLIS);
145 - }
146 -
147 - @Override
148 - public void addNode(ControllerNode node) {
149 - //members.put(node.id(), node);
150 - }
151 -
152 - @Override
153 - public void removeNode(ControllerNode node) {
154 - broadcast(new ClusterMessage(
155 - localNode.id(),
156 - new MessageSubject("CLUSTER_MEMBERSHIP_EVENT"),
157 - SERIALIZER.encode(new ClusterMembershipEvent(ClusterMembershipEventType.LEAVING_MEMBER, node))));
158 - //members.remove(node.id());
159 - }
160 -
161 - // Sends a heart beat to all peers.
162 - private class KeepAlive extends TimerTask {
163 -
164 - @Override
165 - public void run() {
166 - broadcast(new ClusterMessage(
167 - localNode.id(),
168 - new MessageSubject("CLUSTER_MEMBERSHIP_EVENT"),
169 - SERIALIZER.encode(new ClusterMembershipEvent(ClusterMembershipEventType.HEART_BEAT, localNode))));
170 - }
171 - }
172 -
173 - private class ClusterMemebershipEventHandler implements ClusterMessageHandler {
174 -
175 - @Override
176 - public void handle(ClusterMessage message) {
177 -
178 - ClusterMembershipEvent event = SERIALIZER.decode(message.payload());
179 - ControllerNode node = event.node();
180 - if (event.type() == ClusterMembershipEventType.HEART_BEAT) {
181 - log.info("Node {} sent a hearbeat", node.id());
182 - nodesDelegate.nodeDetected(node.id(), node.ip(), node.tcpPort());
183 - } else if (event.type() == ClusterMembershipEventType.LEAVING_MEMBER) {
184 - log.info("Node {} is leaving", node.id());
185 - nodesDelegate.nodeRemoved(node.id());
186 - } else if (event.type() == ClusterMembershipEventType.UNREACHABLE_MEMBER) {
187 - log.info("Node {} is unreachable", node.id());
188 - nodesDelegate.nodeVanished(node.id());
189 - }
190 - }
191 - }
192 -
193 private final class InternalClusterMessageHandler implements MessageHandler { 128 private final class InternalClusterMessageHandler implements MessageHandler {
194 129
195 private final ClusterMessageHandler handler; 130 private final ClusterMessageHandler handler;
......
1 -package org.onlab.onos.store.cluster.messaging.impl;
2 -
3 -import org.apache.felix.scr.annotations.Activate;
4 -import org.apache.felix.scr.annotations.Component;
5 -import org.apache.felix.scr.annotations.Deactivate;
6 -import org.apache.felix.scr.annotations.Service;
7 -import org.onlab.onos.store.cluster.messaging.MessageSubject;
8 -import org.onlab.onos.store.cluster.messaging.SerializationService;
9 -import org.onlab.onos.store.serializers.KryoPoolUtil;
10 -import org.onlab.util.KryoPool;
11 -import org.slf4j.Logger;
12 -import org.slf4j.LoggerFactory;
13 -
14 -//FIXME: not used any more? remove
15 -/**
16 - * Factory for parsing messages sent between cluster members.
17 - */
18 -@Component(immediate = true)
19 -@Service
20 -public class MessageSerializer implements SerializationService {
21 -
22 - private final Logger log = LoggerFactory.getLogger(getClass());
23 -
24 - private static final int METADATA_LENGTH = 12; // 8 + 4
25 - private static final int LENGTH_OFFSET = 8;
26 -
27 - private static final long MARKER = 0xfeedcafebeaddeadL;
28 -
29 - private KryoPool serializerPool;
30 -
31 - @Activate
32 - public void activate() {
33 - setupKryoPool();
34 - log.info("Started");
35 - }
36 -
37 - @Deactivate
38 - public void deactivate() {
39 - log.info("Stopped");
40 - }
41 -
42 - /**
43 - * Sets up the common serialzers pool.
44 - */
45 - protected void setupKryoPool() {
46 - serializerPool = KryoPool.newBuilder()
47 - .register(KryoPoolUtil.API)
48 - // TODO: Should MessageSubject be in API bundle?
49 - .register(MessageSubject.class)
50 - .build()
51 - .populate(1);
52 - }
53 -
54 -
55 - @Override
56 - public <T> T decode(byte[] data) {
57 - return serializerPool.deserialize(data);
58 - }
59 -
60 - @Override
61 - public byte[] encode(Object payload) {
62 - return serializerPool.serialize(payload);
63 - }
64 -}
...@@ -86,14 +86,11 @@ public class GossipDeviceStore ...@@ -86,14 +86,11 @@ public class GossipDeviceStore
86 86
87 private final Logger log = getLogger(getClass()); 87 private final Logger log = getLogger(getClass());
88 88
89 - public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; 89 + private static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
90 90
91 - // TODO: Check if inner Map can be replaced with plain Map.
92 // innerMap is used to lock a Device, thus instance should never be replaced. 91 // innerMap is used to lock a Device, thus instance should never be replaced.
93 -
94 // collection of Description given from various providers 92 // collection of Description given from various providers
95 - private final ConcurrentMap<DeviceId, 93 + private final ConcurrentMap<DeviceId, Map<ProviderId, DeviceDescriptions>>
96 - ConcurrentMap<ProviderId, DeviceDescriptions>>
97 deviceDescs = Maps.newConcurrentMap(); 94 deviceDescs = Maps.newConcurrentMap();
98 95
99 // cache of Device and Ports generated by compositing descriptions from providers 96 // cache of Device and Ports generated by compositing descriptions from providers
...@@ -208,9 +205,9 @@ public class GossipDeviceStore ...@@ -208,9 +205,9 @@ public class GossipDeviceStore
208 final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp); 205 final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp);
209 final DeviceEvent event; 206 final DeviceEvent event;
210 final Timestamped<DeviceDescription> mergedDesc; 207 final Timestamped<DeviceDescription> mergedDesc;
211 - synchronized (getDeviceDescriptions(deviceId)) { 208 + synchronized (getOrCreateDeviceDescriptionsMap(deviceId)) {
212 event = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc); 209 event = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc);
213 - mergedDesc = getDeviceDescriptions(deviceId).get(providerId).getDeviceDesc(); 210 + mergedDesc = getOrCreateDeviceDescriptionsMap(deviceId).get(providerId).getDeviceDesc();
214 } 211 }
215 if (event != null) { 212 if (event != null) {
216 log.info("Notifying peers of a device update topology event for providerId: {} and deviceId: {}", 213 log.info("Notifying peers of a device update topology event for providerId: {} and deviceId: {}",
...@@ -230,8 +227,8 @@ public class GossipDeviceStore ...@@ -230,8 +227,8 @@ public class GossipDeviceStore
230 Timestamped<DeviceDescription> deltaDesc) { 227 Timestamped<DeviceDescription> deltaDesc) {
231 228
232 // Collection of DeviceDescriptions for a Device 229 // Collection of DeviceDescriptions for a Device
233 - ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs 230 + Map<ProviderId, DeviceDescriptions> providerDescs
234 - = getDeviceDescriptions(deviceId); 231 + = getOrCreateDeviceDescriptionsMap(deviceId);
235 232
236 synchronized (providerDescs) { 233 synchronized (providerDescs) {
237 // locking per device 234 // locking per device
...@@ -241,9 +238,7 @@ public class GossipDeviceStore ...@@ -241,9 +238,7 @@ public class GossipDeviceStore
241 return null; 238 return null;
242 } 239 }
243 240
244 - DeviceDescriptions descs 241 + DeviceDescriptions descs = getOrCreateProviderDeviceDescriptions(providerDescs, providerId, deltaDesc);
245 - = createIfAbsentUnchecked(providerDescs, providerId,
246 - new InitDeviceDescs(deltaDesc));
247 242
248 final Device oldDevice = devices.get(deviceId); 243 final Device oldDevice = devices.get(deviceId);
249 final Device newDevice; 244 final Device newDevice;
...@@ -338,7 +333,7 @@ public class GossipDeviceStore ...@@ -338,7 +333,7 @@ public class GossipDeviceStore
338 private DeviceEvent markOfflineInternal(DeviceId deviceId, Timestamp timestamp) { 333 private DeviceEvent markOfflineInternal(DeviceId deviceId, Timestamp timestamp) {
339 334
340 Map<ProviderId, DeviceDescriptions> providerDescs 335 Map<ProviderId, DeviceDescriptions> providerDescs
341 - = getDeviceDescriptions(deviceId); 336 + = getOrCreateDeviceDescriptionsMap(deviceId);
342 337
343 // locking device 338 // locking device
344 synchronized (providerDescs) { 339 synchronized (providerDescs) {
...@@ -401,9 +396,9 @@ public class GossipDeviceStore ...@@ -401,9 +396,9 @@ public class GossipDeviceStore
401 final List<DeviceEvent> events; 396 final List<DeviceEvent> events;
402 final Timestamped<List<PortDescription>> merged; 397 final Timestamped<List<PortDescription>> merged;
403 398
404 - synchronized (getDeviceDescriptions(deviceId)) { 399 + synchronized (getOrCreateDeviceDescriptionsMap(deviceId)) {
405 events = updatePortsInternal(providerId, deviceId, timestampedInput); 400 events = updatePortsInternal(providerId, deviceId, timestampedInput);
406 - final DeviceDescriptions descs = getDeviceDescriptions(deviceId).get(providerId); 401 + final DeviceDescriptions descs = getOrCreateDeviceDescriptionsMap(deviceId).get(providerId);
407 List<PortDescription> mergedList = 402 List<PortDescription> mergedList =
408 FluentIterable.from(portDescriptions) 403 FluentIterable.from(portDescriptions)
409 .transform(new Function<PortDescription, PortDescription>() { 404 .transform(new Function<PortDescription, PortDescription>() {
...@@ -435,7 +430,7 @@ public class GossipDeviceStore ...@@ -435,7 +430,7 @@ public class GossipDeviceStore
435 Device device = devices.get(deviceId); 430 Device device = devices.get(deviceId);
436 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); 431 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
437 432
438 - ConcurrentMap<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId); 433 + Map<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId);
439 checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId); 434 checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId);
440 435
441 List<DeviceEvent> events = new ArrayList<>(); 436 List<DeviceEvent> events = new ArrayList<>();
...@@ -539,10 +534,34 @@ public class GossipDeviceStore ...@@ -539,10 +534,34 @@ public class GossipDeviceStore
539 NewConcurrentHashMap.<PortNumber, Port>ifNeeded()); 534 NewConcurrentHashMap.<PortNumber, Port>ifNeeded());
540 } 535 }
541 536
542 - private ConcurrentMap<ProviderId, DeviceDescriptions> getDeviceDescriptions( 537 + private Map<ProviderId, DeviceDescriptions> getOrCreateDeviceDescriptionsMap(
543 DeviceId deviceId) { 538 DeviceId deviceId) {
544 - return createIfAbsentUnchecked(deviceDescs, deviceId, 539 + Map<ProviderId, DeviceDescriptions> r;
545 - NewConcurrentHashMap.<ProviderId, DeviceDescriptions>ifNeeded()); 540 + r = deviceDescs.get(deviceId);
541 + if (r == null) {
542 + r = new HashMap<ProviderId, DeviceDescriptions>();
543 + final Map<ProviderId, DeviceDescriptions> concurrentlyAdded;
544 + concurrentlyAdded = deviceDescs.putIfAbsent(deviceId, r);
545 + if (concurrentlyAdded != null) {
546 + r = concurrentlyAdded;
547 + }
548 + }
549 + return r;
550 + }
551 +
552 + // Guarded by deviceDescs value (=Device lock)
553 + private DeviceDescriptions getOrCreateProviderDeviceDescriptions(
554 + Map<ProviderId, DeviceDescriptions> device,
555 + ProviderId providerId, Timestamped<DeviceDescription> deltaDesc) {
556 +
557 + synchronized (device) {
558 + DeviceDescriptions r = device.get(providerId);
559 + if (r == null) {
560 + r = new DeviceDescriptions(deltaDesc);
561 + device.put(providerId, r);
562 + }
563 + return r;
564 + }
546 } 565 }
547 566
548 @Override 567 @Override
...@@ -555,9 +574,9 @@ public class GossipDeviceStore ...@@ -555,9 +574,9 @@ public class GossipDeviceStore
555 = new Timestamped<>(portDescription, newTimestamp); 574 = new Timestamped<>(portDescription, newTimestamp);
556 final DeviceEvent event; 575 final DeviceEvent event;
557 final Timestamped<PortDescription> mergedDesc; 576 final Timestamped<PortDescription> mergedDesc;
558 - synchronized (getDeviceDescriptions(deviceId)) { 577 + synchronized (getOrCreateDeviceDescriptionsMap(deviceId)) {
559 event = updatePortStatusInternal(providerId, deviceId, deltaDesc); 578 event = updatePortStatusInternal(providerId, deviceId, deltaDesc);
560 - mergedDesc = getDeviceDescriptions(deviceId).get(providerId) 579 + mergedDesc = getOrCreateDeviceDescriptionsMap(deviceId).get(providerId)
561 .getPortDesc(portDescription.portNumber()); 580 .getPortDesc(portDescription.portNumber());
562 } 581 }
563 if (event != null) { 582 if (event != null) {
...@@ -579,7 +598,7 @@ public class GossipDeviceStore ...@@ -579,7 +598,7 @@ public class GossipDeviceStore
579 Device device = devices.get(deviceId); 598 Device device = devices.get(deviceId);
580 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); 599 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
581 600
582 - ConcurrentMap<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId); 601 + Map<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId);
583 checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId); 602 checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId);
584 603
585 synchronized (descsMap) { 604 synchronized (descsMap) {
...@@ -591,7 +610,7 @@ public class GossipDeviceStore ...@@ -591,7 +610,7 @@ public class GossipDeviceStore
591 610
592 DeviceDescriptions descs = descsMap.get(providerId); 611 DeviceDescriptions descs = descsMap.get(providerId);
593 // assuming all providers must to give DeviceDescription 612 // assuming all providers must to give DeviceDescription
594 - checkArgument(descs != null, 613 + verify(descs != null,
595 "Device description for Device ID %s from Provider %s was not found", 614 "Device description for Device ID %s from Provider %s was not found",
596 deviceId, providerId); 615 deviceId, providerId);
597 616
...@@ -661,7 +680,7 @@ public class GossipDeviceStore ...@@ -661,7 +680,7 @@ public class GossipDeviceStore
661 private DeviceEvent removeDeviceInternal(DeviceId deviceId, 680 private DeviceEvent removeDeviceInternal(DeviceId deviceId,
662 Timestamp timestamp) { 681 Timestamp timestamp) {
663 682
664 - Map<ProviderId, DeviceDescriptions> descs = getDeviceDescriptions(deviceId); 683 + Map<ProviderId, DeviceDescriptions> descs = getOrCreateDeviceDescriptionsMap(deviceId);
665 synchronized (descs) { 684 synchronized (descs) {
666 // accept removal request if given timestamp is newer than 685 // accept removal request if given timestamp is newer than
667 // the latest Timestamp from Primary provider 686 // the latest Timestamp from Primary provider
...@@ -751,14 +770,14 @@ public class GossipDeviceStore ...@@ -751,14 +770,14 @@ public class GossipDeviceStore
751 * 770 *
752 * @param device device the port is on 771 * @param device device the port is on
753 * @param number port number 772 * @param number port number
754 - * @param providerDescs Collection of Descriptions from multiple providers 773 + * @param descsMap Collection of Descriptions from multiple providers
755 * @return Port instance 774 * @return Port instance
756 */ 775 */
757 private Port composePort(Device device, PortNumber number, 776 private Port composePort(Device device, PortNumber number,
758 - ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs) { 777 + Map<ProviderId, DeviceDescriptions> descsMap) {
759 778
760 - ProviderId primary = pickPrimaryPID(providerDescs); 779 + ProviderId primary = pickPrimaryPID(descsMap);
761 - DeviceDescriptions primDescs = providerDescs.get(primary); 780 + DeviceDescriptions primDescs = descsMap.get(primary);
762 // if no primary, assume not enabled 781 // if no primary, assume not enabled
763 // TODO: revisit this default port enabled/disabled behavior 782 // TODO: revisit this default port enabled/disabled behavior
764 boolean isEnabled = false; 783 boolean isEnabled = false;
...@@ -770,7 +789,7 @@ public class GossipDeviceStore ...@@ -770,7 +789,7 @@ public class GossipDeviceStore
770 annotations = merge(annotations, portDesc.value().annotations()); 789 annotations = merge(annotations, portDesc.value().annotations());
771 } 790 }
772 791
773 - for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) { 792 + for (Entry<ProviderId, DeviceDescriptions> e : descsMap.entrySet()) {
774 if (e.getKey().equals(primary)) { 793 if (e.getKey().equals(primary)) {
775 continue; 794 continue;
776 } 795 }
...@@ -893,41 +912,48 @@ public class GossipDeviceStore ...@@ -893,41 +912,48 @@ public class GossipDeviceStore
893 private DeviceAntiEntropyAdvertisement createAdvertisement() { 912 private DeviceAntiEntropyAdvertisement createAdvertisement() {
894 final NodeId self = clusterService.getLocalNode().id(); 913 final NodeId self = clusterService.getLocalNode().id();
895 914
896 - Map<DeviceFragmentId, Timestamp> devices = new HashMap<>(deviceDescs.size()); 915 + final int numDevices = deviceDescs.size();
897 - final int portsPerDevice = 8; // random guess to minimize reallocation 916 + Map<DeviceFragmentId, Timestamp> adDevices = new HashMap<>(numDevices);
898 - Map<PortFragmentId, Timestamp> ports = new HashMap<>(devices.size() * portsPerDevice); 917 + final int portsPerDevice = 8; // random factor to minimize reallocation
899 - Map<DeviceId, Timestamp> offline = new HashMap<>(devices.size()); 918 + Map<PortFragmentId, Timestamp> adPorts = new HashMap<>(numDevices * portsPerDevice);
919 + Map<DeviceId, Timestamp> adOffline = new HashMap<>(numDevices);
900 920
901 - for (Entry<DeviceId, ConcurrentMap<ProviderId, DeviceDescriptions>> 921 + for (Entry<DeviceId, Map<ProviderId, DeviceDescriptions>>
902 provs : deviceDescs.entrySet()) { 922 provs : deviceDescs.entrySet()) {
903 923
924 + // for each Device...
904 final DeviceId deviceId = provs.getKey(); 925 final DeviceId deviceId = provs.getKey();
905 - final ConcurrentMap<ProviderId, DeviceDescriptions> devDescs = provs.getValue(); 926 + final Map<ProviderId, DeviceDescriptions> devDescs = provs.getValue();
906 synchronized (devDescs) { 927 synchronized (devDescs) {
907 928
908 - offline.put(deviceId, this.offline.get(deviceId)); 929 + // send device offline timestamp
930 + Timestamp lOffline = this.offline.get(deviceId);
931 + if (lOffline != null) {
932 + adOffline.put(deviceId, lOffline);
933 + }
909 934
910 for (Entry<ProviderId, DeviceDescriptions> 935 for (Entry<ProviderId, DeviceDescriptions>
911 prov : devDescs.entrySet()) { 936 prov : devDescs.entrySet()) {
912 937
938 + // for each Provider Descriptions...
913 final ProviderId provId = prov.getKey(); 939 final ProviderId provId = prov.getKey();
914 final DeviceDescriptions descs = prov.getValue(); 940 final DeviceDescriptions descs = prov.getValue();
915 941
916 - devices.put(new DeviceFragmentId(deviceId, provId), 942 + adDevices.put(new DeviceFragmentId(deviceId, provId),
917 descs.getDeviceDesc().timestamp()); 943 descs.getDeviceDesc().timestamp());
918 944
919 for (Entry<PortNumber, Timestamped<PortDescription>> 945 for (Entry<PortNumber, Timestamped<PortDescription>>
920 portDesc : descs.getPortDescs().entrySet()) { 946 portDesc : descs.getPortDescs().entrySet()) {
921 947
922 final PortNumber number = portDesc.getKey(); 948 final PortNumber number = portDesc.getKey();
923 - ports.put(new PortFragmentId(deviceId, provId, number), 949 + adPorts.put(new PortFragmentId(deviceId, provId, number),
924 portDesc.getValue().timestamp()); 950 portDesc.getValue().timestamp());
925 } 951 }
926 } 952 }
927 } 953 }
928 } 954 }
929 955
930 - return new DeviceAntiEntropyAdvertisement(self, devices, ports, offline); 956 + return new DeviceAntiEntropyAdvertisement(self, adDevices, adPorts, adOffline);
931 } 957 }
932 958
933 /** 959 /**
...@@ -950,7 +976,7 @@ public class GossipDeviceStore ...@@ -950,7 +976,7 @@ public class GossipDeviceStore
950 Collection<DeviceFragmentId> reqDevices = new ArrayList<>(); 976 Collection<DeviceFragmentId> reqDevices = new ArrayList<>();
951 Collection<PortFragmentId> reqPorts = new ArrayList<>(); 977 Collection<PortFragmentId> reqPorts = new ArrayList<>();
952 978
953 - for (Entry<DeviceId, ConcurrentMap<ProviderId, DeviceDescriptions>> de : deviceDescs.entrySet()) { 979 + for (Entry<DeviceId, Map<ProviderId, DeviceDescriptions>> de : deviceDescs.entrySet()) {
954 final DeviceId deviceId = de.getKey(); 980 final DeviceId deviceId = de.getKey();
955 final Map<ProviderId, DeviceDescriptions> lDevice = de.getValue(); 981 final Map<ProviderId, DeviceDescriptions> lDevice = de.getValue();
956 982
...@@ -1199,7 +1225,7 @@ public class GossipDeviceStore ...@@ -1199,7 +1225,7 @@ public class GossipDeviceStore
1199 1225
1200 @Override 1226 @Override
1201 public void handle(ClusterMessage message) { 1227 public void handle(ClusterMessage message) {
1202 - log.info("Received Device advertisement from peer: {}", message.sender()); 1228 + log.debug("Received Device Anti-Entropy advertisement from peer: {}", message.sender());
1203 DeviceAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload()); 1229 DeviceAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload());
1204 handleAdvertisement(advertisement); 1230 handleAdvertisement(advertisement);
1205 } 1231 }
......
...@@ -4,10 +4,14 @@ import com.google.common.collect.HashMultimap; ...@@ -4,10 +4,14 @@ import com.google.common.collect.HashMultimap;
4 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.ImmutableSet;
5 import com.google.common.collect.Multimap; 5 import com.google.common.collect.Multimap;
6 import com.google.common.collect.Sets; 6 import com.google.common.collect.Sets;
7 +
7 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
8 import org.apache.felix.scr.annotations.Component; 9 import org.apache.felix.scr.annotations.Component;
9 import org.apache.felix.scr.annotations.Deactivate; 10 import org.apache.felix.scr.annotations.Deactivate;
11 +import org.apache.felix.scr.annotations.Reference;
12 +import org.apache.felix.scr.annotations.ReferenceCardinality;
10 import org.apache.felix.scr.annotations.Service; 13 import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.cluster.ClusterService;
11 import org.onlab.onos.net.Annotations; 15 import org.onlab.onos.net.Annotations;
12 import org.onlab.onos.net.ConnectPoint; 16 import org.onlab.onos.net.ConnectPoint;
13 import org.onlab.onos.net.DefaultHost; 17 import org.onlab.onos.net.DefaultHost;
...@@ -15,6 +19,7 @@ import org.onlab.onos.net.DeviceId; ...@@ -15,6 +19,7 @@ import org.onlab.onos.net.DeviceId;
15 import org.onlab.onos.net.Host; 19 import org.onlab.onos.net.Host;
16 import org.onlab.onos.net.HostId; 20 import org.onlab.onos.net.HostId;
17 import org.onlab.onos.net.HostLocation; 21 import org.onlab.onos.net.HostLocation;
22 +import org.onlab.onos.net.host.HostClockService;
18 import org.onlab.onos.net.host.HostDescription; 23 import org.onlab.onos.net.host.HostDescription;
19 import org.onlab.onos.net.host.HostEvent; 24 import org.onlab.onos.net.host.HostEvent;
20 import org.onlab.onos.net.host.HostStore; 25 import org.onlab.onos.net.host.HostStore;
...@@ -22,11 +27,21 @@ import org.onlab.onos.net.host.HostStoreDelegate; ...@@ -22,11 +27,21 @@ import org.onlab.onos.net.host.HostStoreDelegate;
22 import org.onlab.onos.net.host.PortAddresses; 27 import org.onlab.onos.net.host.PortAddresses;
23 import org.onlab.onos.net.provider.ProviderId; 28 import org.onlab.onos.net.provider.ProviderId;
24 import org.onlab.onos.store.AbstractStore; 29 import org.onlab.onos.store.AbstractStore;
30 +import org.onlab.onos.store.Timestamp;
31 +import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
32 +import org.onlab.onos.store.cluster.messaging.ClusterMessage;
33 +import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
34 +import org.onlab.onos.store.cluster.messaging.MessageSubject;
35 +import org.onlab.onos.store.common.impl.Timestamped;
36 +import org.onlab.onos.store.serializers.DistributedStoreSerializers;
37 +import org.onlab.onos.store.serializers.KryoSerializer;
25 import org.onlab.packet.IpPrefix; 38 import org.onlab.packet.IpPrefix;
26 import org.onlab.packet.MacAddress; 39 import org.onlab.packet.MacAddress;
27 import org.onlab.packet.VlanId; 40 import org.onlab.packet.VlanId;
41 +import org.onlab.util.KryoPool;
28 import org.slf4j.Logger; 42 import org.slf4j.Logger;
29 43
44 +import java.io.IOException;
30 import java.util.HashSet; 45 import java.util.HashSet;
31 import java.util.Map; 46 import java.util.Map;
32 import java.util.Set; 47 import java.util.Set;
...@@ -35,14 +50,14 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -35,14 +50,14 @@ import java.util.concurrent.ConcurrentHashMap;
35 import static org.onlab.onos.net.host.HostEvent.Type.*; 50 import static org.onlab.onos.net.host.HostEvent.Type.*;
36 import static org.slf4j.LoggerFactory.getLogger; 51 import static org.slf4j.LoggerFactory.getLogger;
37 52
53 +//TODO: multi-provider, annotation not supported.
38 /** 54 /**
39 - * Manages inventory of end-station hosts using trivial in-memory 55 + * Manages inventory of end-station hosts in distributed data store
40 - * implementation. 56 + * that uses optimistic replication and gossip based techniques.
41 */ 57 */
42 -//FIXME: I LIE I AM NOT DISTRIBUTED
43 @Component(immediate = true) 58 @Component(immediate = true)
44 @Service 59 @Service
45 -public class DistributedHostStore 60 +public class GossipHostStore
46 extends AbstractStore<HostEvent, HostStoreDelegate> 61 extends AbstractStore<HostEvent, HostStoreDelegate>
47 implements HostStore { 62 implements HostStore {
48 63
...@@ -51,14 +66,41 @@ public class DistributedHostStore ...@@ -51,14 +66,41 @@ public class DistributedHostStore
51 // Host inventory 66 // Host inventory
52 private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16); 67 private final Map<HostId, StoredHost> hosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
53 68
69 + private final Map<HostId, Timestamped<Host>> removedHosts = new ConcurrentHashMap<>(2000000, 0.75f, 16);
70 +
54 // Hosts tracked by their location 71 // Hosts tracked by their location
55 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create(); 72 private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
56 73
57 private final Map<ConnectPoint, PortAddresses> portAddresses = 74 private final Map<ConnectPoint, PortAddresses> portAddresses =
58 new ConcurrentHashMap<>(); 75 new ConcurrentHashMap<>();
59 76
77 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 + protected HostClockService hostClockService;
79 +
80 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 + protected ClusterCommunicationService clusterCommunicator;
82 +
83 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 + protected ClusterService clusterService;
85 +
86 + private static final KryoSerializer SERIALIZER = new KryoSerializer() {
87 + @Override
88 + protected void setupKryoPool() {
89 + serializerPool = KryoPool.newBuilder()
90 + .register(DistributedStoreSerializers.COMMON)
91 + .register(InternalHostRemovedEvent.class)
92 + .build()
93 + .populate(1);
94 + }
95 + };
96 +
60 @Activate 97 @Activate
61 public void activate() { 98 public void activate() {
99 + clusterCommunicator.addSubscriber(
100 + GossipHostStoreMessageSubjects.HOST_UPDATED, new InternalHostEventListener());
101 + clusterCommunicator.addSubscriber(
102 + GossipHostStoreMessageSubjects.HOST_REMOVED, new InternalHostRemovedEventListener());
103 +
62 log.info("Started"); 104 log.info("Started");
63 } 105 }
64 106
...@@ -70,34 +112,60 @@ public class DistributedHostStore ...@@ -70,34 +112,60 @@ public class DistributedHostStore
70 @Override 112 @Override
71 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId, 113 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
72 HostDescription hostDescription) { 114 HostDescription hostDescription) {
115 + Timestamp timestamp = hostClockService.getTimestamp(hostId);
116 + HostEvent event = createOrUpdateHostInternal(providerId, hostId, hostDescription, timestamp);
117 + if (event != null) {
118 + log.info("Notifying peers of a host topology event for providerId: "
119 + + "{}; hostId: {}; hostDescription: {}", providerId, hostId, hostDescription);
120 + try {
121 + notifyPeers(new InternalHostEvent(providerId, hostId, hostDescription, timestamp));
122 + } catch (IOException e) {
123 + log.error("Failed to notify peers of a host topology event for providerId: "
124 + + "{}; hostId: {}; hostDescription: {}", providerId, hostId, hostDescription);
125 + }
126 + }
127 + return event;
128 + }
129 +
130 + private HostEvent createOrUpdateHostInternal(ProviderId providerId, HostId hostId,
131 + HostDescription hostDescription, Timestamp timestamp) {
73 StoredHost host = hosts.get(hostId); 132 StoredHost host = hosts.get(hostId);
74 if (host == null) { 133 if (host == null) {
75 - return createHost(providerId, hostId, hostDescription); 134 + return createHost(providerId, hostId, hostDescription, timestamp);
76 } 135 }
77 - return updateHost(providerId, host, hostDescription); 136 + return updateHost(providerId, host, hostDescription, timestamp);
78 } 137 }
79 138
80 // creates a new host and sends HOST_ADDED 139 // creates a new host and sends HOST_ADDED
81 private HostEvent createHost(ProviderId providerId, HostId hostId, 140 private HostEvent createHost(ProviderId providerId, HostId hostId,
82 - HostDescription descr) { 141 + HostDescription descr, Timestamp timestamp) {
83 - StoredHost newhost = new StoredHost(providerId, hostId,
84 - descr.hwAddress(),
85 - descr.vlan(),
86 - descr.location(),
87 - ImmutableSet.of(descr.ipAddress()));
88 synchronized (this) { 142 synchronized (this) {
143 + // If this host was previously removed, first ensure
144 + // this new request is "newer"
145 + if (removedHosts.containsKey(hostId)) {
146 + if (removedHosts.get(hostId).isNewer(timestamp)) {
147 + return null;
148 + } else {
149 + removedHosts.remove(hostId);
150 + }
151 + }
152 + StoredHost newhost = new StoredHost(providerId, hostId,
153 + descr.hwAddress(),
154 + descr.vlan(),
155 + new Timestamped<>(descr.location(), timestamp),
156 + ImmutableSet.of(descr.ipAddress()));
89 hosts.put(hostId, newhost); 157 hosts.put(hostId, newhost);
90 locations.put(descr.location(), newhost); 158 locations.put(descr.location(), newhost);
159 + return new HostEvent(HOST_ADDED, newhost);
91 } 160 }
92 - return new HostEvent(HOST_ADDED, newhost);
93 } 161 }
94 162
95 // checks for type of update to host, sends appropriate event 163 // checks for type of update to host, sends appropriate event
96 private HostEvent updateHost(ProviderId providerId, StoredHost host, 164 private HostEvent updateHost(ProviderId providerId, StoredHost host,
97 - HostDescription descr) { 165 + HostDescription descr, Timestamp timestamp) {
98 HostEvent event; 166 HostEvent event;
99 - if (!host.location().equals(descr.location())) { 167 + if (!host.location.isNewer(timestamp) && !host.location().equals(descr.location())) {
100 - host.setLocation(descr.location()); 168 + host.setLocation(new Timestamped<>(descr.location(), timestamp));
101 return new HostEvent(HOST_MOVED, host); 169 return new HostEvent(HOST_MOVED, host);
102 } 170 }
103 171
...@@ -109,7 +177,7 @@ public class DistributedHostStore ...@@ -109,7 +177,7 @@ public class DistributedHostStore
109 addresses.add(descr.ipAddress()); 177 addresses.add(descr.ipAddress());
110 StoredHost updated = new StoredHost(providerId, host.id(), 178 StoredHost updated = new StoredHost(providerId, host.id(),
111 host.mac(), host.vlan(), 179 host.mac(), host.vlan(),
112 - descr.location(), addresses); 180 + host.location, addresses);
113 event = new HostEvent(HOST_UPDATED, updated); 181 event = new HostEvent(HOST_UPDATED, updated);
114 synchronized (this) { 182 synchronized (this) {
115 hosts.put(host.id(), updated); 183 hosts.put(host.id(), updated);
...@@ -121,10 +189,25 @@ public class DistributedHostStore ...@@ -121,10 +189,25 @@ public class DistributedHostStore
121 189
122 @Override 190 @Override
123 public HostEvent removeHost(HostId hostId) { 191 public HostEvent removeHost(HostId hostId) {
192 + Timestamp timestamp = hostClockService.getTimestamp(hostId);
193 + HostEvent event = removeHostInternal(hostId, timestamp);
194 + if (event != null) {
195 + log.info("Notifying peers of a host removed topology event for hostId: {}", hostId);
196 + try {
197 + notifyPeers(new InternalHostRemovedEvent(hostId, timestamp));
198 + } catch (IOException e) {
199 + log.info("Failed to notify peers of a host removed topology event for hostId: {}", hostId);
200 + }
201 + }
202 + return event;
203 + }
204 +
205 + private HostEvent removeHostInternal(HostId hostId, Timestamp timestamp) {
124 synchronized (this) { 206 synchronized (this) {
125 Host host = hosts.remove(hostId); 207 Host host = hosts.remove(hostId);
126 if (host != null) { 208 if (host != null) {
127 locations.remove((host.location()), host); 209 locations.remove((host.location()), host);
210 + removedHosts.put(hostId, new Timestamped<>(host, timestamp));
128 return new HostEvent(HOST_REMOVED, host); 211 return new HostEvent(HOST_REMOVED, host);
129 } 212 }
130 return null; 213 return null;
...@@ -270,7 +353,7 @@ public class DistributedHostStore ...@@ -270,7 +353,7 @@ public class DistributedHostStore
270 353
271 // Auxiliary extension to allow location to mutate. 354 // Auxiliary extension to allow location to mutate.
272 private class StoredHost extends DefaultHost { 355 private class StoredHost extends DefaultHost {
273 - private HostLocation location; 356 + private Timestamped<HostLocation> location;
274 357
275 /** 358 /**
276 * Creates an end-station host using the supplied information. 359 * Creates an end-station host using the supplied information.
...@@ -284,19 +367,71 @@ public class DistributedHostStore ...@@ -284,19 +367,71 @@ public class DistributedHostStore
284 * @param annotations optional key/value annotations 367 * @param annotations optional key/value annotations
285 */ 368 */
286 public StoredHost(ProviderId providerId, HostId id, 369 public StoredHost(ProviderId providerId, HostId id,
287 - MacAddress mac, VlanId vlan, HostLocation location, 370 + MacAddress mac, VlanId vlan, Timestamped<HostLocation> location,
288 Set<IpPrefix> ips, Annotations... annotations) { 371 Set<IpPrefix> ips, Annotations... annotations) {
289 - super(providerId, id, mac, vlan, location, ips, annotations); 372 + super(providerId, id, mac, vlan, location.value(), ips, annotations);
290 this.location = location; 373 this.location = location;
291 } 374 }
292 375
293 - void setLocation(HostLocation location) { 376 + void setLocation(Timestamped<HostLocation> location) {
294 this.location = location; 377 this.location = location;
295 } 378 }
296 379
297 @Override 380 @Override
298 public HostLocation location() { 381 public HostLocation location() {
299 - return location; 382 + return location.value();
383 + }
384 + }
385 +
386 + private void notifyPeers(InternalHostRemovedEvent event) throws IOException {
387 + broadcastMessage(GossipHostStoreMessageSubjects.HOST_REMOVED, event);
388 + }
389 +
390 + private void notifyPeers(InternalHostEvent event) throws IOException {
391 + broadcastMessage(GossipHostStoreMessageSubjects.HOST_UPDATED, event);
392 + }
393 +
394 + private void broadcastMessage(MessageSubject subject, Object event) throws IOException {
395 + ClusterMessage message = new ClusterMessage(
396 + clusterService.getLocalNode().id(),
397 + subject,
398 + SERIALIZER.encode(event));
399 + clusterCommunicator.broadcast(message);
400 + }
401 +
402 + private void notifyDelegateIfNotNull(HostEvent event) {
403 + if (event != null) {
404 + notifyDelegate(event);
405 + }
406 + }
407 +
408 + private class InternalHostEventListener implements ClusterMessageHandler {
409 + @Override
410 + public void handle(ClusterMessage message) {
411 +
412 + log.info("Received host update event from peer: {}", message.sender());
413 + InternalHostEvent event = (InternalHostEvent) SERIALIZER.decode(message.payload());
414 +
415 + ProviderId providerId = event.providerId();
416 + HostId hostId = event.hostId();
417 + HostDescription hostDescription = event.hostDescription();
418 + Timestamp timestamp = event.timestamp();
419 +
420 + notifyDelegateIfNotNull(createOrUpdateHostInternal(providerId, hostId, hostDescription, timestamp));
421 + }
422 + }
423 +
424 + private class InternalHostRemovedEventListener implements ClusterMessageHandler {
425 + @Override
426 + public void handle(ClusterMessage message) {
427 +
428 + log.info("Received host removed event from peer: {}", message.sender());
429 + InternalHostRemovedEvent event = (InternalHostRemovedEvent) SERIALIZER.decode(message.payload());
430 +
431 + HostId hostId = event.hostId();
432 + Timestamp timestamp = event.timestamp();
433 +
434 + notifyDelegateIfNotNull(removeHostInternal(hostId, timestamp));
300 } 435 }
301 } 436 }
302 } 437 }
......
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import org.onlab.onos.store.cluster.messaging.MessageSubject;
4 +
5 +public final class GossipHostStoreMessageSubjects {
6 + private GossipHostStoreMessageSubjects() {}
7 + public static final MessageSubject HOST_UPDATED = new MessageSubject("peer-host-updated");
8 + public static final MessageSubject HOST_REMOVED = new MessageSubject("peer-host-removed");
9 +}
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import org.onlab.onos.net.HostId;
4 +import org.onlab.onos.net.host.HostDescription;
5 +import org.onlab.onos.net.provider.ProviderId;
6 +import org.onlab.onos.store.Timestamp;
7 +
8 +/**
9 + * Information published by GossipHostStore to notify peers of a host
10 + * change (create/update) event.
11 + */
12 +public class InternalHostEvent {
13 +
14 + private final ProviderId providerId;
15 + private final HostId hostId;
16 + private final HostDescription hostDescription;
17 + private final Timestamp timestamp;
18 +
19 + public InternalHostEvent(ProviderId providerId, HostId hostId,
20 + HostDescription hostDescription, Timestamp timestamp) {
21 + this.providerId = providerId;
22 + this.hostId = hostId;
23 + this.hostDescription = hostDescription;
24 + this.timestamp = timestamp;
25 + }
26 +
27 + public ProviderId providerId() {
28 + return providerId;
29 + }
30 +
31 + public HostId hostId() {
32 + return hostId;
33 + }
34 +
35 + public HostDescription hostDescription() {
36 + return hostDescription;
37 + }
38 +
39 + public Timestamp timestamp() {
40 + return timestamp;
41 + }
42 +
43 + // Needed for serialization.
44 + @SuppressWarnings("unused")
45 + private InternalHostEvent() {
46 + providerId = null;
47 + hostId = null;
48 + hostDescription = null;
49 + timestamp = null;
50 + }
51 +}
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import org.onlab.onos.net.HostId;
4 +import org.onlab.onos.store.Timestamp;
5 +
6 +/**
7 + * Information published by GossipHostStore to notify peers of a host
8 + * removed event.
9 + */
10 +public class InternalHostRemovedEvent {
11 +
12 + private final HostId hostId;
13 + private final Timestamp timestamp;
14 +
15 + public InternalHostRemovedEvent(HostId hostId, Timestamp timestamp) {
16 + this.hostId = hostId;
17 + this.timestamp = timestamp;
18 + }
19 +
20 + public HostId hostId() {
21 + return hostId;
22 + }
23 +
24 + public Timestamp timestamp() {
25 + return timestamp;
26 + }
27 +
28 + // for serialization.
29 + @SuppressWarnings("unused")
30 + private InternalHostRemovedEvent() {
31 + hostId = null;
32 + timestamp = null;
33 + }
34 +}
...@@ -9,7 +9,6 @@ import com.google.common.collect.Maps; ...@@ -9,7 +9,6 @@ import com.google.common.collect.Maps;
9 import com.google.common.collect.SetMultimap; 9 import com.google.common.collect.SetMultimap;
10 10
11 import org.apache.commons.lang3.RandomUtils; 11 import org.apache.commons.lang3.RandomUtils;
12 -import org.apache.commons.lang3.concurrent.ConcurrentUtils;
13 import org.apache.felix.scr.annotations.Activate; 12 import org.apache.felix.scr.annotations.Activate;
14 import org.apache.felix.scr.annotations.Component; 13 import org.apache.felix.scr.annotations.Component;
15 import org.apache.felix.scr.annotations.Deactivate; 14 import org.apache.felix.scr.annotations.Deactivate;
...@@ -46,7 +45,6 @@ import org.onlab.onos.store.common.impl.Timestamped; ...@@ -46,7 +45,6 @@ import org.onlab.onos.store.common.impl.Timestamped;
46 import org.onlab.onos.store.serializers.DistributedStoreSerializers; 45 import org.onlab.onos.store.serializers.DistributedStoreSerializers;
47 import org.onlab.onos.store.serializers.KryoSerializer; 46 import org.onlab.onos.store.serializers.KryoSerializer;
48 import org.onlab.util.KryoPool; 47 import org.onlab.util.KryoPool;
49 -import org.onlab.util.NewConcurrentHashMap;
50 import org.slf4j.Logger; 48 import org.slf4j.Logger;
51 49
52 import java.io.IOException; 50 import java.io.IOException;
...@@ -87,7 +85,7 @@ public class GossipLinkStore ...@@ -87,7 +85,7 @@ public class GossipLinkStore
87 private final Logger log = getLogger(getClass()); 85 private final Logger log = getLogger(getClass());
88 86
89 // Link inventory 87 // Link inventory
90 - private final ConcurrentMap<LinkKey, ConcurrentMap<ProviderId, Timestamped<LinkDescription>>> linkDescs = 88 + private final ConcurrentMap<LinkKey, Map<ProviderId, Timestamped<LinkDescription>>> linkDescs =
91 new ConcurrentHashMap<>(); 89 new ConcurrentHashMap<>();
92 90
93 // Link instance cache 91 // Link instance cache
...@@ -238,7 +236,7 @@ public class GossipLinkStore ...@@ -238,7 +236,7 @@ public class GossipLinkStore
238 236
239 final Timestamped<LinkDescription> deltaDesc = new Timestamped<>(linkDescription, newTimestamp); 237 final Timestamped<LinkDescription> deltaDesc = new Timestamped<>(linkDescription, newTimestamp);
240 238
241 - LinkKey key = linkKey(linkDescription); 239 + LinkKey key = linkKey(linkDescription.src(), linkDescription.dst());
242 final LinkEvent event; 240 final LinkEvent event;
243 final Timestamped<LinkDescription> mergedDesc; 241 final Timestamped<LinkDescription> mergedDesc;
244 synchronized (getLinkDescriptions(key)) { 242 synchronized (getLinkDescriptions(key)) {
...@@ -265,8 +263,9 @@ public class GossipLinkStore ...@@ -265,8 +263,9 @@ public class GossipLinkStore
265 ProviderId providerId, 263 ProviderId providerId,
266 Timestamped<LinkDescription> linkDescription) { 264 Timestamped<LinkDescription> linkDescription) {
267 265
268 - LinkKey key = linkKey(linkDescription.value()); 266 + LinkKey key = linkKey(linkDescription.value().src(),
269 - ConcurrentMap<ProviderId, Timestamped<LinkDescription>> descs = getLinkDescriptions(key); 267 + linkDescription.value().dst());
268 + Map<ProviderId, Timestamped<LinkDescription>> descs = getLinkDescriptions(key);
270 269
271 synchronized (descs) { 270 synchronized (descs) {
272 // if the link was previously removed, we should proceed if and 271 // if the link was previously removed, we should proceed if and
...@@ -293,12 +292,12 @@ public class GossipLinkStore ...@@ -293,12 +292,12 @@ public class GossipLinkStore
293 292
294 // Guarded by linkDescs value (=locking each Link) 293 // Guarded by linkDescs value (=locking each Link)
295 private Timestamped<LinkDescription> createOrUpdateLinkDescription( 294 private Timestamped<LinkDescription> createOrUpdateLinkDescription(
296 - ConcurrentMap<ProviderId, Timestamped<LinkDescription>> existingLinkDescriptions, 295 + Map<ProviderId, Timestamped<LinkDescription>> descs,
297 ProviderId providerId, 296 ProviderId providerId,
298 Timestamped<LinkDescription> linkDescription) { 297 Timestamped<LinkDescription> linkDescription) {
299 298
300 // merge existing attributes and merge 299 // merge existing attributes and merge
301 - Timestamped<LinkDescription> existingLinkDescription = existingLinkDescriptions.get(providerId); 300 + Timestamped<LinkDescription> existingLinkDescription = descs.get(providerId);
302 if (existingLinkDescription != null && existingLinkDescription.isNewer(linkDescription)) { 301 if (existingLinkDescription != null && existingLinkDescription.isNewer(linkDescription)) {
303 return null; 302 return null;
304 } 303 }
...@@ -313,7 +312,7 @@ public class GossipLinkStore ...@@ -313,7 +312,7 @@ public class GossipLinkStore
313 linkDescription.value().type(), merged), 312 linkDescription.value().type(), merged),
314 linkDescription.timestamp()); 313 linkDescription.timestamp());
315 } 314 }
316 - return existingLinkDescriptions.put(providerId, newLinkDescription); 315 + return descs.put(providerId, newLinkDescription);
317 } 316 }
318 317
319 // Creates and stores the link and returns the appropriate event. 318 // Creates and stores the link and returns the appropriate event.
...@@ -379,7 +378,7 @@ public class GossipLinkStore ...@@ -379,7 +378,7 @@ public class GossipLinkStore
379 } 378 }
380 379
381 private LinkEvent removeLinkInternal(LinkKey key, Timestamp timestamp) { 380 private LinkEvent removeLinkInternal(LinkKey key, Timestamp timestamp) {
382 - ConcurrentMap<ProviderId, Timestamped<LinkDescription>> linkDescriptions = 381 + Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions =
383 getLinkDescriptions(key); 382 getLinkDescriptions(key);
384 synchronized (linkDescriptions) { 383 synchronized (linkDescriptions) {
385 // accept removal request if given timestamp is newer than 384 // accept removal request if given timestamp is newer than
...@@ -408,10 +407,10 @@ public class GossipLinkStore ...@@ -408,10 +407,10 @@ public class GossipLinkStore
408 * @return primary ProviderID, or randomly chosen one if none exists 407 * @return primary ProviderID, or randomly chosen one if none exists
409 */ 408 */
410 private ProviderId pickPrimaryProviderId( 409 private ProviderId pickPrimaryProviderId(
411 - ConcurrentMap<ProviderId, Timestamped<LinkDescription>> providerDescs) { 410 + Map<ProviderId, Timestamped<LinkDescription>> linkDescriptions) {
412 411
413 ProviderId fallBackPrimary = null; 412 ProviderId fallBackPrimary = null;
414 - for (Entry<ProviderId, Timestamped<LinkDescription>> e : providerDescs.entrySet()) { 413 + for (Entry<ProviderId, Timestamped<LinkDescription>> e : linkDescriptions.entrySet()) {
415 if (!e.getKey().isAncillary()) { 414 if (!e.getKey().isAncillary()) {
416 return e.getKey(); 415 return e.getKey();
417 } else if (fallBackPrimary == null) { 416 } else if (fallBackPrimary == null) {
...@@ -422,9 +421,9 @@ public class GossipLinkStore ...@@ -422,9 +421,9 @@ public class GossipLinkStore
422 return fallBackPrimary; 421 return fallBackPrimary;
423 } 422 }
424 423
425 - private Link composeLink(ConcurrentMap<ProviderId, Timestamped<LinkDescription>> linkDescriptions) { 424 + private Link composeLink(Map<ProviderId, Timestamped<LinkDescription>> descs) {
426 - ProviderId primaryProviderId = pickPrimaryProviderId(linkDescriptions); 425 + ProviderId primaryProviderId = pickPrimaryProviderId(descs);
427 - Timestamped<LinkDescription> base = linkDescriptions.get(primaryProviderId); 426 + Timestamped<LinkDescription> base = descs.get(primaryProviderId);
428 427
429 ConnectPoint src = base.value().src(); 428 ConnectPoint src = base.value().src();
430 ConnectPoint dst = base.value().dst(); 429 ConnectPoint dst = base.value().dst();
...@@ -432,7 +431,7 @@ public class GossipLinkStore ...@@ -432,7 +431,7 @@ public class GossipLinkStore
432 DefaultAnnotations annotations = DefaultAnnotations.builder().build(); 431 DefaultAnnotations annotations = DefaultAnnotations.builder().build();
433 annotations = merge(annotations, base.value().annotations()); 432 annotations = merge(annotations, base.value().annotations());
434 433
435 - for (Entry<ProviderId, Timestamped<LinkDescription>> e : linkDescriptions.entrySet()) { 434 + for (Entry<ProviderId, Timestamped<LinkDescription>> e : descs.entrySet()) {
436 if (primaryProviderId.equals(e.getKey())) { 435 if (primaryProviderId.equals(e.getKey())) {
437 continue; 436 continue;
438 } 437 }
...@@ -449,9 +448,20 @@ public class GossipLinkStore ...@@ -449,9 +448,20 @@ public class GossipLinkStore
449 return new DefaultLink(primaryProviderId , src, dst, type, annotations); 448 return new DefaultLink(primaryProviderId , src, dst, type, annotations);
450 } 449 }
451 450
452 - private ConcurrentMap<ProviderId, Timestamped<LinkDescription>> getLinkDescriptions(LinkKey key) { 451 + private Map<ProviderId, Timestamped<LinkDescription>> getLinkDescriptions(LinkKey key) {
453 - return ConcurrentUtils.createIfAbsentUnchecked(linkDescs, key, 452 + Map<ProviderId, Timestamped<LinkDescription>> r;
454 - NewConcurrentHashMap.<ProviderId, Timestamped<LinkDescription>>ifNeeded()); 453 + r = linkDescs.get(key);
454 + if (r != null) {
455 + return r;
456 + }
457 + r = new HashMap<>();
458 + final Map<ProviderId, Timestamped<LinkDescription>> concurrentlyAdded;
459 + concurrentlyAdded = linkDescs.putIfAbsent(key, r);
460 + if (concurrentlyAdded != null) {
461 + return concurrentlyAdded;
462 + } else {
463 + return r;
464 + }
455 } 465 }
456 466
457 private Timestamped<LinkDescription> getLinkDescription(LinkKey key, ProviderId providerId) { 467 private Timestamped<LinkDescription> getLinkDescription(LinkKey key, ProviderId providerId) {
...@@ -470,13 +480,13 @@ public class GossipLinkStore ...@@ -470,13 +480,13 @@ public class GossipLinkStore
470 } 480 }
471 } 481 }
472 482
473 - private static final Predicate<Provided> IS_PRIMARY = new IsPrimary();
474 - private static final Predicate<Provided> isPrimary() {
475 - return IS_PRIMARY;
476 - }
477 -
478 private static final class IsPrimary implements Predicate<Provided> { 483 private static final class IsPrimary implements Predicate<Provided> {
479 484
485 + private static final Predicate<Provided> IS_PRIMARY = new IsPrimary();
486 + public static final Predicate<Provided> isPrimary() {
487 + return IS_PRIMARY;
488 + }
489 +
480 @Override 490 @Override
481 public boolean apply(Provided input) { 491 public boolean apply(Provided input) {
482 return !input.providerId().isAncillary(); 492 return !input.providerId().isAncillary();
...@@ -581,11 +591,11 @@ public class GossipLinkStore ...@@ -581,11 +591,11 @@ public class GossipLinkStore
581 Map<LinkFragmentId, Timestamp> linkTimestamps = new HashMap<>(linkDescs.size()); 591 Map<LinkFragmentId, Timestamp> linkTimestamps = new HashMap<>(linkDescs.size());
582 Map<LinkKey, Timestamp> linkTombstones = new HashMap<>(removedLinks.size()); 592 Map<LinkKey, Timestamp> linkTombstones = new HashMap<>(removedLinks.size());
583 593
584 - for (Entry<LinkKey, ConcurrentMap<ProviderId, Timestamped<LinkDescription>>> 594 + for (Entry<LinkKey, Map<ProviderId, Timestamped<LinkDescription>>>
585 provs : linkDescs.entrySet()) { 595 provs : linkDescs.entrySet()) {
586 596
587 final LinkKey linkKey = provs.getKey(); 597 final LinkKey linkKey = provs.getKey();
588 - final ConcurrentMap<ProviderId, Timestamped<LinkDescription>> linkDesc = provs.getValue(); 598 + final Map<ProviderId, Timestamped<LinkDescription>> linkDesc = provs.getValue();
589 synchronized (linkDesc) { 599 synchronized (linkDesc) {
590 for (Map.Entry<ProviderId, Timestamped<LinkDescription>> e : linkDesc.entrySet()) { 600 for (Map.Entry<ProviderId, Timestamped<LinkDescription>> e : linkDesc.entrySet()) {
591 linkTimestamps.put(new LinkFragmentId(linkKey, e.getKey()), e.getValue().timestamp()); 601 linkTimestamps.put(new LinkFragmentId(linkKey, e.getKey()), e.getValue().timestamp());
...@@ -670,7 +680,7 @@ public class GossipLinkStore ...@@ -670,7 +680,7 @@ public class GossipLinkStore
670 680
671 @Override 681 @Override
672 public void handle(ClusterMessage message) { 682 public void handle(ClusterMessage message) {
673 - log.info("Received Link Anti-Entropy advertisement from peer: {}", message.sender()); 683 + log.debug("Received Link Anti-Entropy advertisement from peer: {}", message.sender());
674 LinkAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload()); 684 LinkAntiEntropyAdvertisement advertisement = SERIALIZER.decode(message.payload());
675 handleAntiEntropyAdvertisement(advertisement); 685 handleAntiEntropyAdvertisement(advertisement);
676 } 686 }
......
...@@ -40,22 +40,18 @@ public class ClusterCommunicationManagerTest { ...@@ -40,22 +40,18 @@ public class ClusterCommunicationManagerTest {
40 40
41 @Before 41 @Before
42 public void setUp() throws Exception { 42 public void setUp() throws Exception {
43 - MessageSerializer messageSerializer = new MessageSerializer();
44 - messageSerializer.activate();
45 43
46 NettyMessagingService messagingService = new NettyMessagingService(); 44 NettyMessagingService messagingService = new NettyMessagingService();
47 messagingService.activate(); 45 messagingService.activate();
48 46
49 ccm1 = new ClusterCommunicationManager(); 47 ccm1 = new ClusterCommunicationManager();
50 -// ccm1.serializationService = messageSerializer;
51 ccm1.activate(); 48 ccm1.activate();
52 49
53 ccm2 = new ClusterCommunicationManager(); 50 ccm2 = new ClusterCommunicationManager();
54 -// ccm2.serializationService = messageSerializer;
55 ccm2.activate(); 51 ccm2.activate();
56 52
57 - ccm1.initialize(node1, cnd1); 53 +// ccm1.initialize(node1, cnd1);
58 - ccm2.initialize(node2, cnd2); 54 +// ccm2.initialize(node2, cnd2);
59 } 55 }
60 56
61 @After 57 @After
...@@ -70,7 +66,7 @@ public class ClusterCommunicationManagerTest { ...@@ -70,7 +66,7 @@ public class ClusterCommunicationManagerTest {
70 cnd1.latch = new CountDownLatch(1); 66 cnd1.latch = new CountDownLatch(1);
71 cnd2.latch = new CountDownLatch(1); 67 cnd2.latch = new CountDownLatch(1);
72 68
73 - ccm1.addNode(node2); 69 +// ccm1.addNode(node2);
74 validateDelegateEvent(cnd1, Op.DETECTED, node2.id()); 70 validateDelegateEvent(cnd1, Op.DETECTED, node2.id());
75 validateDelegateEvent(cnd2, Op.DETECTED, node1.id()); 71 validateDelegateEvent(cnd2, Op.DETECTED, node1.id());
76 } 72 }
...@@ -81,7 +77,7 @@ public class ClusterCommunicationManagerTest { ...@@ -81,7 +77,7 @@ public class ClusterCommunicationManagerTest {
81 cnd1.latch = new CountDownLatch(1); 77 cnd1.latch = new CountDownLatch(1);
82 cnd2.latch = new CountDownLatch(1); 78 cnd2.latch = new CountDownLatch(1);
83 79
84 - ccm1.addNode(node2); 80 +// ccm1.addNode(node2);
85 validateDelegateEvent(cnd1, Op.DETECTED, node2.id()); 81 validateDelegateEvent(cnd1, Op.DETECTED, node2.id());
86 validateDelegateEvent(cnd2, Op.DETECTED, node1.id()); 82 validateDelegateEvent(cnd2, Op.DETECTED, node1.id());
87 83
......
...@@ -151,7 +151,7 @@ public class DistributedLinkStore ...@@ -151,7 +151,7 @@ public class DistributedLinkStore
151 @Override 151 @Override
152 public LinkEvent createOrUpdateLink(ProviderId providerId, 152 public LinkEvent createOrUpdateLink(ProviderId providerId,
153 LinkDescription linkDescription) { 153 LinkDescription linkDescription) {
154 - LinkKey key = linkKey(linkDescription); 154 + LinkKey key = linkKey(linkDescription.src(), linkDescription.dst());
155 Optional<DefaultLink> link = links.getUnchecked(key); 155 Optional<DefaultLink> link = links.getUnchecked(key);
156 if (!link.isPresent()) { 156 if (!link.isPresent()) {
157 return createLink(providerId, key, linkDescription); 157 return createLink(providerId, key, linkDescription);
......
...@@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap;
35 import static org.onlab.onos.net.host.HostEvent.Type.*; 35 import static org.onlab.onos.net.host.HostEvent.Type.*;
36 import static org.slf4j.LoggerFactory.getLogger; 36 import static org.slf4j.LoggerFactory.getLogger;
37 37
38 +// TODO: multi-provider, annotation not supported.
38 /** 39 /**
39 * Manages inventory of end-station hosts using trivial in-memory 40 * Manages inventory of end-station hosts using trivial in-memory
40 * implementation. 41 * implementation.
......
...@@ -149,7 +149,7 @@ public class SimpleLinkStore ...@@ -149,7 +149,7 @@ public class SimpleLinkStore
149 @Override 149 @Override
150 public LinkEvent createOrUpdateLink(ProviderId providerId, 150 public LinkEvent createOrUpdateLink(ProviderId providerId,
151 LinkDescription linkDescription) { 151 LinkDescription linkDescription) {
152 - LinkKey key = linkKey(linkDescription); 152 + LinkKey key = linkKey(linkDescription.src(), linkDescription.dst());
153 153
154 ConcurrentMap<ProviderId, LinkDescription> descs = getLinkDescriptions(key); 154 ConcurrentMap<ProviderId, LinkDescription> descs = getLinkDescriptions(key);
155 synchronized (descs) { 155 synchronized (descs) {
......
...@@ -67,16 +67,6 @@ ...@@ -67,16 +67,6 @@
67 <bundle>mvn:org.onlab.onos/onos-core-hz-cluster/1.0.0-SNAPSHOT</bundle> 67 <bundle>mvn:org.onlab.onos/onos-core-hz-cluster/1.0.0-SNAPSHOT</bundle>
68 </feature> 68 </feature>
69 69
70 - <feature name="onos-core-hazelcast" version="1.0.0"
71 - description="ONOS core components built on hazelcast">
72 - <feature>onos-api</feature>
73 - <bundle>mvn:org.onlab.onos/onos-core-net/1.0.0-SNAPSHOT</bundle>
74 - <bundle>mvn:org.onlab.onos/onos-core-hz-common/1.0.0-SNAPSHOT</bundle>
75 - <bundle>mvn:org.onlab.onos/onos-core-serializers/1.0.0-SNAPSHOT</bundle>
76 - <bundle>mvn:org.onlab.onos/onos-core-hz-cluster/1.0.0-SNAPSHOT</bundle>
77 - <bundle>mvn:org.onlab.onos/onos-core-hz-net/1.0.0-SNAPSHOT</bundle>
78 - </feature>
79 -
80 <feature name="onos-core-trivial" version="1.0.0" 70 <feature name="onos-core-trivial" version="1.0.0"
81 description="ONOS core components"> 71 description="ONOS core components">
82 <feature>onos-api</feature> 72 <feature>onos-api</feature>
...@@ -163,4 +153,10 @@ ...@@ -163,4 +153,10 @@
163 <bundle>mvn:org.onlab.onos/onos-app-config/1.0.0-SNAPSHOT</bundle> 153 <bundle>mvn:org.onlab.onos/onos-app-config/1.0.0-SNAPSHOT</bundle>
164 </feature> 154 </feature>
165 155
156 + <feature name="onos-app-sdnip" version="1.0.0"
157 + description="SDN-IP peering application">
158 + <feature>onos-api</feature>
159 + <bundle>mvn:org.onlab.onos/onos-app-sdnip/1.0.0-SNAPSHOT</bundle>
160 + </feature>
161 +
166 </features> 162 </features>
......
...@@ -5,6 +5,7 @@ import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeComplet ...@@ -5,6 +5,7 @@ import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeComplet
5 import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted; 5 import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
6 import org.onlab.onos.openflow.controller.Dpid; 6 import org.onlab.onos.openflow.controller.Dpid;
7 import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch; 7 import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch;
8 +import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
8 import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply; 9 import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
9 import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest; 10 import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
10 import org.projectfloodlight.openflow.protocol.OFDescStatsReply; 11 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
...@@ -21,7 +22,6 @@ import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort; ...@@ -21,7 +22,6 @@ import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort;
21 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigid; 22 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigid;
22 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic; 23 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
23 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtype; 24 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtype;
24 -import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtypeBasic;
25 import org.projectfloodlight.openflow.types.CircuitSignalID; 25 import org.projectfloodlight.openflow.types.CircuitSignalID;
26 import org.projectfloodlight.openflow.types.OFPort; 26 import org.projectfloodlight.openflow.types.OFPort;
27 import org.projectfloodlight.openflow.types.U8; 27 import org.projectfloodlight.openflow.types.U8;
...@@ -119,11 +119,12 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -119,11 +119,12 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
119 processHandshakeOFExperimenterPortDescRequest( 119 processHandshakeOFExperimenterPortDescRequest(
120 (OFCircuitPortsReply) m); 120 (OFCircuitPortsReply) m);
121 driverHandshakeComplete.set(true); 121 driverHandshakeComplete.set(true);
122 - /* try { 122 + try {
123 testMA(); 123 testMA();
124 + testReverseMA();
124 } catch (IOException e) { 125 } catch (IOException e) {
125 e.printStackTrace(); 126 e.printStackTrace();
126 - }*/ 127 + }
127 break; 128 break;
128 default: 129 default:
129 log.debug("Received message {} during switch-driver " + 130 log.debug("Received message {} during switch-driver " +
...@@ -163,22 +164,71 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -163,22 +164,71 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
163 "message " + 164 "message " +
164 "{}", 165 "{}",
165 circuitPortsRequest.toString()); 166 circuitPortsRequest.toString());
166 - channel.write(Collections.singletonList(circuitPortsRequest)); 167 + sendMsg(Collections.<OFMessage>singletonList(circuitPortsRequest));
167 } 168 }
168 169
169 170
170 - 171 + public static final U8 SIGNAL_TYPE = U8.of((short) 10);
171 - //todo for testing
172 - public static final U8 SIGNAL_TYPE = U8.of((short) 1);
173 private void testMA() throws IOException { 172 private void testMA() throws IOException {
174 log.debug("LINC OE *** Testing MA "); 173 log.debug("LINC OE *** Testing MA ");
175 - short lambda = 100; 174 + short lambda = 1;
176 - if (getId() == 0x0000ffffffffff02L) { 175 + if (getId() == 0x0000ffffffffff01L) {
177 final int inport = 10; 176 final int inport = 10;
178 final int outport = 20; 177 final int outport = 20;
179 //Circuit signal id 178 //Circuit signal id
180 CircuitSignalID sigID = getSignalID(lambda); 179 CircuitSignalID sigID = getSignalID(lambda);
181 180
181 + OFOxmOchSigidBasic ofOxmOchSigidBasic =
182 + factory().oxms().ochSigidBasic(sigID);
183 +
184 +
185 + //Match Port
186 + OFOxmInPort fieldPort = factory().oxms()
187 + .inPort(OFPort.of(inport));
188 + OFMatchV3 matchPort =
189 + factory()
190 + .buildMatchV3().
191 + setOxmList(OFOxmList.of(fieldPort)).build();
192 +
193 +
194 + // Set Action outport ,sigType and sigID
195 + List<OFAction> actionList = new ArrayList<>();
196 + OFAction actionOutPort =
197 + factory().actions().output(OFPort.of(outport),
198 + 0xffff);
199 +
200 + OFActionCircuit actionCircuit = factory()
201 + .actions()
202 + .circuit(ofOxmOchSigidBasic);
203 +
204 + actionList.add(actionCircuit);
205 + actionList.add(actionOutPort);
206 +
207 + OFInstruction instructionAction =
208 + factory().instructions().buildApplyActions()
209 + .setActions(actionList)
210 + .build();
211 + List<OFInstruction> instructions =
212 + Collections.singletonList(instructionAction);
213 +
214 + OFMessage opticalFlowEntry =
215 + factory().buildFlowAdd()
216 + .setMatch(matchPort)
217 + .setPriority(100)
218 + .setInstructions(instructions)
219 + .setXid(getNextTransactionId())
220 + .build();
221 + log.debug("Adding optical flow in sw {}", getStringId());
222 + List<OFMessage> msglist = new ArrayList<>(1);
223 + msglist.add(opticalFlowEntry);
224 + write(msglist);
225 + sendBarrier(true);
226 + } else if (getId() == 0x0000ffffffffff03L) {
227 + final int inport = 30;
228 + final int outport = 31;
229 + //Circuit signal id
230 + CircuitSignalID sigID = getSignalID(lambda);
231 +
182 OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID); 232 OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
183 OFOxmOchSigtype fieldSigType = factory() 233 OFOxmOchSigtype fieldSigType = factory()
184 .oxms() 234 .oxms()
...@@ -187,8 +237,119 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -187,8 +237,119 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
187 OFOxmOchSigidBasic ofOxmOchSigidBasic = 237 OFOxmOchSigidBasic ofOxmOchSigidBasic =
188 factory().oxms().ochSigidBasic(sigID); 238 factory().oxms().ochSigidBasic(sigID);
189 239
190 - OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic = 240 + //Match Port,SigType,SigID
191 - factory().oxms().ochSigtypeBasic(SIGNAL_TYPE); 241 + OFOxmInPort fieldPort = factory()
242 + .oxms()
243 + .inPort(OFPort.of(inport));
244 + OFMatchV3 matchPort = factory()
245 + .buildMatchV3()
246 + .setOxmList(OFOxmList.of(fieldPort,
247 + fieldSigIDMatch,
248 + fieldSigType
249 + ))
250 + .build();
251 +
252 + // Set Action outport ,SigType, sigID
253 + List<OFAction> actionList = new ArrayList<>();
254 + OFAction actionOutPort =
255 + factory().actions().output(OFPort.of(outport),
256 + 0xffff);
257 +
258 + OFActionCircuit actionCircuit = factory()
259 + .actions()
260 + .circuit(ofOxmOchSigidBasic);
261 +
262 +
263 +
264 + //actionList.add(setActionSigType);
265 + actionList.add(actionCircuit);
266 + actionList.add(actionOutPort);
267 +
268 + OFInstruction instructionAction =
269 + factory().instructions().buildApplyActions()
270 + .setActions(actionList)
271 + .build();
272 + List<OFInstruction> instructions =
273 + Collections.singletonList(instructionAction);
274 +
275 + OFMessage opticalFlowEntry =
276 + factory().buildFlowAdd()
277 + .setMatch(matchPort)
278 + .setPriority(100)
279 + .setInstructions(instructions)
280 + .setXid(getNextTransactionId())
281 + .build();
282 + log.debug("Adding optical flow in sw {}", getStringId());
283 + List<OFMessage> msglist = new ArrayList<>(1);
284 + msglist.add(opticalFlowEntry);
285 + write(msglist);
286 + sendBarrier(true);
287 +
288 + } else if (getId() == 0x0000ffffffffff02L) {
289 + final int inport = 21;
290 + final int outport = 11;
291 + //Circuit signal id
292 + CircuitSignalID sigID = getSignalID(lambda);
293 +
294 + OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID);
295 + OFOxmOchSigtype fieldSigType = factory()
296 + .oxms()
297 + .ochSigtype(SIGNAL_TYPE);
298 +
299 +
300 + //Match Port, sig type and sig id
301 + OFOxmInPort fieldPort = factory()
302 + .oxms()
303 + .inPort(OFPort.of(inport));
304 + OFMatchV3 matchPort =
305 + factory().buildMatchV3()
306 + .setOxmList(OFOxmList.of(fieldPort,
307 + fieldSigIDMatch,
308 + fieldSigType
309 + ))
310 + .build();
311 +
312 + // Set Action outport
313 + List<OFAction> actionList = new ArrayList<>();
314 + OFAction actionOutPort =
315 + factory().actions().output(OFPort.of(outport),
316 + 0xffff);
317 +
318 + actionList.add(actionOutPort);
319 +
320 + OFInstruction instructionAction =
321 + factory().instructions().buildApplyActions()
322 + .setActions(actionList)
323 + .build();
324 + List<OFInstruction> instructions =
325 + Collections.singletonList(instructionAction);
326 +
327 + OFMessage opticalFlowEntry =
328 + factory().buildFlowAdd()
329 + .setMatch(matchPort)
330 + .setPriority(100)
331 + .setInstructions(instructions)
332 + .setXid(getNextTransactionId())
333 + .build();
334 + log.debug("Adding optical flow in sw {}", getStringId());
335 + List<OFMessage> msglist = new ArrayList<>(1);
336 + msglist.add(opticalFlowEntry);
337 + write(msglist);
338 + sendBarrier(true);
339 + }
340 +
341 + }
342 + private void testReverseMA() throws IOException {
343 + log.debug("LINC OE *** Testing MA ");
344 + short lambda = 1;
345 + if (getId() == 0x0000ffffffffff02L) {
346 + final int inport = 11;
347 + final int outport = 21;
348 + //Circuit signal id
349 + CircuitSignalID sigID = getSignalID(lambda);
350 +
351 + OFOxmOchSigidBasic ofOxmOchSigidBasic =
352 + factory().oxms().ochSigidBasic(sigID);
192 353
193 //Match Port 354 //Match Port
194 OFOxmInPort fieldPort = factory().oxms() 355 OFOxmInPort fieldPort = factory().oxms()
...@@ -196,27 +357,20 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -196,27 +357,20 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
196 OFMatchV3 matchPort = 357 OFMatchV3 matchPort =
197 factory() 358 factory()
198 .buildMatchV3(). 359 .buildMatchV3().
199 - setOxmList(OFOxmList.of(fieldPort, 360 + setOxmList(OFOxmList.of(fieldPort)).build();
200 - fieldSigType,
201 - fieldSigIDMatch)).build();
202 361
203 362
204 // Set Action outport ,sigType and sigID 363 // Set Action outport ,sigType and sigID
205 List<OFAction> actionList = new ArrayList<>(); 364 List<OFAction> actionList = new ArrayList<>();
206 OFAction actionOutPort = 365 OFAction actionOutPort =
207 factory().actions().output(OFPort.of(outport), 366 factory().actions().output(OFPort.of(outport),
208 - Short.MAX_VALUE); 367 + 0xffff);
209 368
210 OFActionCircuit actionCircuit = factory() 369 OFActionCircuit actionCircuit = factory()
211 .actions() 370 .actions()
212 .circuit(ofOxmOchSigidBasic); 371 .circuit(ofOxmOchSigidBasic);
213 - OFActionCircuit setActionSigType = factory()
214 - .actions()
215 - .circuit(ofOxmOchSigtypeBasic);
216 -
217 - actionList.add(actionOutPort);
218 - actionList.add(setActionSigType);
219 actionList.add(actionCircuit); 372 actionList.add(actionCircuit);
373 + actionList.add(actionOutPort);
220 374
221 OFInstruction instructionAction = 375 OFInstruction instructionAction =
222 factory().instructions().buildApplyActions() 376 factory().instructions().buildApplyActions()
...@@ -228,6 +382,7 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -228,6 +382,7 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
228 OFMessage opticalFlowEntry = 382 OFMessage opticalFlowEntry =
229 factory().buildFlowAdd() 383 factory().buildFlowAdd()
230 .setMatch(matchPort) 384 .setMatch(matchPort)
385 + .setPriority(100)
231 .setInstructions(instructions) 386 .setInstructions(instructions)
232 .setXid(getNextTransactionId()) 387 .setXid(getNextTransactionId())
233 .build(); 388 .build();
...@@ -235,9 +390,10 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -235,9 +390,10 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
235 List<OFMessage> msglist = new ArrayList<>(1); 390 List<OFMessage> msglist = new ArrayList<>(1);
236 msglist.add(opticalFlowEntry); 391 msglist.add(opticalFlowEntry);
237 write(msglist); 392 write(msglist);
393 + sendBarrier(true);
238 } else if (getId() == 0x0000ffffffffff03L) { 394 } else if (getId() == 0x0000ffffffffff03L) {
239 - final int inport = 21; 395 + final int inport = 31;
240 - final int outport = 22; 396 + final int outport = 30;
241 //Circuit signal id 397 //Circuit signal id
242 CircuitSignalID sigID = getSignalID(lambda); 398 CircuitSignalID sigID = getSignalID(lambda);
243 399
...@@ -249,9 +405,6 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -249,9 +405,6 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
249 OFOxmOchSigidBasic ofOxmOchSigidBasic = 405 OFOxmOchSigidBasic ofOxmOchSigidBasic =
250 factory().oxms().ochSigidBasic(sigID); 406 factory().oxms().ochSigidBasic(sigID);
251 407
252 - OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic =
253 - factory().oxms().ochSigtypeBasic(SIGNAL_TYPE);
254 -
255 //Match Port,SigType,SigID 408 //Match Port,SigType,SigID
256 OFOxmInPort fieldPort = factory() 409 OFOxmInPort fieldPort = factory()
257 .oxms() 410 .oxms()
...@@ -259,27 +412,22 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -259,27 +412,22 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
259 OFMatchV3 matchPort = factory() 412 OFMatchV3 matchPort = factory()
260 .buildMatchV3() 413 .buildMatchV3()
261 .setOxmList(OFOxmList.of(fieldPort, 414 .setOxmList(OFOxmList.of(fieldPort,
262 - fieldSigType, 415 + fieldSigIDMatch,
263 - fieldSigIDMatch)) 416 + fieldSigType
417 + ))
264 .build(); 418 .build();
265 419
266 // Set Action outport ,SigType, sigID 420 // Set Action outport ,SigType, sigID
267 List<OFAction> actionList = new ArrayList<>(); 421 List<OFAction> actionList = new ArrayList<>();
268 OFAction actionOutPort = 422 OFAction actionOutPort =
269 factory().actions().output(OFPort.of(outport), 423 factory().actions().output(OFPort.of(outport),
270 - Short.MAX_VALUE); 424 + 0xffff);
271 -
272 - OFActionCircuit setActionSigType = factory()
273 - .actions()
274 - .circuit(ofOxmOchSigtypeBasic);
275 OFActionCircuit actionCircuit = factory() 425 OFActionCircuit actionCircuit = factory()
276 .actions() 426 .actions()
277 .circuit(ofOxmOchSigidBasic); 427 .circuit(ofOxmOchSigidBasic);
278 428
279 -
280 - actionList.add(actionOutPort);
281 - actionList.add(setActionSigType);
282 actionList.add(actionCircuit); 429 actionList.add(actionCircuit);
430 + actionList.add(actionOutPort);
283 431
284 OFInstruction instructionAction = 432 OFInstruction instructionAction =
285 factory().instructions().buildApplyActions() 433 factory().instructions().buildApplyActions()
...@@ -290,18 +438,20 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -290,18 +438,20 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
290 438
291 OFMessage opticalFlowEntry = 439 OFMessage opticalFlowEntry =
292 factory().buildFlowAdd() 440 factory().buildFlowAdd()
293 - .setMatch(matchPort) 441 + .setMatch(matchPort)
294 - .setInstructions(instructions) 442 + .setPriority(100)
295 - .setXid(getNextTransactionId()) 443 + .setInstructions(instructions)
296 - .build(); 444 + .setXid(getNextTransactionId())
445 + .build();
297 log.debug("Adding optical flow in sw {}", getStringId()); 446 log.debug("Adding optical flow in sw {}", getStringId());
298 List<OFMessage> msglist = new ArrayList<>(1); 447 List<OFMessage> msglist = new ArrayList<>(1);
299 msglist.add(opticalFlowEntry); 448 msglist.add(opticalFlowEntry);
300 write(msglist); 449 write(msglist);
450 + sendBarrier(true);
301 451
302 - } else if (getId() == 0x0000ffffffffff04L) { 452 + } else if (getId() == 0x0000ffffffffff01L) {
303 - final int inport = 23; 453 + final int inport = 20;
304 - final int outport = 11; 454 + final int outport = 10;
305 //Circuit signal id 455 //Circuit signal id
306 CircuitSignalID sigID = getSignalID(lambda); 456 CircuitSignalID sigID = getSignalID(lambda);
307 457
...@@ -318,15 +468,16 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -318,15 +468,16 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
318 OFMatchV3 matchPort = 468 OFMatchV3 matchPort =
319 factory().buildMatchV3() 469 factory().buildMatchV3()
320 .setOxmList(OFOxmList.of(fieldPort, 470 .setOxmList(OFOxmList.of(fieldPort,
321 - fieldSigType, 471 + fieldSigIDMatch,
322 - fieldSigIDMatch)) 472 + fieldSigType
473 + ))
323 .build(); 474 .build();
324 475
325 // Set Action outport 476 // Set Action outport
326 List<OFAction> actionList = new ArrayList<>(); 477 List<OFAction> actionList = new ArrayList<>();
327 OFAction actionOutPort = 478 OFAction actionOutPort =
328 factory().actions().output(OFPort.of(outport), 479 factory().actions().output(OFPort.of(outport),
329 - Short.MAX_VALUE); 480 + 0xffff);
330 481
331 actionList.add(actionOutPort); 482 actionList.add(actionOutPort);
332 483
...@@ -339,18 +490,21 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -339,18 +490,21 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
339 490
340 OFMessage opticalFlowEntry = 491 OFMessage opticalFlowEntry =
341 factory().buildFlowAdd() 492 factory().buildFlowAdd()
342 - .setMatch(matchPort) 493 + .setMatch(matchPort)
343 - .setInstructions(instructions) 494 + .setPriority(100)
344 - .setXid(getNextTransactionId()) 495 + .setInstructions(instructions)
345 - .build(); 496 + .setXid(getNextTransactionId())
497 + .build();
346 log.debug("Adding optical flow in sw {}", getStringId()); 498 log.debug("Adding optical flow in sw {}", getStringId());
347 List<OFMessage> msglist = new ArrayList<>(1); 499 List<OFMessage> msglist = new ArrayList<>(1);
348 msglist.add(opticalFlowEntry); 500 msglist.add(opticalFlowEntry);
349 write(msglist); 501 write(msglist);
502 + sendBarrier(true);
350 } 503 }
351 504
352 } 505 }
353 506
507 +
354 // Todo remove - for testing purpose only 508 // Todo remove - for testing purpose only
355 private static CircuitSignalID getSignalID(short lambda) { 509 private static CircuitSignalID getSignalID(short lambda) {
356 byte myGrid = 1; 510 byte myGrid = 1;
...@@ -365,9 +519,21 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { ...@@ -365,9 +519,21 @@ public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch {
365 return signalID; 519 return signalID;
366 } 520 }
367 521
522 + private void sendBarrier(boolean finalBarrier) throws IOException {
523 + int xid = getNextTransactionId();
524 + if (finalBarrier) {
525 + barrierXidToWaitFor = xid;
526 + }
527 + OFBarrierRequest br = factory()
528 + .buildBarrierRequest()
529 + .setXid(xid)
530 + .build();
531 + sendMsg(br);
532 + }
533 +
368 @Override 534 @Override
369 public void write(OFMessage msg) { 535 public void write(OFMessage msg) {
370 - this.channel.write(msg); 536 + this.sendMsg(msg);
371 } 537 }
372 538
373 @Override 539 @Override
......
...@@ -304,7 +304,9 @@ ...@@ -304,7 +304,9 @@
304 <plugin> 304 <plugin>
305 <groupId>org.apache.maven.plugins</groupId> 305 <groupId>org.apache.maven.plugins</groupId>
306 <artifactId>maven-compiler-plugin</artifactId> 306 <artifactId>maven-compiler-plugin</artifactId>
307 - <version>3.1</version> 307 + <!-- TODO: update once following issue is fixed. -->
308 + <!-- https://jira.codehaus.org/browse/MCOMPILER-205 -->
309 + <version>2.5.1</version>
308 <configuration> 310 <configuration>
309 <source>1.7</source> 311 <source>1.7</source>
310 <target>1.7</target> 312 <target>1.7</target>
......
...@@ -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().toInt())); 164 + return factory.actions().setNwDst(IPv4Address.of(ip.ip().toRealInt()));
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().toInt())); 167 + return factory.actions().setNwSrc(IPv4Address.of(ip.ip().toRealInt()));
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().toInt()), 223 + Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()),
224 - IPv4Address.of(ip.ip().netmask().toInt())); 224 + IPv4Address.of(ip.ip().netmask().toRealInt()));
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().toInt())); 227 + mBuilder.setExact(MatchField.IPV4_DST, IPv4Address.of(ip.ip().toRealInt()));
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().toInt()), 233 + Masked<IPv4Address> maskedIp = Masked.of(IPv4Address.of(ip.ip().toRealInt()),
234 - IPv4Address.of(ip.ip().netmask().toInt())); 234 + IPv4Address.of(ip.ip().netmask().toRealInt()));
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().toInt())); 237 + mBuilder.setExact(MatchField.IPV4_SRC, IPv4Address.of(ip.ip().toRealInt()));
238 } 238 }
239 break; 239 break;
240 case IP_PROTO: 240 case IP_PROTO:
......
...@@ -9,6 +9,10 @@ export KARAF_ZIP=${KARAF_ZIP:-~/Downloads/apache-karaf-3.0.1.zip} ...@@ -9,6 +9,10 @@ export KARAF_ZIP=${KARAF_ZIP:-~/Downloads/apache-karaf-3.0.1.zip}
9 export KARAF_TAR=${KARAF_TAR:-~/Downloads/apache-karaf-3.0.1.tar.gz} 9 export KARAF_TAR=${KARAF_TAR:-~/Downloads/apache-karaf-3.0.1.tar.gz}
10 export KARAF_DIST=$(basename $KARAF_ZIP .zip) 10 export KARAF_DIST=$(basename $KARAF_ZIP .zip)
11 11
12 +# Add ONOS-specific directories to the exectable PATH
13 +export PATH="$PATH:$ONOS_ROOT/tools/dev/bin:$ONOS_ROOT/tools/test/bin"
14 +export PATH="$PATH:$ONOS_ROOT/tools/build"
15 +
12 # Fallback build number us derived from from the user name & time 16 # Fallback build number us derived from from the user name & time
13 export BUILD_NUMBER=${BUILD_NUMBER:-$(id -un)~$(date +'%Y/%m/%d@%H:%M')} 17 export BUILD_NUMBER=${BUILD_NUMBER:-$(id -un)~$(date +'%Y/%m/%d@%H:%M')}
14 18
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Builds the ONOS from source. 3 # Builds the ONOS from source.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
8 8
9 cd $ONOS_ROOT 9 cd $ONOS_ROOT
10 -mvn clean install && mvn javadoc:aggregate
...\ No newline at end of file ...\ No newline at end of file
10 +mvn clean install && mvn javadoc:aggregate
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Packages ONOS distributable into onos.tar.gz 3 # Packages ONOS distributable into onos.tar.gz
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Launches the ONOS tests on the current cell environment. 3 # Launches the ONOS tests on the current cell environment.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
...@@ -61,15 +61,14 @@ function cell { ...@@ -61,15 +61,14 @@ function cell {
61 if [ -n "$1" ]; then 61 if [ -n "$1" ]; then
62 [ ! -f $ONOS_ROOT/tools/test/cells/$1 ] && \ 62 [ ! -f $ONOS_ROOT/tools/test/cells/$1 ] && \
63 echo "No such cell: $1" >&2 && return 1 63 echo "No such cell: $1" >&2 && return 1
64 + unset ONOS_CELL ONOS_NIC ONOS_FEATURES
64 unset OC1 OC2 OC3 OC4 OC5 OC6 OC7 OC8 OC9 OCN OCI 65 unset OC1 OC2 OC3 OC4 OC5 OC6 OC7 OC8 OC9 OCN OCI
65 . $ONOS_ROOT/tools/test/cells/$1 66 . $ONOS_ROOT/tools/test/cells/$1
66 - export OCI=$OC1
67 - export ONOS_CELL=$1
68 cell 67 cell
69 else 68 else
70 env | egrep "ONOS_CELL" 69 env | egrep "ONOS_CELL"
71 env | egrep "OCI" 70 env | egrep "OCI"
72 - env | egrep "OC[0-9]+" | sort 71 + env | egrep "OC[1-9]+" | sort
73 env | egrep "OCN" 72 env | egrep "OCN"
74 env | egrep "ONOS_" | egrep -v 'ONOS_ROOT|ONOS_CELL' 73 env | egrep "ONOS_" | egrep -v 'ONOS_ROOT|ONOS_CELL'
75 fi 74 fi
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------ 2 +# ----------------------------------------------------------------------------
3 # Selectively builds only those projects that contained modified Java files. 3 # Selectively builds only those projects that contained modified Java files.
4 -#------------------------------------------------------------------------------ 4 +# ----------------------------------------------------------------------------
5 5
6 projects=$(find $ONOS_ROOT -name '*.java' \ 6 projects=$(find $ONOS_ROOT -name '*.java' \
7 -not -path '*/openflowj/*' -and -not -path '.git/*' \ 7 -not -path '*/openflowj/*' -and -not -path '.git/*' \
...@@ -9,4 +9,4 @@ projects=$(find $ONOS_ROOT -name '*.java' \ ...@@ -9,4 +9,4 @@ projects=$(find $ONOS_ROOT -name '*.java' \
9 sort -u | sed "s:$ONOS_ROOT::g" | tr '\n' ',' | \ 9 sort -u | sed "s:$ONOS_ROOT::g" | tr '\n' ',' | \
10 sed 's:/,:,:g;s:,/:,:g;s:^/::g;s:,$::g') 10 sed 's:/,:,:g;s:,/:,:g;s:^/::g;s:,$::g')
11 11
12 -[ -n "$projects" ] && cd $ONOS_ROOT && mvn --projects $projects ${@:-clean install}
...\ No newline at end of file ...\ No newline at end of file
12 +[ -n "$projects" ] && cd $ONOS_ROOT && mvn --projects $projects ${@:-clean install}
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------ 2 +# ----------------------------------------------------------------------------
3 # Echoes project-level directory if a Java file within is newer than the 3 # Echoes project-level directory if a Java file within is newer than the
4 # target directory. 4 # target directory.
5 -#------------------------------------------------------------------------------ 5 +# ----------------------------------------------------------------------------
6 6
7 javaFile=${1#*\/src\/*\/java/} 7 javaFile=${1#*\/src\/*\/java/}
8 basename=${1/*\//} 8 basename=${1/*\//}
...@@ -14,4 +14,3 @@ project=${src/src*/} ...@@ -14,4 +14,3 @@ project=${src/src*/}
14 target=$project/target 14 target=$project/target
15 15
16 [ $target -nt ${src}$javaFile ] || echo ${src/src*/} 16 [ $target -nt ${src}$javaFile ] || echo ${src/src*/}
17 -
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------ 2 +# ----------------------------------------------------------------------------
3 # Continuously watches the Apache Karaf log; survives 'karaf clean' 3 # Continuously watches the Apache Karaf log; survives 'karaf clean'
4 -#------------------------------------------------------------------------------ 4 +# ----------------------------------------------------------------------------
5 KARAF_LOG=${KARAF_LOG:-~/apache-karaf-3.0.1/data/log/karaf.log} 5 KARAF_LOG=${KARAF_LOG:-~/apache-karaf-3.0.1/data/log/karaf.log}
6 6
7 while true; do 7 while true; do
8 [ ! -f $KARAF_LOG ] && sleep 2 && continue 8 [ ! -f $KARAF_LOG ] && sleep 2 && continue
9 tail -n 512 -f -F $KARAF_LOG 9 tail -n 512 -f -F $KARAF_LOG
10 done 10 done
11 -
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # ONOS command-line client 3 # ONOS command-line client
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/} 6 export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/}
7 7
8 cd $(dirname $0)/../apache-karaf-*/bin 8 cd $(dirname $0)/../apache-karaf-*/bin
9 ./client -h localhost "$@" 9 ./client -h localhost "$@"
10 -
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Starts ONOS Apache Karaf container 3 # Starts ONOS Apache Karaf container
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/} 6 export JAVA_HOME=${JAVA_HOME:-/usr/lib/jvm/java-7-openjdk-amd64/}
7 export JAVA_OPTS="-Xms256M -Xmx2048M" 7 export JAVA_OPTS="-Xms256M -Xmx2048M"
8 8
9 cd /opt/onos 9 cd /opt/onos
10 /opt/onos/apache-karaf-3.0.1/bin/karaf "$@" 10 /opt/onos/apache-karaf-3.0.1/bin/karaf "$@"
11 -
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # ONOS remote command-line client. 3 # ONOS remote command-line client.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 +
6 +[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 +. $ONOS_ROOT/tools/build/envDefaults
5 8
6 [ "$1" = "-w" ] && shift && onos-wait-for-start $1 9 [ "$1" = "-w" ] && shift && onos-wait-for-start $1
7 10
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Checks the logs of the remote ONOS instance and makes sure they are clean. 3 # Checks the logs of the remote ONOS instance and makes sure they are clean.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Remotely configures & starts ONOS for the first time. 3 # Remotely configures & starts ONOS for the first time.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
...@@ -24,5 +24,4 @@ ssh $remote " ...@@ -24,5 +24,4 @@ ssh $remote "
24 echo \"onos.ip = \$(ifconfig | grep $ONOS_NIC | cut -d: -f2 | cut -d\\ -f1)\" \ 24 echo \"onos.ip = \$(ifconfig | grep $ONOS_NIC | cut -d: -f2 | cut -d\\ -f1)\" \
25 >> $ONOS_INSTALL_DIR/$KARAF_DIST/etc/system.properties 25 >> $ONOS_INSTALL_DIR/$KARAF_DIST/etc/system.properties
26 " 26 "
27 -
28 -scp -q $CDEF_FILE $remote:$ONOS_INSTALL_DIR/config/
...\ No newline at end of file ...\ No newline at end of file
27 +scp -q $CDEF_FILE $remote:$ONOS_INSTALL_DIR/config/
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Remotely fetches the ONOS test VMs from a local share into ~/Downloads. 3 # Remotely fetches the ONOS test VMs from a local share into ~/Downloads.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Launches ONOS GUI on the specified node. 3 # Launches ONOS GUI on the specified node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 +
6 +[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 +. $ONOS_ROOT/tools/build/envDefaults
5 8
6 host=${1:-$OCI} 9 host=${1:-$OCI}
7 host=${host:-localhost} 10 host=${host:-localhost}
8 11
9 -open http://$host:8181/onos/tvue
...\ No newline at end of file ...\ No newline at end of file
12 +open http://$host:8181/onos/tvue
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Remotely pushes bits to a remote node and installs ONOS on it. 3 # Remotely pushes bits to a remote node and installs ONOS on it.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
...@@ -18,7 +18,7 @@ ssh $remote " ...@@ -18,7 +18,7 @@ ssh $remote "
18 [ -d $ONOS_INSTALL_DIR/bin ] && echo \"ONOS is already installed\" && exit 1 18 [ -d $ONOS_INSTALL_DIR/bin ] && echo \"ONOS is already installed\" && exit 1
19 19
20 # Prepare a landing zone and unroll the bits 20 # Prepare a landing zone and unroll the bits
21 - sudo mkdir -p $ONOS_INSTALL_DIR && sudo chown sdn:sdn $ONOS_INSTALL_DIR 21 + sudo mkdir -p $ONOS_INSTALL_DIR && sudo chown ${ONOS_USER}:${ONOS_USER} $ONOS_INSTALL_DIR
22 tar zxmf /tmp/$ONOS_BITS.tar.gz -C $ONOS_INSTALL_DIR --strip-components=1 22 tar zxmf /tmp/$ONOS_BITS.tar.gz -C $ONOS_INSTALL_DIR --strip-components=1
23 23
24 # Make a link to the log file directory and make a home for auxiliaries 24 # Make a link to the log file directory and make a home for auxiliaries
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Remotely kills the ONOS service on the specified node. 3 # Remotely kills the ONOS service on the specified node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
8 8
9 -ssh $ONOS_USER@${1:-$OCI} "kill -9 \$(ps -ef | grep karaf.jar | grep -v grep | cut -c10-15)"
...\ No newline at end of file ...\ No newline at end of file
9 +ssh $ONOS_USER@${1:-$OCI} "kill -9 \$(ps -ef | grep karaf.jar | grep -v grep | cut -c10-15)"
......
1 +#!/bin/bash
2 +# -----------------------------------------------------------------------------
3 +# List available ONOS cells configuration.
4 +# -----------------------------------------------------------------------------
5 +
6 +[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 +. $ONOS_ROOT/tools/build/envDefaults
8 +
9 +# Lists available cells
10 +for cell in $(ls -1 $ONOS_ROOT/tools/test/cells); do
11 + if [ ${cell} = "${ONOS_CELL}" ]; then
12 + cell_id="${cell} *"
13 + else
14 + cell_id="${cell}"
15 + fi
16 + cell_descr="$(grep '^#' $ONOS_ROOT/tools/test/cells/$cell | head -n 1)"
17 + printf "%-12s %s\n" "${cell_id}" "${cell_descr}"
18 +done
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Monitors remote ONOS log file on the specified node. 3 # Monitors remote ONOS log file on the specified node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Remotely patches the ONOS VM to tailor its hostname. 3 # Remotely patches the ONOS VM to tailor its hostname.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Pushes the local id_rsa.pub to the authorized_keys on a remote ONOS node. 3 # Pushes the local id_rsa.pub to the authorized_keys on a remote ONOS node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Pushes the specified bundle to the remote ONOS cell machines and updates it. 3 # Pushes the specified bundle to the remote ONOS cell machines and updates it.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Remotely administers the ONOS service on the specified node. 3 # Remotely administers the ONOS service on the specified node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
8 8
9 -ssh $ONOS_USER@${1:-$OCI} "sudo service onos ${2:-status}"
...\ No newline at end of file ...\ No newline at end of file
9 +ssh $ONOS_USER@${1:-$OCI} "sudo service onos ${2:-status}"
......
1 +#!/bin/bash
2 +# -----------------------------------------------------------------------------
3 +# Print the configuration of an ONOS cell.
4 +# -----------------------------------------------------------------------------
5 +
6 +[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 +. $ONOS_ROOT/tools/build/envDefaults
8 +
9 +function print_usage {
10 + echo "Print the configuration of an ONOS cell."
11 + echo "If no arguments are specified, it will print the configuration for the default"
12 + echo "ONOS cell as specified in the 'ONOS_CELL' environmental variable."
13 + echo
14 + echo "Optional arguments:"
15 + echo " [cell-name] Print the configuration of 'cell-name'"
16 + echo " [-h | --help] Print this help"
17 +}
18 +
19 +if [ "${1}" = "-h" -o "${1}" = "--help" ]; then
20 + print_usage
21 + exit 0
22 +fi
23 +
24 +if [ -n "${1}" ]; then
25 + cell="${1}"
26 +else
27 + if [ -z "${ONOS_CELL}" ]; then
28 + echo "Environmental variable 'ONOS_CELL' is not defiled"
29 + exit 1
30 + else
31 + cell="${ONOS_CELL}"
32 + fi
33 +fi
34 +
35 +if [ ! -f $ONOS_ROOT/tools/test/cells/${cell} ]; then
36 + echo "No such cell: ${cell}"
37 + exit 1
38 +fi
39 +
40 +# Load the cell setup
41 +. $ONOS_ROOT/tools/test/cells/${cell}
42 +
43 +echo "ONOS_CELL=${ONOS_CELL}"
44 +echo "ONOS_NIC=${ONOS_NIC}"
45 +for n in {1..9}; do
46 + ocn="OC${n}"
47 + if [ -n "${!ocn}" ]; then
48 + echo "$ocn=${!ocn}"
49 + fi
50 +done
51 +echo "OCN=${OCN}"
52 +echo "OCI=${OCI}"
53 +echo "ONOS_FEATURES=${ONOS_FEATURES}"
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Logs in to the remote ONOS node. 3 # Logs in to the remote ONOS node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Verifies connectivity to each node in ONOS cell. 3 # Verifies connectivity to each node in ONOS cell.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Remotely stops & uninstalls ONOS on the specified node. 3 # Remotely stops & uninstalls ONOS on the specified node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Update bundle on locally running karaf. 3 # Update bundle on locally running karaf.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Verifies connectivity to each node in ONOS cell. 3 # Verifies connectivity to each node in ONOS cell.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
8 8
9 for node in $(env | sort | egrep "OC[0-9N]+" | cut -d= -f2); do 9 for node in $(env | sort | egrep "OC[0-9N]+" | cut -d= -f2); do
10 printf "%s: " $node; ssh -n -o PasswordAuthentication=no $ONOS_USER@$node date 10 printf "%s: " $node; ssh -n -o PasswordAuthentication=no $ONOS_USER@$node date
11 -done
...\ No newline at end of file ...\ No newline at end of file
11 +done
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Waits for ONOS to reach run-level 100 on the specified remote node. 3 # Waits for ONOS to reach run-level 100 on the specified remote node.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 #!/bin/bash 1 #!/bin/bash
2 -#------------------------------------------------------------------------------- 2 +# -----------------------------------------------------------------------------
3 # Monitors selected set of ONOS commands using the system watch command. 3 # Monitors selected set of ONOS commands using the system watch command.
4 -#------------------------------------------------------------------------------- 4 +# -----------------------------------------------------------------------------
5 5
6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 6 [ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 . $ONOS_ROOT/tools/build/envDefaults 7 . $ONOS_ROOT/tools/build/envDefaults
......
1 # Local VirtualBox-based single ONOS instance & ONOS mininet box 1 # Local VirtualBox-based single ONOS instance & ONOS mininet box
2 2
3 +export ONOS_CELL="cbench"
4 +
3 export ONOS_NIC=192.168.56.* 5 export ONOS_NIC=192.168.56.*
4 export OC1="192.168.56.103" 6 export OC1="192.168.56.103"
5 export OCN="192.168.56.103" 7 export OCN="192.168.56.103"
8 +export OCI="${OC1}"
6 9
7 export ONOS_FEATURES="webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd" 10 export ONOS_FEATURES="webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd"
......
1 # Local VirtualBox-based ONOS instances 1,2 & ONOS mininet box 1 # Local VirtualBox-based ONOS instances 1,2 & ONOS mininet box
2 2
3 +export ONOS_CELL="local"
4 +
3 export ONOS_NIC=192.168.56.* 5 export ONOS_NIC=192.168.56.*
4 export OC1="192.168.56.101" 6 export OC1="192.168.56.101"
5 export OC2="192.168.56.102" 7 export OC2="192.168.56.102"
6 -
7 export OCN="192.168.56.103" 8 export OCN="192.168.56.103"
9 +export OCI="${OC1}"
8 10
9 - 11 +export ONOS_FEATURES=""
......
1 # ProxMox-based cell of ONOS instance; no mininet-box 1 # ProxMox-based cell of ONOS instance; no mininet-box
2 2
3 -export ONOS_FEATURES="webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd,onos-app-mobility,onos-app-tvue,onos-app-proxyarp" 3 +export ONOS_CELL="office"
4 4
5 export ONOS_NIC="10.128.4.*" 5 export ONOS_NIC="10.128.4.*"
6 export OC1="10.128.4.60" 6 export OC1="10.128.4.60"
7 +export OCI="${OC1}"
7 8
9 +export ONOS_FEATURES="webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd,onos-app-mobility,onos-app-tvue,onos-app-proxyarp"
......
1 # ProxMox-based cell of ONOS instances 1,2 & ONOS mininet box 1 # ProxMox-based cell of ONOS instances 1,2 & ONOS mininet box
2 2
3 +export ONOS_CELL="prox"
4 +
3 export ONOS_NIC="10.1.9.*" 5 export ONOS_NIC="10.1.9.*"
4 export OC1="10.1.9.94" 6 export OC1="10.1.9.94"
5 export OC2="10.1.9.82" 7 export OC2="10.1.9.82"
6 -
7 export OCN="10.1.9.93" 8 export OCN="10.1.9.93"
9 +export OCI="${OC1}"
10 +
11 +export ONOS_FEATURES=""
......
1 # Local VirtualBox-based single ONOS instance & ONOS mininet box 1 # Local VirtualBox-based single ONOS instance & ONOS mininet box
2 2
3 +export ONOS_CELL="single"
4 +
3 export ONOS_NIC=192.168.56.* 5 export ONOS_NIC=192.168.56.*
4 export OC1="192.168.56.101" 6 export OC1="192.168.56.101"
5 export OCN="192.168.56.103" 7 export OCN="192.168.56.103"
8 +export OCI="${OC1}"
6 9
10 +export ONOS_FEATURES=""
......
1 # Local VirtualBox-based ONOS instances 1,2,3 & ONOS mininet box 1 # Local VirtualBox-based ONOS instances 1,2,3 & ONOS mininet box
2 2
3 +export ONOS_CELL="triple"
4 +
3 export ONOS_NIC=192.168.56.* 5 export ONOS_NIC=192.168.56.*
4 export OC1="192.168.56.101" 6 export OC1="192.168.56.101"
5 export OC2="192.168.56.102" 7 export OC2="192.168.56.102"
6 export OC3="192.168.56.104" 8 export OC3="192.168.56.104"
7 -
8 export OCN="192.168.56.103" 9 export OCN="192.168.56.103"
10 +export OCI="${OC1}"
9 11
12 +export ONOS_FEATURES=""
......
...@@ -181,6 +181,15 @@ public final class IpAddress { ...@@ -181,6 +181,15 @@ public final class IpAddress {
181 return address; 181 return address;
182 } 182 }
183 183
184 + public int toRealInt() {
185 + int val = 0;
186 + for (int i = 0; i < octets.length; i++) {
187 + val <<= 8;
188 + val |= octets[i] & 0xff;
189 + }
190 + return val;
191 + }
192 +
184 /** 193 /**
185 * Helper for computing the mask value from CIDR. 194 * Helper for computing the mask value from CIDR.
186 * 195 *
......
...@@ -3,7 +3,6 @@ package org.onlab.util; ...@@ -3,7 +3,6 @@ package org.onlab.util;
3 import java.util.concurrent.ConcurrentHashMap; 3 import java.util.concurrent.ConcurrentHashMap;
4 import java.util.concurrent.ConcurrentMap; 4 import java.util.concurrent.ConcurrentMap;
5 5
6 -import org.apache.commons.lang3.concurrent.ConcurrentException;
7 import org.apache.commons.lang3.concurrent.ConcurrentInitializer; 6 import org.apache.commons.lang3.concurrent.ConcurrentInitializer;
8 7
9 /** 8 /**
...@@ -27,7 +26,7 @@ public final class NewConcurrentHashMap<K, V> ...@@ -27,7 +26,7 @@ public final class NewConcurrentHashMap<K, V>
27 } 26 }
28 27
29 @Override 28 @Override
30 - public ConcurrentMap<K, V> get() throws ConcurrentException { 29 + public ConcurrentMap<K, V> get() {
31 return new ConcurrentHashMap<>(); 30 return new ConcurrentHashMap<>();
32 } 31 }
33 } 32 }
......
...@@ -108,5 +108,10 @@ public class IpPrefixTest { ...@@ -108,5 +108,10 @@ public class IpPrefixTest {
108 IpAddress addr = IpAddress.valueOf("192.168.10.1"); 108 IpAddress addr = IpAddress.valueOf("192.168.10.1");
109 109
110 assertTrue(intf.contains(addr)); 110 assertTrue(intf.contains(addr));
111 +
112 + IpPrefix intf1 = IpPrefix.valueOf("10.0.0.101/24");
113 + IpAddress addr1 = IpAddress.valueOf("10.0.0.4");
114 +
115 + assertTrue(intf1.contains(addr1));
111 } 116 }
112 } 117 }
......
...@@ -15,7 +15,7 @@ import static org.onlab.util.Tools.namedThreads; ...@@ -15,7 +15,7 @@ import static org.onlab.util.Tools.namedThreads;
15 */ 15 */
16 public abstract class AbstractLoopTest { 16 public abstract class AbstractLoopTest {
17 17
18 - protected static final long MAX_MS_WAIT = 500; 18 + protected static final long MAX_MS_WAIT = 1500;
19 19
20 /** Block on specified countdown latch. Return when countdown reaches 20 /** Block on specified countdown latch. Return when countdown reaches
21 * zero, or fail the test if the {@value #MAX_MS_WAIT} ms timeout expires. 21 * zero, or fail the test if the {@value #MAX_MS_WAIT} ms timeout expires.
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
2 <html> 2 <html>
3 <head> 3 <head>
4 <title>ONOS GUI</title> 4 <title>ONOS GUI</title>
5 +
6 + <script src="libs/d3.min.js"></script>
7 + <script src="libs/jquery-2.1.1.min.js"></script>
5 </head> 8 </head>
6 <body> 9 <body>
7 <h1>ONOS GUI</h1> 10 <h1>ONOS GUI</h1>
......