Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
80 changed files
with
2070 additions
and
552 deletions
... | @@ -368,12 +368,12 @@ public class OpticalConfigProvider extends AbstractProvider implements DevicePro | ... | @@ -368,12 +368,12 @@ public class OpticalConfigProvider extends AbstractProvider implements DevicePro |
368 | } | 368 | } |
369 | 369 | ||
370 | @Override | 370 | @Override |
371 | - public void roleChanged(Device device, MastershipRole newRole) { | 371 | + public void roleChanged(DeviceId device, MastershipRole newRole) { |
372 | // TODO Auto-generated method stub. | 372 | // TODO Auto-generated method stub. |
373 | } | 373 | } |
374 | 374 | ||
375 | @Override | 375 | @Override |
376 | - public boolean isReachable(Device device) { | 376 | + public boolean isReachable(DeviceId device) { |
377 | return false; | 377 | return false; |
378 | } | 378 | } |
379 | } | 379 | } | ... | ... |
... | @@ -246,11 +246,13 @@ public class BgpSession extends SimpleChannelHandler { | ... | @@ -246,11 +246,13 @@ public class BgpSession extends SimpleChannelHandler { |
246 | InetAddress inetAddr; | 246 | InetAddress inetAddr; |
247 | if (localAddress instanceof InetSocketAddress) { | 247 | if (localAddress instanceof InetSocketAddress) { |
248 | inetAddr = ((InetSocketAddress) localAddress).getAddress(); | 248 | inetAddr = ((InetSocketAddress) localAddress).getAddress(); |
249 | - localIp4Address = IpAddress.valueOf(inetAddr.getAddress()); | 249 | + localIp4Address = IpAddress.valueOf(IpAddress.Version.INET, |
250 | + inetAddr.getAddress()); | ||
250 | } | 251 | } |
251 | if (remoteAddress instanceof InetSocketAddress) { | 252 | if (remoteAddress instanceof InetSocketAddress) { |
252 | inetAddr = ((InetSocketAddress) remoteAddress).getAddress(); | 253 | inetAddr = ((InetSocketAddress) remoteAddress).getAddress(); |
253 | - remoteIp4Address = IpAddress.valueOf(inetAddr.getAddress()); | 254 | + remoteIp4Address = IpAddress.valueOf(IpAddress.Version.INET, |
255 | + inetAddr.getAddress()); | ||
254 | } | 256 | } |
255 | 257 | ||
256 | log.debug("BGP Session Connected from {} on {}", | 258 | log.debug("BGP Session Connected from {} on {}", | ... | ... |
... | @@ -105,7 +105,8 @@ public class BgpSessionManager { | ... | @@ -105,7 +105,8 @@ public class BgpSessionManager { |
105 | if (bgpSession.getLocalAddress() instanceof InetSocketAddress) { | 105 | if (bgpSession.getLocalAddress() instanceof InetSocketAddress) { |
106 | InetAddress inetAddr = | 106 | InetAddress inetAddr = |
107 | ((InetSocketAddress) bgpSession.getLocalAddress()).getAddress(); | 107 | ((InetSocketAddress) bgpSession.getLocalAddress()).getAddress(); |
108 | - IpAddress ip4Address = IpAddress.valueOf(inetAddr.getAddress()); | 108 | + IpAddress ip4Address = IpAddress.valueOf(IpAddress.Version.INET, |
109 | + inetAddr.getAddress()); | ||
109 | updateMyBgpId(ip4Address); | 110 | updateMyBgpId(ip4Address); |
110 | } | 111 | } |
111 | return true; | 112 | return true; | ... | ... |
... | @@ -74,7 +74,7 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { | ... | @@ -74,7 +74,7 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { |
74 | * @param deviceString string representing the device/port | 74 | * @param deviceString string representing the device/port |
75 | * @return port number as a string, empty string if the port is not found | 75 | * @return port number as a string, empty string if the port is not found |
76 | */ | 76 | */ |
77 | - private String getPortNumber(String deviceString) { | 77 | + public static String getPortNumber(String deviceString) { |
78 | int slash = deviceString.indexOf('/'); | 78 | int slash = deviceString.indexOf('/'); |
79 | if (slash <= 0) { | 79 | if (slash <= 0) { |
80 | return ""; | 80 | return ""; |
... | @@ -88,7 +88,7 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { | ... | @@ -88,7 +88,7 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand { |
88 | * @param deviceString string representing the device/port | 88 | * @param deviceString string representing the device/port |
89 | * @return device ID string | 89 | * @return device ID string |
90 | */ | 90 | */ |
91 | - private String getDeviceId(String deviceString) { | 91 | + public static String getDeviceId(String deviceString) { |
92 | int slash = deviceString.indexOf('/'); | 92 | int slash = deviceString.indexOf('/'); |
93 | if (slash <= 0) { | 93 | if (slash <= 0) { |
94 | return ""; | 94 | return ""; | ... | ... |
... | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ... | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
20 | import com.fasterxml.jackson.databind.node.ArrayNode; | 20 | import com.fasterxml.jackson.databind.node.ArrayNode; |
21 | import com.fasterxml.jackson.databind.node.ObjectNode; | 21 | import com.fasterxml.jackson.databind.node.ObjectNode; |
22 | import org.apache.karaf.shell.commands.Command; | 22 | import org.apache.karaf.shell.commands.Command; |
23 | +import org.apache.karaf.shell.commands.Option; | ||
23 | import org.onlab.onos.cli.AbstractShellCommand; | 24 | import org.onlab.onos.cli.AbstractShellCommand; |
24 | import org.onlab.onos.net.ConnectPoint; | 25 | import org.onlab.onos.net.ConnectPoint; |
25 | import org.onlab.onos.net.Link; | 26 | import org.onlab.onos.net.Link; |
... | @@ -44,6 +45,11 @@ import java.util.Set; | ... | @@ -44,6 +45,11 @@ import java.util.Set; |
44 | description = "Lists the inventory of intents and their states") | 45 | description = "Lists the inventory of intents and their states") |
45 | public class IntentsListCommand extends AbstractShellCommand { | 46 | public class IntentsListCommand extends AbstractShellCommand { |
46 | 47 | ||
48 | + @Option(name = "-i", aliases = "--installable", description = "Output Installable Intents", | ||
49 | + required = false, multiValued = false) | ||
50 | + private boolean showInstallable = false; | ||
51 | + | ||
52 | + | ||
47 | @Override | 53 | @Override |
48 | protected void execute() { | 54 | protected void execute() { |
49 | IntentService service = get(IntentService.class); | 55 | IntentService service = get(IntentService.class); |
... | @@ -93,7 +99,7 @@ public class IntentsListCommand extends AbstractShellCommand { | ... | @@ -93,7 +99,7 @@ public class IntentsListCommand extends AbstractShellCommand { |
93 | } | 99 | } |
94 | 100 | ||
95 | List<Intent> installable = service.getInstallableIntents(intent.id()); | 101 | List<Intent> installable = service.getInstallableIntents(intent.id()); |
96 | - if (installable != null && !installable.isEmpty()) { | 102 | + if (showInstallable && installable != null && !installable.isEmpty()) { |
97 | print(" installable=%s", installable); | 103 | print(" installable=%s", installable); |
98 | } | 104 | } |
99 | } | 105 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onlab.onos.cli.net; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onlab.onos.cli.AbstractShellCommand; | ||
21 | +import org.onlab.onos.net.ConnectPoint; | ||
22 | +import org.onlab.onos.net.DeviceId; | ||
23 | +import org.onlab.onos.net.Link; | ||
24 | +import org.onlab.onos.net.PortNumber; | ||
25 | +import org.onlab.onos.net.link.LinkService; | ||
26 | +import org.onlab.onos.net.resource.LinkResourceAllocations; | ||
27 | +import org.onlab.onos.net.resource.LinkResourceService; | ||
28 | + | ||
29 | +import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getDeviceId; | ||
30 | +import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getPortNumber; | ||
31 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
32 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
33 | + | ||
34 | +/** | ||
35 | + * Lists allocations by link. | ||
36 | + */ | ||
37 | +@Command(scope = "onos", name = "resource-allocations", | ||
38 | + description = "Lists allocations by link") | ||
39 | +public class ResourceAllocationsCommand extends AbstractShellCommand { | ||
40 | + | ||
41 | + private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s"; | ||
42 | + private static final String COMPACT = "%s/%s-%s/%s"; | ||
43 | + | ||
44 | + @Argument(index = 0, name = "srcString", description = "Link source", | ||
45 | + required = false, multiValued = false) | ||
46 | + String srcString = null; | ||
47 | + @Argument(index = 1, name = "dstString", description = "Link destination", | ||
48 | + required = false, multiValued = false) | ||
49 | + String dstString = null; | ||
50 | + | ||
51 | + @Override | ||
52 | + protected void execute() { | ||
53 | + LinkResourceService resourceService = get(LinkResourceService.class); | ||
54 | + LinkService linkService = get(LinkService.class); | ||
55 | + | ||
56 | + Iterable<LinkResourceAllocations> itr = null; | ||
57 | + try { | ||
58 | + DeviceId ingressDeviceId = deviceId(getDeviceId(srcString)); | ||
59 | + PortNumber ingressPortNumber = portNumber(getPortNumber(srcString)); | ||
60 | + ConnectPoint src = new ConnectPoint(ingressDeviceId, ingressPortNumber); | ||
61 | + | ||
62 | + DeviceId egressDeviceId = deviceId(getDeviceId(dstString)); | ||
63 | + PortNumber egressPortNumber = portNumber(getPortNumber(dstString)); | ||
64 | + ConnectPoint dst = new ConnectPoint(egressDeviceId, egressPortNumber); | ||
65 | + | ||
66 | + Link link = linkService.getLink(src, dst); | ||
67 | + | ||
68 | + itr = resourceService.getAllocations(link); | ||
69 | + | ||
70 | + for (LinkResourceAllocations allocation : itr) { | ||
71 | + print("%s", allocation.getResourceAllocation(link)); | ||
72 | + } | ||
73 | + | ||
74 | + } catch (Exception e) { | ||
75 | + print("----- Displaying all resource allocations -----", e.getMessage()); | ||
76 | + itr = resourceService.getAllocations(); | ||
77 | + for (LinkResourceAllocations allocation : itr) { | ||
78 | + print("%s", allocation); | ||
79 | + } | ||
80 | + | ||
81 | + } | ||
82 | + } | ||
83 | +} |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onlab.onos.cli.net; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onlab.onos.cli.AbstractShellCommand; | ||
21 | +import org.onlab.onos.net.ConnectPoint; | ||
22 | +import org.onlab.onos.net.DeviceId; | ||
23 | +import org.onlab.onos.net.Link; | ||
24 | +import org.onlab.onos.net.PortNumber; | ||
25 | +import org.onlab.onos.net.link.LinkService; | ||
26 | +import org.onlab.onos.net.resource.LinkResourceService; | ||
27 | +import org.onlab.onos.net.resource.ResourceRequest; | ||
28 | + | ||
29 | +import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getDeviceId; | ||
30 | +import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getPortNumber; | ||
31 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
32 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
33 | + | ||
34 | +/** | ||
35 | + * Lists allocations by link. | ||
36 | + */ | ||
37 | +@Command(scope = "onos", name = "resource-available", | ||
38 | + description = "Lists available resources by link") | ||
39 | +public class ResourceAvailableCommand extends AbstractShellCommand { | ||
40 | + | ||
41 | + private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s"; | ||
42 | + private static final String COMPACT = "%s/%s-%s/%s"; | ||
43 | + | ||
44 | + @Argument(index = 0, name = "srcString", description = "Link source", | ||
45 | + required = false, multiValued = false) | ||
46 | + String srcString = null; | ||
47 | + @Argument(index = 1, name = "dstString", description = "Link destination", | ||
48 | + required = false, multiValued = false) | ||
49 | + String dstString = null; | ||
50 | + | ||
51 | + @Override | ||
52 | + protected void execute() { | ||
53 | + LinkResourceService resourceService = get(LinkResourceService.class); | ||
54 | + LinkService linkService = get(LinkService.class); | ||
55 | + | ||
56 | + Iterable<ResourceRequest> itr = null; | ||
57 | + try { | ||
58 | + DeviceId ingressDeviceId = deviceId(getDeviceId(srcString)); | ||
59 | + PortNumber ingressPortNumber = portNumber(getPortNumber(srcString)); | ||
60 | + ConnectPoint src = new ConnectPoint(ingressDeviceId, ingressPortNumber); | ||
61 | + | ||
62 | + DeviceId egressDeviceId = deviceId(getDeviceId(dstString)); | ||
63 | + PortNumber egressPortNumber = portNumber(getPortNumber(dstString)); | ||
64 | + ConnectPoint dst = new ConnectPoint(egressDeviceId, egressPortNumber); | ||
65 | + | ||
66 | + Link link = linkService.getLink(src, dst); | ||
67 | + | ||
68 | + itr = resourceService.getAvailableResources(link); | ||
69 | + | ||
70 | + int lambdaCount = 0; | ||
71 | + for (ResourceRequest req : itr) { | ||
72 | + switch (req.type()) { | ||
73 | + case LAMBDA: | ||
74 | + lambdaCount++; | ||
75 | + break; | ||
76 | + case BANDWIDTH: | ||
77 | + print("%s", req); | ||
78 | + break; | ||
79 | + default: | ||
80 | + break; | ||
81 | + } | ||
82 | + } | ||
83 | + if (lambdaCount > 0) { | ||
84 | + print("Number of available lambdas: %d", lambdaCount); | ||
85 | + } | ||
86 | + | ||
87 | + } catch (Exception e) { | ||
88 | + print("Invalid link", e.getMessage()); | ||
89 | + } | ||
90 | + } | ||
91 | +} |
... | @@ -158,7 +158,22 @@ | ... | @@ -158,7 +158,22 @@ |
158 | <null/> | 158 | <null/> |
159 | </completers> | 159 | </completers> |
160 | </command> | 160 | </command> |
161 | - | 161 | + <command> |
162 | + <action class="org.onlab.onos.cli.net.ResourceAllocationsCommand"/> | ||
163 | + <completers> | ||
164 | + <ref component-id="connectPointCompleter"/> | ||
165 | + <ref component-id="connectPointCompleter"/> | ||
166 | + <null/> | ||
167 | + </completers> | ||
168 | + </command> | ||
169 | + <command> | ||
170 | + <action class="org.onlab.onos.cli.net.ResourceAvailableCommand"/> | ||
171 | + <completers> | ||
172 | + <ref component-id="connectPointCompleter"/> | ||
173 | + <ref component-id="connectPointCompleter"/> | ||
174 | + <null/> | ||
175 | + </completers> | ||
176 | + </command> | ||
162 | <command> | 177 | <command> |
163 | <action class="org.onlab.onos.cli.net.ClustersListCommand"/> | 178 | <action class="org.onlab.onos.cli.net.ClustersListCommand"/> |
164 | </command> | 179 | </command> | ... | ... |
... | @@ -40,7 +40,9 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI | ... | @@ -40,7 +40,9 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI |
40 | MASTER_CHANGED, | 40 | MASTER_CHANGED, |
41 | 41 | ||
42 | /** | 42 | /** |
43 | - * Signifies that the list of backup nodes has changed. | 43 | + * Signifies that the list of backup nodes has changed. If |
44 | + * the change in the backups list is accompanied by a change in | ||
45 | + * master, the event is subsumed by MASTER_CHANGED. | ||
44 | */ | 46 | */ |
45 | BACKUPS_CHANGED | 47 | BACKUPS_CHANGED |
46 | } | 48 | } |
... | @@ -49,9 +51,9 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI | ... | @@ -49,9 +51,9 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI |
49 | * Creates an event of a given type and for the specified device, | 51 | * Creates an event of a given type and for the specified device, |
50 | * role information, and the current time. | 52 | * role information, and the current time. |
51 | * | 53 | * |
52 | - * @param type device event type | 54 | + * @param type mastership event type |
53 | * @param device event device subject | 55 | * @param device event device subject |
54 | - * @param info mastership role information subject | 56 | + * @param info mastership role information |
55 | */ | 57 | */ |
56 | public MastershipEvent(Type type, DeviceId device, RoleInfo info) { | 58 | public MastershipEvent(Type type, DeviceId device, RoleInfo info) { |
57 | super(type, device); | 59 | super(type, device); | ... | ... |
... | @@ -16,7 +16,7 @@ | ... | @@ -16,7 +16,7 @@ |
16 | package org.onlab.onos.net; | 16 | package org.onlab.onos.net; |
17 | 17 | ||
18 | /** | 18 | /** |
19 | - * Representation of a network resource. | 19 | + * Representation of a network resource, e.g. a link, lambda, MPLS tag. |
20 | */ | 20 | */ |
21 | public interface NetworkResource { | 21 | public interface NetworkResource { |
22 | } | 22 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onlab.onos.net; | ||
17 | + | ||
18 | +/** | ||
19 | + * Abstraction of a generalized network tunnel. | ||
20 | + */ | ||
21 | +public interface Tunnel extends Link { | ||
22 | + | ||
23 | + /** | ||
24 | + * Tunnel technology type. | ||
25 | + */ | ||
26 | + enum Type { | ||
27 | + MPLS, VLAN, VXLAN, GRE, OPTICAL | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * Network resource backing the tunnel, e.g. lambda, VLAN id, MPLS tag. | ||
32 | + * | ||
33 | + * @return backing resource | ||
34 | + */ | ||
35 | + NetworkResource resource(); | ||
36 | + | ||
37 | +} |
... | @@ -25,6 +25,14 @@ import org.onlab.onos.net.DeviceId; | ... | @@ -25,6 +25,14 @@ import org.onlab.onos.net.DeviceId; |
25 | public interface DeviceClockProviderService { | 25 | public interface DeviceClockProviderService { |
26 | 26 | ||
27 | /** | 27 | /** |
28 | + * Checks if this service can issue Timestamp for specified device. | ||
29 | + * | ||
30 | + * @param deviceId device identifier. | ||
31 | + * @return true if timestamp can be issued for specified device | ||
32 | + */ | ||
33 | + public boolean isTimestampAvailable(DeviceId deviceId); | ||
34 | + | ||
35 | + /** | ||
28 | * Updates the mastership term for the specified deviceId. | 36 | * Updates the mastership term for the specified deviceId. |
29 | * | 37 | * |
30 | * @param deviceId device identifier. | 38 | * @param deviceId device identifier. | ... | ... |
... | @@ -24,7 +24,16 @@ import org.onlab.onos.store.Timestamp; | ... | @@ -24,7 +24,16 @@ import org.onlab.onos.store.Timestamp; |
24 | public interface DeviceClockService { | 24 | public interface DeviceClockService { |
25 | 25 | ||
26 | /** | 26 | /** |
27 | + * Checks if this service can issue Timestamp for specified device. | ||
28 | + * | ||
29 | + * @param deviceId device identifier. | ||
30 | + * @return true if timestamp can be issued for specified device | ||
31 | + */ | ||
32 | + public boolean isTimestampAvailable(DeviceId deviceId); | ||
33 | + | ||
34 | + /** | ||
27 | * Returns a new timestamp for the specified deviceId. | 35 | * Returns a new timestamp for the specified deviceId. |
36 | + * | ||
28 | * @param deviceId device identifier. | 37 | * @param deviceId device identifier. |
29 | * @return timestamp. | 38 | * @return timestamp. |
30 | */ | 39 | */ | ... | ... |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | package org.onlab.onos.net.device; | 16 | package org.onlab.onos.net.device; |
17 | 17 | ||
18 | import org.onlab.onos.net.Device; | 18 | import org.onlab.onos.net.Device; |
19 | +import org.onlab.onos.net.DeviceId; | ||
19 | import org.onlab.onos.net.MastershipRole; | 20 | import org.onlab.onos.net.MastershipRole; |
20 | import org.onlab.onos.net.provider.Provider; | 21 | import org.onlab.onos.net.provider.Provider; |
21 | 22 | ||
... | @@ -42,16 +43,16 @@ public interface DeviceProvider extends Provider { | ... | @@ -42,16 +43,16 @@ public interface DeviceProvider extends Provider { |
42 | * Notifies the provider of a mastership role change for the specified | 43 | * Notifies the provider of a mastership role change for the specified |
43 | * device as decided by the core. | 44 | * device as decided by the core. |
44 | * | 45 | * |
45 | - * @param device affected device | 46 | + * @param deviceId device identifier |
46 | * @param newRole newly determined mastership role | 47 | * @param newRole newly determined mastership role |
47 | */ | 48 | */ |
48 | - void roleChanged(Device device, MastershipRole newRole); | 49 | + void roleChanged(DeviceId deviceId, MastershipRole newRole); |
49 | 50 | ||
50 | /** | 51 | /** |
51 | * Checks the reachability (connectivity) of a device from this provider. | 52 | * Checks the reachability (connectivity) of a device from this provider. |
52 | * | 53 | * |
53 | - * @param device device to check | 54 | + * @param deviceId device identifier |
54 | * @return true if reachable, false otherwise | 55 | * @return true if reachable, false otherwise |
55 | */ | 56 | */ |
56 | - boolean isReachable(Device device); | 57 | + boolean isReachable(DeviceId deviceId); |
57 | } | 58 | } | ... | ... |
... | @@ -61,12 +61,12 @@ public interface DeviceProviderService extends ProviderService<DeviceProvider> { | ... | @@ -61,12 +61,12 @@ public interface DeviceProviderService extends ProviderService<DeviceProvider> { |
61 | void portStatusChanged(DeviceId deviceId, PortDescription portDescription); | 61 | void portStatusChanged(DeviceId deviceId, PortDescription portDescription); |
62 | 62 | ||
63 | /** | 63 | /** |
64 | - * Notifies the core about the providers inability to assert the specified | 64 | + * Notifies the core about the result of a RoleRequest sent to a device. |
65 | - * mastership role on the device. | ||
66 | * | 65 | * |
67 | * @param deviceId identity of the device | 66 | * @param deviceId identity of the device |
68 | - * @param role mastership role that was asserted but failed | 67 | + * @param requested mastership role that was requested by the node |
68 | + * @param replied mastership role the switch accepted | ||
69 | */ | 69 | */ |
70 | - void unableToAssertRole(DeviceId deviceId, MastershipRole role); | 70 | + void receivedRoleReply(DeviceId deviceId, MastershipRole requested, MastershipRole response); |
71 | 71 | ||
72 | } | 72 | } | ... | ... |
... | @@ -27,11 +27,14 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T | ... | @@ -27,11 +27,14 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T |
27 | */ | 27 | */ |
28 | public enum Type { | 28 | public enum Type { |
29 | 29 | ||
30 | + // Request has been forwarded to MASTER Node | ||
30 | /** | 31 | /** |
31 | * Signifies that a batch operation has been initiated. | 32 | * Signifies that a batch operation has been initiated. |
32 | */ | 33 | */ |
33 | BATCH_OPERATION_REQUESTED, | 34 | BATCH_OPERATION_REQUESTED, |
34 | 35 | ||
36 | + // MASTER Node has pushed the batch down to the Device | ||
37 | + // (e.g., Received barrier reply) | ||
35 | /** | 38 | /** |
36 | * Signifies that a batch operation has completed. | 39 | * Signifies that a batch operation has completed. |
37 | */ | 40 | */ | ... | ... |
... | @@ -25,29 +25,29 @@ import com.google.common.collect.Lists; | ... | @@ -25,29 +25,29 @@ import com.google.common.collect.Lists; |
25 | public class FlowRuleBatchRequest { | 25 | public class FlowRuleBatchRequest { |
26 | 26 | ||
27 | private final int batchId; | 27 | private final int batchId; |
28 | - private final List<FlowEntry> toAdd; | 28 | + private final List<FlowRule> toAdd; |
29 | - private final List<FlowEntry> toRemove; | 29 | + private final List<FlowRule> toRemove; |
30 | 30 | ||
31 | - public FlowRuleBatchRequest(int batchId, List<? extends FlowEntry> toAdd, List<? extends FlowEntry> toRemove) { | 31 | + public FlowRuleBatchRequest(int batchId, List<? extends FlowRule> toAdd, List<? extends FlowRule> toRemove) { |
32 | this.batchId = batchId; | 32 | this.batchId = batchId; |
33 | this.toAdd = Collections.unmodifiableList(toAdd); | 33 | this.toAdd = Collections.unmodifiableList(toAdd); |
34 | this.toRemove = Collections.unmodifiableList(toRemove); | 34 | this.toRemove = Collections.unmodifiableList(toRemove); |
35 | } | 35 | } |
36 | 36 | ||
37 | - public List<FlowEntry> toAdd() { | 37 | + public List<FlowRule> toAdd() { |
38 | return toAdd; | 38 | return toAdd; |
39 | } | 39 | } |
40 | 40 | ||
41 | - public List<FlowEntry> toRemove() { | 41 | + public List<FlowRule> toRemove() { |
42 | return toRemove; | 42 | return toRemove; |
43 | } | 43 | } |
44 | 44 | ||
45 | public FlowRuleBatchOperation asBatchOperation() { | 45 | public FlowRuleBatchOperation asBatchOperation() { |
46 | List<FlowRuleBatchEntry> entries = Lists.newArrayList(); | 46 | List<FlowRuleBatchEntry> entries = Lists.newArrayList(); |
47 | - for (FlowEntry e : toAdd) { | 47 | + for (FlowRule e : toAdd) { |
48 | entries.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, e)); | 48 | entries.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, e)); |
49 | } | 49 | } |
50 | - for (FlowEntry e : toRemove) { | 50 | + for (FlowRule e : toRemove) { |
51 | entries.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, e)); | 51 | entries.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, e)); |
52 | } | 52 | } |
53 | return new FlowRuleBatchOperation(entries); | 53 | return new FlowRuleBatchOperation(entries); | ... | ... |
... | @@ -200,7 +200,7 @@ public final class Instructions { | ... | @@ -200,7 +200,7 @@ public final class Instructions { |
200 | } | 200 | } |
201 | if (obj instanceof OutputInstruction) { | 201 | if (obj instanceof OutputInstruction) { |
202 | OutputInstruction that = (OutputInstruction) obj; | 202 | OutputInstruction that = (OutputInstruction) obj; |
203 | - Objects.equals(port, that.port); | 203 | + return Objects.equals(port, that.port); |
204 | 204 | ||
205 | } | 205 | } |
206 | return false; | 206 | return false; | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.resource; | 16 | package org.onlab.onos.net.resource; |
17 | 17 | ||
18 | +import com.google.common.base.MoreObjects; | ||
19 | + | ||
18 | /** | 20 | /** |
19 | * Representation of allocated bandwidth resource. | 21 | * Representation of allocated bandwidth resource. |
20 | */ | 22 | */ |
... | @@ -35,4 +37,11 @@ public class BandwidthResourceAllocation extends BandwidthResourceRequest | ... | @@ -35,4 +37,11 @@ public class BandwidthResourceAllocation extends BandwidthResourceRequest |
35 | public BandwidthResourceAllocation(Bandwidth bandwidth) { | 37 | public BandwidthResourceAllocation(Bandwidth bandwidth) { |
36 | super(bandwidth); | 38 | super(bandwidth); |
37 | } | 39 | } |
40 | + | ||
41 | + @Override | ||
42 | + public String toString() { | ||
43 | + return MoreObjects.toStringHelper(this) | ||
44 | + .add("bandwidth", bandwidth()) | ||
45 | + .toString(); | ||
46 | + } | ||
38 | } | 47 | } | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.resource; | 16 | package org.onlab.onos.net.resource; |
17 | 17 | ||
18 | +import com.google.common.base.MoreObjects; | ||
19 | + | ||
18 | /** | 20 | /** |
19 | * Representation of a request for bandwidth resource. | 21 | * Representation of a request for bandwidth resource. |
20 | */ | 22 | */ |
... | @@ -53,4 +55,11 @@ public class BandwidthResourceRequest implements ResourceRequest { | ... | @@ -53,4 +55,11 @@ public class BandwidthResourceRequest implements ResourceRequest { |
53 | public ResourceType type() { | 55 | public ResourceType type() { |
54 | return ResourceType.BANDWIDTH; | 56 | return ResourceType.BANDWIDTH; |
55 | } | 57 | } |
58 | + | ||
59 | + @Override | ||
60 | + public String toString() { | ||
61 | + return MoreObjects.toStringHelper(this) | ||
62 | + .add("bandwidth", bandwidth) | ||
63 | + .toString(); | ||
64 | + } | ||
56 | } | 65 | } | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.resource; | 16 | package org.onlab.onos.net.resource; |
17 | 17 | ||
18 | +import com.google.common.base.MoreObjects; | ||
19 | + | ||
18 | import java.util.Objects; | 20 | import java.util.Objects; |
19 | 21 | ||
20 | /** | 22 | /** |
... | @@ -64,4 +66,11 @@ public class LambdaResourceAllocation extends LambdaResourceRequest | ... | @@ -64,4 +66,11 @@ public class LambdaResourceAllocation extends LambdaResourceRequest |
64 | final LambdaResourceAllocation other = (LambdaResourceAllocation) obj; | 66 | final LambdaResourceAllocation other = (LambdaResourceAllocation) obj; |
65 | return Objects.equals(this.lambda, other.lambda); | 67 | return Objects.equals(this.lambda, other.lambda); |
66 | } | 68 | } |
69 | + | ||
70 | + @Override | ||
71 | + public String toString() { | ||
72 | + return MoreObjects.toStringHelper(this) | ||
73 | + .add("lambda", lambda) | ||
74 | + .toString(); | ||
75 | + } | ||
67 | } | 76 | } | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.resource; | 16 | package org.onlab.onos.net.resource; |
17 | 17 | ||
18 | +import com.google.common.base.MoreObjects; | ||
19 | + | ||
18 | /** | 20 | /** |
19 | * Representation of a request for lambda resource. | 21 | * Representation of a request for lambda resource. |
20 | */ | 22 | */ |
... | @@ -25,4 +27,9 @@ public class LambdaResourceRequest implements ResourceRequest { | ... | @@ -25,4 +27,9 @@ public class LambdaResourceRequest implements ResourceRequest { |
25 | return ResourceType.LAMBDA; | 27 | return ResourceType.LAMBDA; |
26 | } | 28 | } |
27 | 29 | ||
30 | + @Override | ||
31 | + public String toString() { | ||
32 | + return MoreObjects.toStringHelper(this) | ||
33 | + .toString(); | ||
34 | + } | ||
28 | } | 35 | } | ... | ... |
... | @@ -17,6 +17,7 @@ package org.onlab.onos.net.device.impl; | ... | @@ -17,6 +17,7 @@ package org.onlab.onos.net.device.impl; |
17 | 17 | ||
18 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
19 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED; | 19 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED; |
20 | +import static org.onlab.onos.net.MastershipRole.*; | ||
20 | import static org.slf4j.LoggerFactory.getLogger; | 21 | import static org.slf4j.LoggerFactory.getLogger; |
21 | 22 | ||
22 | import java.util.List; | 23 | import java.util.List; |
... | @@ -29,7 +30,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -29,7 +30,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
29 | import org.apache.felix.scr.annotations.Service; | 30 | import org.apache.felix.scr.annotations.Service; |
30 | import org.onlab.onos.cluster.ClusterService; | 31 | import org.onlab.onos.cluster.ClusterService; |
31 | import org.onlab.onos.cluster.NodeId; | 32 | import org.onlab.onos.cluster.NodeId; |
32 | -import org.onlab.onos.cluster.RoleInfo; | ||
33 | import org.onlab.onos.event.AbstractListenerRegistry; | 33 | import org.onlab.onos.event.AbstractListenerRegistry; |
34 | import org.onlab.onos.event.EventDeliveryService; | 34 | import org.onlab.onos.event.EventDeliveryService; |
35 | import org.onlab.onos.mastership.MastershipEvent; | 35 | import org.onlab.onos.mastership.MastershipEvent; |
... | @@ -59,8 +59,6 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; | ... | @@ -59,8 +59,6 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; |
59 | import org.onlab.onos.net.provider.AbstractProviderService; | 59 | import org.onlab.onos.net.provider.AbstractProviderService; |
60 | import org.slf4j.Logger; | 60 | import org.slf4j.Logger; |
61 | 61 | ||
62 | -import com.google.common.collect.HashMultimap; | ||
63 | - | ||
64 | /** | 62 | /** |
65 | * Provides implementation of the device SB & NB APIs. | 63 | * Provides implementation of the device SB & NB APIs. |
66 | */ | 64 | */ |
... | @@ -160,39 +158,15 @@ public class DeviceManager | ... | @@ -160,39 +158,15 @@ public class DeviceManager |
160 | return store.isAvailable(deviceId); | 158 | return store.isAvailable(deviceId); |
161 | } | 159 | } |
162 | 160 | ||
163 | - // Applies the specified role to the device; ignores NONE | ||
164 | - private void applyRole(DeviceId deviceId, MastershipRole newRole) { | ||
165 | - if (newRole.equals(MastershipRole.NONE)) { | ||
166 | - return; | ||
167 | - } | ||
168 | - | ||
169 | - Device device = store.getDevice(deviceId); | ||
170 | - // FIXME: Device might not be there yet. (eventual consistent) | ||
171 | - if (device == null) { | ||
172 | - return; | ||
173 | - } | ||
174 | - | ||
175 | - DeviceProvider provider = getProvider(device.providerId()); | ||
176 | - if (provider != null) { | ||
177 | - provider.roleChanged(device, newRole); | ||
178 | - // only trigger event when request was sent to provider | ||
179 | - // TODO: consider removing this from Device event type? | ||
180 | - post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device)); | ||
181 | - | ||
182 | - if (newRole.equals(MastershipRole.MASTER)) { | ||
183 | - provider.triggerProbe(device); | ||
184 | - } | ||
185 | - } | ||
186 | - } | ||
187 | - | ||
188 | // Check a device for control channel connectivity. | 161 | // Check a device for control channel connectivity. |
189 | - private boolean isReachable(Device device) { | 162 | + private boolean isReachable(DeviceId deviceId) { |
190 | - // FIXME: Device might not be there yet. (eventual consistent) | 163 | + DeviceProvider provider = getProvider(deviceId); |
191 | - if (device == null) { | 164 | + if (provider != null) { |
165 | + return provider.isReachable(deviceId); | ||
166 | + } else { | ||
167 | + log.error("Provider not found for {}", deviceId); | ||
192 | return false; | 168 | return false; |
193 | } | 169 | } |
194 | - DeviceProvider provider = getProvider(device.providerId()); | ||
195 | - return provider.isReachable(device); | ||
196 | } | 170 | } |
197 | 171 | ||
198 | @Override | 172 | @Override |
... | @@ -234,6 +208,32 @@ public class DeviceManager | ... | @@ -234,6 +208,32 @@ public class DeviceManager |
234 | super(provider); | 208 | super(provider); |
235 | } | 209 | } |
236 | 210 | ||
211 | + /** | ||
212 | + * Apply role in reaction to provider event. | ||
213 | + * | ||
214 | + * @param deviceId device identifier | ||
215 | + * @param newRole new role to apply to the device | ||
216 | + * @return true if the request was sent to provider | ||
217 | + */ | ||
218 | + private boolean applyRole(DeviceId deviceId, MastershipRole newRole) { | ||
219 | + | ||
220 | + if (newRole.equals(MastershipRole.NONE)) { | ||
221 | + //no-op | ||
222 | + return true; | ||
223 | + } | ||
224 | + | ||
225 | + DeviceProvider provider = provider(); | ||
226 | + if (provider == null) { | ||
227 | + log.warn("Provider for {} was not found. Cannot apply role {}", deviceId, newRole); | ||
228 | + return false; | ||
229 | + } | ||
230 | + provider.roleChanged(deviceId, newRole); | ||
231 | + // not triggering probe when triggered by provider service event | ||
232 | + | ||
233 | + return true; | ||
234 | + } | ||
235 | + | ||
236 | + | ||
237 | @Override | 237 | @Override |
238 | public void deviceConnected(DeviceId deviceId, | 238 | public void deviceConnected(DeviceId deviceId, |
239 | DeviceDescription deviceDescription) { | 239 | DeviceDescription deviceDescription) { |
... | @@ -242,26 +242,19 @@ public class DeviceManager | ... | @@ -242,26 +242,19 @@ public class DeviceManager |
242 | checkValidity(); | 242 | checkValidity(); |
243 | 243 | ||
244 | log.info("Device {} connected", deviceId); | 244 | log.info("Device {} connected", deviceId); |
245 | - // check my Role | ||
246 | - MastershipRole role = mastershipService.requestRoleFor(deviceId); | ||
247 | - if (role != MastershipRole.MASTER) { | ||
248 | - // TODO: Do we need to explicitly tell the Provider that | ||
249 | - // this instance is no longer the MASTER? probably not | ||
250 | -// Device device = getDevice(deviceId); | ||
251 | -// if (device != null) { | ||
252 | -// // FIXME roleChanged should take DeviceId instead of Device | ||
253 | -// provider().roleChanged(device, role); | ||
254 | -// } | ||
255 | - return; | ||
256 | - } | ||
257 | - MastershipTerm term = termService.getMastershipTerm(deviceId); | ||
258 | - | ||
259 | final NodeId myNodeId = clusterService.getLocalNode().id(); | 245 | final NodeId myNodeId = clusterService.getLocalNode().id(); |
246 | + | ||
247 | + // check my Role | ||
248 | + mastershipService.requestRoleFor(deviceId); | ||
249 | + final MastershipTerm term = termService.getMastershipTerm(deviceId); | ||
260 | if (!myNodeId.equals(term.master())) { | 250 | if (!myNodeId.equals(term.master())) { |
261 | - // lost mastership after requestRole told this instance was MASTER. | 251 | + log.info("Role of this node is STANDBY for {}", deviceId); |
262 | - log.info("lost mastership before getting term info."); | 252 | + // TODO: Do we need to explicitly tell the Provider that |
253 | + // this instance is not the MASTER | ||
254 | + applyRole(deviceId, MastershipRole.STANDBY); | ||
263 | return; | 255 | return; |
264 | } | 256 | } |
257 | + log.info("Role of this node is MASTER for {}", deviceId); | ||
265 | 258 | ||
266 | // tell clock provider if this instance is the master | 259 | // tell clock provider if this instance is the master |
267 | deviceClockProviderService.setMastershipTerm(deviceId, term); | 260 | deviceClockProviderService.setMastershipTerm(deviceId, term); |
... | @@ -269,24 +262,15 @@ public class DeviceManager | ... | @@ -269,24 +262,15 @@ public class DeviceManager |
269 | DeviceEvent event = store.createOrUpdateDevice(provider().id(), | 262 | DeviceEvent event = store.createOrUpdateDevice(provider().id(), |
270 | deviceId, deviceDescription); | 263 | deviceId, deviceDescription); |
271 | 264 | ||
265 | + applyRole(deviceId, MastershipRole.MASTER); | ||
266 | + | ||
272 | // If there was a change of any kind, tell the provider | 267 | // If there was a change of any kind, tell the provider |
273 | // that this instance is the master. | 268 | // that this instance is the master. |
274 | - // Note: event can be null, if mastership was lost between | ||
275 | - // roleRequest and store update calls. | ||
276 | if (event != null) { | 269 | if (event != null) { |
277 | - // TODO: Check switch reconnected case. Is it assured that | 270 | + log.trace("event: {} {}", event.type(), event); |
278 | - // event will never be null? | ||
279 | - // Could there be a situation MastershipService told this | ||
280 | - // instance is the new Master, but | ||
281 | - // event returned from the store is null? | ||
282 | - | ||
283 | - // FIXME: 1st argument should be deviceId, to allow setting | ||
284 | - // certain roles even if the store returned null. | ||
285 | - log.info("event: {} {}", event.type(), event); | ||
286 | - provider().roleChanged(event.subject(), role); | ||
287 | post(event); | 271 | post(event); |
288 | } else { | 272 | } else { |
289 | - log.info("No event to publish"); | 273 | + post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, store.getDevice(deviceId))); |
290 | } | 274 | } |
291 | } | 275 | } |
292 | 276 | ||
... | @@ -295,6 +279,7 @@ public class DeviceManager | ... | @@ -295,6 +279,7 @@ public class DeviceManager |
295 | checkNotNull(deviceId, DEVICE_ID_NULL); | 279 | checkNotNull(deviceId, DEVICE_ID_NULL); |
296 | checkValidity(); | 280 | checkValidity(); |
297 | 281 | ||
282 | + log.info("Device {} disconnected from this node", deviceId); | ||
298 | 283 | ||
299 | DeviceEvent event = null; | 284 | DeviceEvent event = null; |
300 | try { | 285 | try { |
... | @@ -318,18 +303,18 @@ public class DeviceManager | ... | @@ -318,18 +303,18 @@ public class DeviceManager |
318 | final NodeId myNodeId = clusterService.getLocalNode().id(); | 303 | final NodeId myNodeId = clusterService.getLocalNode().id(); |
319 | // TODO: Move this type of check inside device clock manager, etc. | 304 | // TODO: Move this type of check inside device clock manager, etc. |
320 | if (myNodeId.equals(term.master())) { | 305 | if (myNodeId.equals(term.master())) { |
321 | - log.info("Marking {} offline", deviceId); | 306 | + log.info("Retry marking {} offline", deviceId); |
322 | deviceClockProviderService.setMastershipTerm(deviceId, term); | 307 | deviceClockProviderService.setMastershipTerm(deviceId, term); |
323 | event = store.markOffline(deviceId); | 308 | event = store.markOffline(deviceId); |
324 | } else { | 309 | } else { |
325 | - log.error("Failed again marking {} offline. {}", deviceId, role); | 310 | + log.info("Failed again marking {} offline. {}", deviceId, role); |
326 | } | 311 | } |
327 | } finally { | 312 | } finally { |
328 | //relinquish master role and ability to be backup. | 313 | //relinquish master role and ability to be backup. |
329 | mastershipService.relinquishMastership(deviceId); | 314 | mastershipService.relinquishMastership(deviceId); |
330 | 315 | ||
331 | if (event != null) { | 316 | if (event != null) { |
332 | - log.info("Device {} disconnected", deviceId); | 317 | + log.info("Device {} disconnected from cluster", deviceId); |
333 | post(event); | 318 | post(event); |
334 | } | 319 | } |
335 | } | 320 | } |
... | @@ -343,6 +328,13 @@ public class DeviceManager | ... | @@ -343,6 +328,13 @@ public class DeviceManager |
343 | "Port descriptions list cannot be null"); | 328 | "Port descriptions list cannot be null"); |
344 | checkValidity(); | 329 | checkValidity(); |
345 | 330 | ||
331 | + if (!deviceClockProviderService.isTimestampAvailable(deviceId)) { | ||
332 | + // Never been a master for this device | ||
333 | + // any update will be ignored. | ||
334 | + log.trace("Ignoring {} port updates on standby node. {}", deviceId, portDescriptions); | ||
335 | + return; | ||
336 | + } | ||
337 | + | ||
346 | List<DeviceEvent> events = store.updatePorts(this.provider().id(), | 338 | List<DeviceEvent> events = store.updatePorts(this.provider().id(), |
347 | deviceId, portDescriptions); | 339 | deviceId, portDescriptions); |
348 | for (DeviceEvent event : events) { | 340 | for (DeviceEvent event : events) { |
... | @@ -357,6 +349,13 @@ public class DeviceManager | ... | @@ -357,6 +349,13 @@ public class DeviceManager |
357 | checkNotNull(portDescription, PORT_DESCRIPTION_NULL); | 349 | checkNotNull(portDescription, PORT_DESCRIPTION_NULL); |
358 | checkValidity(); | 350 | checkValidity(); |
359 | 351 | ||
352 | + if (!deviceClockProviderService.isTimestampAvailable(deviceId)) { | ||
353 | + // Never been a master for this device | ||
354 | + // any update will be ignored. | ||
355 | + log.trace("Ignoring {} port update on standby node. {}", deviceId, portDescription); | ||
356 | + return; | ||
357 | + } | ||
358 | + | ||
360 | final DeviceEvent event = store.updatePortStatus(this.provider().id(), | 359 | final DeviceEvent event = store.updatePortStatus(this.provider().id(), |
361 | deviceId, portDescription); | 360 | deviceId, portDescription); |
362 | if (event != null) { | 361 | if (event != null) { |
... | @@ -367,17 +366,49 @@ public class DeviceManager | ... | @@ -367,17 +366,49 @@ public class DeviceManager |
367 | } | 366 | } |
368 | 367 | ||
369 | @Override | 368 | @Override |
370 | - public void unableToAssertRole(DeviceId deviceId, MastershipRole role) { | 369 | + public void receivedRoleReply( |
370 | + DeviceId deviceId, MastershipRole requested, MastershipRole response) { | ||
371 | + // Several things can happen here: | ||
372 | + // 1. request and response match | ||
373 | + // 2. request and response don't match | ||
374 | + // 3. MastershipRole and requested match (and 1 or 2 are true) | ||
375 | + // 4. MastershipRole and requested don't match (and 1 or 2 are true) | ||
376 | + // | ||
377 | + // 2, 4, and 3 with case 2 are failure modes. | ||
378 | + | ||
371 | // FIXME: implement response to this notification | 379 | // FIXME: implement response to this notification |
372 | - log.warn("Failed to assert role [{}] onto Device {}", role, | 380 | + |
373 | - deviceId); | 381 | + log.info("got reply to a role request for {}: asked for {}, and got {}", |
374 | - if (role == MastershipRole.MASTER) { | 382 | + deviceId, requested, response); |
383 | + | ||
384 | + if (requested == null && response == null) { | ||
385 | + // something was off with DeviceProvider, maybe check channel too? | ||
386 | + log.warn("Failed to assert role [{}] onto Device {}", requested, deviceId); | ||
387 | + mastershipService.relinquishMastership(deviceId); | ||
388 | + return; | ||
389 | + } | ||
390 | + | ||
391 | + if (requested.equals(response)) { | ||
392 | + if (requested.equals(mastershipService.getLocalRole(deviceId))) { | ||
393 | + | ||
394 | + return; | ||
395 | + } else { | ||
396 | + return; | ||
397 | + // FIXME roleManager got the device to comply, but doesn't agree with | ||
398 | + // the store; use the store's view, then try to reassert. | ||
399 | + } | ||
400 | + } else { | ||
401 | + // we didn't get back what we asked for. Reelect someone else. | ||
402 | + log.warn("Failed to assert role [{}] onto Device {}", response, deviceId); | ||
403 | + if (response == MastershipRole.MASTER) { | ||
375 | mastershipService.relinquishMastership(deviceId); | 404 | mastershipService.relinquishMastership(deviceId); |
376 | // TODO: Shouldn't we be triggering event? | 405 | // TODO: Shouldn't we be triggering event? |
377 | //final Device device = getDevice(deviceId); | 406 | //final Device device = getDevice(deviceId); |
378 | //post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device)); | 407 | //post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device)); |
379 | } | 408 | } |
380 | } | 409 | } |
410 | + | ||
411 | + } | ||
381 | } | 412 | } |
382 | 413 | ||
383 | // Posts the specified event to the local event dispatcher. | 414 | // Posts the specified event to the local event dispatcher. |
... | @@ -390,118 +421,134 @@ public class DeviceManager | ... | @@ -390,118 +421,134 @@ public class DeviceManager |
390 | // Intercepts mastership events | 421 | // Intercepts mastership events |
391 | private class InternalMastershipListener implements MastershipListener { | 422 | private class InternalMastershipListener implements MastershipListener { |
392 | 423 | ||
393 | - // random cache size | 424 | + // Applies the specified role to the device; ignores NONE |
394 | - private final int cacheSize = 5; | 425 | + /** |
395 | - // temporarily stores term number + events to check for duplicates. A hack. | 426 | + * Apply role in reaction to mastership event. |
396 | - private HashMultimap<Integer, RoleInfo> eventCache = | 427 | + * |
397 | - HashMultimap.create(); | 428 | + * @param deviceId device identifier |
429 | + * @param newRole new role to apply to the device | ||
430 | + * @return true if the request was sent to provider | ||
431 | + */ | ||
432 | + private boolean applyRole(DeviceId deviceId, MastershipRole newRole) { | ||
433 | + if (newRole.equals(MastershipRole.NONE)) { | ||
434 | + //no-op | ||
435 | + return true; | ||
436 | + } | ||
398 | 437 | ||
399 | - @Override | 438 | + Device device = store.getDevice(deviceId); |
400 | - public void event(MastershipEvent event) { | 439 | + // FIXME: Device might not be there yet. (eventual consistent) |
401 | - final DeviceId did = event.subject(); | 440 | + // FIXME relinquish role |
402 | - final NodeId myNodeId = clusterService.getLocalNode().id(); | 441 | + if (device == null) { |
442 | + log.warn("{} was not there. Cannot apply role {}", deviceId, newRole); | ||
443 | + return false; | ||
444 | + } | ||
403 | 445 | ||
404 | - if (myNodeId.equals(event.roleInfo().master())) { | 446 | + DeviceProvider provider = getProvider(device.providerId()); |
405 | - MastershipTerm term = termService.getMastershipTerm(did); | 447 | + if (provider == null) { |
448 | + log.warn("Provider for {} was not found. Cannot apply role {}", deviceId, newRole); | ||
449 | + return false; | ||
450 | + } | ||
451 | + provider.roleChanged(deviceId, newRole); | ||
406 | 452 | ||
407 | - // TODO duplicate suppression should probably occur in the MastershipManager | 453 | + if (newRole.equals(MastershipRole.MASTER)) { |
408 | - // itself, so listeners that can't deal with duplicates don't have to | 454 | + // only trigger event when request was sent to provider |
409 | - // so this check themselves. | 455 | + // TODO: consider removing this from Device event type? |
410 | -// if (checkDuplicate(event.roleInfo(), term.termNumber())) { | 456 | + post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device)); |
411 | -// return; | ||
412 | -// } | ||
413 | 457 | ||
414 | - if (!myNodeId.equals(term.master())) { | 458 | + provider.triggerProbe(device); |
415 | - // something went wrong in consistency, let go | 459 | + } |
416 | - log.warn("Mastership has changed after this event." | 460 | + return true; |
417 | - + "Term Service suggests {} for {}", term, did); | ||
418 | - // FIXME: Is it possible to let go of MASTER role | ||
419 | - // but remain on STANDBY list? | ||
420 | - mastershipService.relinquishMastership(did); | ||
421 | - applyRole(did, MastershipRole.STANDBY); | ||
422 | - return; | ||
423 | } | 461 | } |
424 | 462 | ||
425 | - // only set the new term if I am the master | 463 | + @Override |
426 | - deviceClockProviderService.setMastershipTerm(did, term); | 464 | + public void event(MastershipEvent event) { |
427 | 465 | ||
428 | - // if the device is null here, we are the first master to claim the | 466 | + if (event.type() != MastershipEvent.Type.MASTER_CHANGED) { |
429 | - // device. No worries, the DeviceManager will create one soon. | 467 | + // Don't care if backup list changed. |
430 | - Device device = getDevice(did); | ||
431 | - if ((device != null) && !isAvailable(did)) { | ||
432 | - if (!isReachable(device)) { | ||
433 | - log.warn("Device {} has disconnected after this event", did); | ||
434 | - mastershipService.relinquishMastership(did); | ||
435 | return; | 468 | return; |
436 | } | 469 | } |
437 | - //flag the device as online. Is there a better way to do this? | 470 | + |
438 | - DeviceEvent devEvent = | 471 | + final DeviceId did = event.subject(); |
439 | - store.createOrUpdateDevice(device.providerId(), did, | 472 | + final NodeId myNodeId = clusterService.getLocalNode().id(); |
440 | - new DefaultDeviceDescription( | 473 | + |
441 | - did.uri(), device.type(), device.manufacturer(), | 474 | + // myRole suggested by MastershipService |
442 | - device.hwVersion(), device.swVersion(), | 475 | + MastershipRole myNextRole; |
443 | - device.serialNumber(), device.chassisId())); | 476 | + if (myNodeId.equals(event.roleInfo().master())) { |
444 | - post(devEvent); | 477 | + // confirm latest info |
478 | + MastershipTerm term = termService.getMastershipTerm(did); | ||
479 | + final boolean iHaveControl = myNodeId.equals(term.master()); | ||
480 | + if (iHaveControl) { | ||
481 | + deviceClockProviderService.setMastershipTerm(did, term); | ||
482 | + myNextRole = MASTER; | ||
483 | + } else { | ||
484 | + myNextRole = STANDBY; | ||
445 | } | 485 | } |
446 | - applyRole(did, MastershipRole.MASTER); | ||
447 | } else if (event.roleInfo().backups().contains(myNodeId)) { | 486 | } else if (event.roleInfo().backups().contains(myNodeId)) { |
448 | - if (!isReachable(getDevice(did))) { | 487 | + myNextRole = STANDBY; |
449 | - log.warn("Device {} has disconnected after this event", did); | 488 | + } else { |
489 | + myNextRole = NONE; | ||
490 | + } | ||
491 | + | ||
492 | + | ||
493 | + final boolean isReachable = isReachable(did); | ||
494 | + if (!isReachable) { | ||
495 | + // device is not connected to this node | ||
496 | + if (myNextRole != NONE) { | ||
497 | + log.warn("Node was instructed to be {} role for {}, " | ||
498 | + + "but this node cannot reach the device. " | ||
499 | + + "Relinquishing role. ", | ||
500 | + myNextRole, did); | ||
450 | mastershipService.relinquishMastership(did); | 501 | mastershipService.relinquishMastership(did); |
451 | - return; | 502 | + // FIXME disconnect? |
452 | } | 503 | } |
453 | - applyRole(did, MastershipRole.STANDBY); | ||
454 | - } else { | ||
455 | - // Event suggests that this Node has no connection to this Device | ||
456 | - // confirm. | ||
457 | - final Device device = getDevice(did); | ||
458 | - if (!isReachable(device)) { | ||
459 | - // not connection to device, as expected | ||
460 | return; | 504 | return; |
461 | } | 505 | } |
462 | - // connection seems to exist | 506 | + |
463 | - log.info("Detected mastership info mismatch, requesting Role"); | 507 | + // device is connected to this node: |
508 | + | ||
509 | + if (myNextRole == NONE) { | ||
464 | mastershipService.requestRoleFor(did); | 510 | mastershipService.requestRoleFor(did); |
465 | - final MastershipTerm term = termService.getMastershipTerm(did); | 511 | + MastershipTerm term = termService.getMastershipTerm(did); |
466 | if (myNodeId.equals(term.master())) { | 512 | if (myNodeId.equals(term.master())) { |
467 | - // became MASTER | 513 | + myNextRole = MASTER; |
468 | - // TODO: consider slicing out method for applying MASTER role | 514 | + } else { |
469 | - deviceClockProviderService.setMastershipTerm(did, term); | 515 | + myNextRole = STANDBY; |
516 | + } | ||
517 | + } | ||
470 | 518 | ||
519 | + switch (myNextRole) { | ||
520 | + case MASTER: | ||
521 | + final Device device = getDevice(did); | ||
522 | + if ((device != null) && !isAvailable(did)) { | ||
471 | //flag the device as online. Is there a better way to do this? | 523 | //flag the device as online. Is there a better way to do this? |
524 | + DefaultDeviceDescription deviceDescription | ||
525 | + = new DefaultDeviceDescription(did.uri(), | ||
526 | + device.type(), | ||
527 | + device.manufacturer(), | ||
528 | + device.hwVersion(), | ||
529 | + device.swVersion(), | ||
530 | + device.serialNumber(), | ||
531 | + device.chassisId()); | ||
472 | DeviceEvent devEvent = | 532 | DeviceEvent devEvent = |
473 | store.createOrUpdateDevice(device.providerId(), did, | 533 | store.createOrUpdateDevice(device.providerId(), did, |
474 | - new DefaultDeviceDescription( | 534 | + deviceDescription); |
475 | - did.uri(), device.type(), device.manufacturer(), | ||
476 | - device.hwVersion(), device.swVersion(), | ||
477 | - device.serialNumber(), device.chassisId())); | ||
478 | - applyRole(did, MastershipRole.MASTER); | ||
479 | post(devEvent); | 535 | post(devEvent); |
480 | - } else { | ||
481 | - applyRole(did, MastershipRole.STANDBY); | ||
482 | } | 536 | } |
537 | + // TODO: should apply role only if there is mismatch | ||
538 | + log.info("Applying role {} to {}", myNextRole, did); | ||
539 | + applyRole(did, MASTER); | ||
540 | + break; | ||
541 | + case STANDBY: | ||
542 | + log.info("Applying role {} to {}", myNextRole, did); | ||
543 | + applyRole(did, STANDBY); | ||
544 | + break; | ||
545 | + case NONE: | ||
546 | + default: | ||
547 | + // should never reach here | ||
548 | + log.error("You didn't see anything. I did not exist."); | ||
549 | + break; | ||
483 | } | 550 | } |
484 | } | 551 | } |
485 | - | ||
486 | - // checks for duplicate event, returning true if one is found. | ||
487 | - private boolean checkDuplicate(RoleInfo roleInfo, int term) { | ||
488 | - // turning off duplicate check | ||
489 | - return false; | ||
490 | -// synchronized (eventCache) { | ||
491 | -// if (eventCache.get(term).contains(roleInfo)) { | ||
492 | -// log.info("duplicate event detected; ignoring"); | ||
493 | -// return true; | ||
494 | -// } else { | ||
495 | -// eventCache.put(term, roleInfo); | ||
496 | -// // purge by-term oldest entries to keep the cache size under limit | ||
497 | -// if (eventCache.size() > cacheSize) { | ||
498 | -// eventCache.removeAll(term - cacheSize); | ||
499 | -// } | ||
500 | -// return false; | ||
501 | -// } | ||
502 | -// } | ||
503 | - } | ||
504 | - | ||
505 | } | 552 | } |
506 | 553 | ||
507 | // Store delegate to re-post events emitted from the store. | 554 | // Store delegate to re-post events emitted from the store. | ... | ... |
... | @@ -371,10 +371,11 @@ public class FlowRuleManager | ... | @@ -371,10 +371,11 @@ public class FlowRuleManager |
371 | final FlowRuleBatchRequest request = event.subject(); | 371 | final FlowRuleBatchRequest request = event.subject(); |
372 | switch (event.type()) { | 372 | switch (event.type()) { |
373 | case BATCH_OPERATION_REQUESTED: | 373 | case BATCH_OPERATION_REQUESTED: |
374 | - for (FlowEntry entry : request.toAdd()) { | 374 | + // Request has been forwarded to MASTER Node, and was |
375 | + for (FlowRule entry : request.toAdd()) { | ||
375 | eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED, entry)); | 376 | eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED, entry)); |
376 | } | 377 | } |
377 | - for (FlowEntry entry : request.toRemove()) { | 378 | + for (FlowRule entry : request.toRemove()) { |
378 | eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVE_REQUESTED, entry)); | 379 | eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVE_REQUESTED, entry)); |
379 | } | 380 | } |
380 | // FIXME: what about op.equals(FlowRuleOperation.MODIFY) ? | 381 | // FIXME: what about op.equals(FlowRuleOperation.MODIFY) ? |
... | @@ -392,21 +393,15 @@ public class FlowRuleManager | ... | @@ -392,21 +393,15 @@ public class FlowRuleManager |
392 | Futures.getUnchecked(result))); | 393 | Futures.getUnchecked(result))); |
393 | } | 394 | } |
394 | }, futureListeners); | 395 | }, futureListeners); |
395 | - | ||
396 | break; | 396 | break; |
397 | + | ||
397 | case BATCH_OPERATION_COMPLETED: | 398 | case BATCH_OPERATION_COMPLETED: |
398 | - Set<FlowRule> failedItems = event.result().failedItems(); | 399 | + // MASTER Node has pushed the batch down to the Device |
399 | - for (FlowEntry entry : request.toAdd()) { | 400 | + |
400 | - if (!failedItems.contains(entry)) { | 401 | + // Note: RULE_ADDED will be posted |
401 | - eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED, entry)); | 402 | + // when Flow was actually confirmed by stats reply. |
402 | - } | ||
403 | - } | ||
404 | - for (FlowEntry entry : request.toRemove()) { | ||
405 | - if (!failedItems.contains(entry)) { | ||
406 | - eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVED, entry)); | ||
407 | - } | ||
408 | - } | ||
409 | break; | 403 | break; |
404 | + | ||
410 | default: | 405 | default: |
411 | break; | 406 | break; |
412 | } | 407 | } | ... | ... |
... | @@ -67,6 +67,7 @@ public class HostMonitor implements TimerTask { | ... | @@ -67,6 +67,7 @@ public class HostMonitor implements TimerTask { |
67 | private final ConcurrentMap<ProviderId, HostProvider> hostProviders; | 67 | private final ConcurrentMap<ProviderId, HostProvider> hostProviders; |
68 | 68 | ||
69 | private static final long DEFAULT_PROBE_RATE = 30000; // milliseconds | 69 | private static final long DEFAULT_PROBE_RATE = 30000; // milliseconds |
70 | + private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes(); | ||
70 | private long probeRate = DEFAULT_PROBE_RATE; | 71 | private long probeRate = DEFAULT_PROBE_RATE; |
71 | 72 | ||
72 | private Timeout timeout; | 73 | private Timeout timeout; |
... | @@ -215,15 +216,15 @@ public class HostMonitor implements TimerTask { | ... | @@ -215,15 +216,15 @@ public class HostMonitor implements TimerTask { |
215 | .setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH) | 216 | .setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH) |
216 | .setOpCode(ARP.OP_REQUEST); | 217 | .setOpCode(ARP.OP_REQUEST); |
217 | 218 | ||
218 | - arp.setSenderHardwareAddress(sourceMac.getAddress()) | 219 | + arp.setSenderHardwareAddress(sourceMac.toBytes()) |
219 | .setSenderProtocolAddress(sourceIp.toOctets()) | 220 | .setSenderProtocolAddress(sourceIp.toOctets()) |
220 | - .setTargetHardwareAddress(MacAddress.ZERO_MAC_ADDRESS) | 221 | + .setTargetHardwareAddress(ZERO_MAC_ADDRESS) |
221 | .setTargetProtocolAddress(targetIp.toOctets()); | 222 | .setTargetProtocolAddress(targetIp.toOctets()); |
222 | 223 | ||
223 | Ethernet ethernet = new Ethernet(); | 224 | Ethernet ethernet = new Ethernet(); |
224 | ethernet.setEtherType(Ethernet.TYPE_ARP) | 225 | ethernet.setEtherType(Ethernet.TYPE_ARP) |
225 | - .setDestinationMACAddress(MacAddress.BROADCAST_MAC) | 226 | + .setDestinationMACAddress(MacAddress.BROADCAST) |
226 | - .setSourceMACAddress(sourceMac.getAddress()) | 227 | + .setSourceMACAddress(sourceMac) |
227 | .setPayload(arp); | 228 | .setPayload(arp); |
228 | 229 | ||
229 | return ethernet; | 230 | return ethernet; | ... | ... |
... | @@ -132,7 +132,8 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -132,7 +132,8 @@ public class ProxyArpManager implements ProxyArpService { |
132 | // for one of our external addresses. | 132 | // for one of our external addresses. |
133 | if (isOutsidePort(inPort)) { | 133 | if (isOutsidePort(inPort)) { |
134 | IpAddress target = | 134 | IpAddress target = |
135 | - IpAddress.valueOf(arp.getTargetProtocolAddress()); | 135 | + IpAddress.valueOf(IpAddress.Version.INET, |
136 | + arp.getTargetProtocolAddress()); | ||
136 | PortAddresses addresses = | 137 | PortAddresses addresses = |
137 | hostService.getAddressBindingsForPort(inPort); | 138 | hostService.getAddressBindingsForPort(inPort); |
138 | 139 | ||
... | @@ -149,7 +150,8 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -149,7 +150,8 @@ public class ProxyArpManager implements ProxyArpService { |
149 | // it could be a request from an internal host to an external | 150 | // it could be a request from an internal host to an external |
150 | // address. Forward it over to the correct port. | 151 | // address. Forward it over to the correct port. |
151 | IpAddress source = | 152 | IpAddress source = |
152 | - IpAddress.valueOf(arp.getSenderProtocolAddress()); | 153 | + IpAddress.valueOf(IpAddress.Version.INET, |
154 | + arp.getSenderProtocolAddress()); | ||
153 | PortAddresses sourceAddresses = findPortInSubnet(source); | 155 | PortAddresses sourceAddresses = findPortInSubnet(source); |
154 | if (sourceAddresses != null) { | 156 | if (sourceAddresses != null) { |
155 | for (InterfaceIpAddress ia : sourceAddresses.ipAddresses()) { | 157 | for (InterfaceIpAddress ia : sourceAddresses.ipAddresses()) { |
... | @@ -164,8 +166,9 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -164,8 +166,9 @@ public class ProxyArpManager implements ProxyArpService { |
164 | // Continue with normal proxy ARP case | 166 | // Continue with normal proxy ARP case |
165 | 167 | ||
166 | VlanId vlan = VlanId.vlanId(eth.getVlanID()); | 168 | VlanId vlan = VlanId.vlanId(eth.getVlanID()); |
167 | - Set<Host> hosts = hostService.getHostsByIp(IpAddress.valueOf(arp | 169 | + Set<Host> hosts = |
168 | - .getTargetProtocolAddress())); | 170 | + hostService.getHostsByIp(IpAddress.valueOf(IpAddress.Version.INET, |
171 | + arp.getTargetProtocolAddress())); | ||
169 | 172 | ||
170 | Host dst = null; | 173 | Host dst = null; |
171 | Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(), | 174 | Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(), |
... | @@ -357,8 +360,8 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -357,8 +360,8 @@ public class ProxyArpManager implements ProxyArpService { |
357 | Ethernet request) { | 360 | Ethernet request) { |
358 | 361 | ||
359 | Ethernet eth = new Ethernet(); | 362 | Ethernet eth = new Ethernet(); |
360 | - eth.setDestinationMACAddress(request.getSourceMACAddress()); | 363 | + eth.setDestinationMACAddress(request.getSourceMAC()); |
361 | - eth.setSourceMACAddress(srcMac.getAddress()); | 364 | + eth.setSourceMACAddress(srcMac); |
362 | eth.setEtherType(Ethernet.TYPE_ARP); | 365 | eth.setEtherType(Ethernet.TYPE_ARP); |
363 | eth.setVlanID(request.getVlanID()); | 366 | eth.setVlanID(request.getVlanID()); |
364 | 367 | ||
... | @@ -369,7 +372,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -369,7 +372,7 @@ public class ProxyArpManager implements ProxyArpService { |
369 | 372 | ||
370 | arp.setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH); | 373 | arp.setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH); |
371 | arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH); | 374 | arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH); |
372 | - arp.setSenderHardwareAddress(srcMac.getAddress()); | 375 | + arp.setSenderHardwareAddress(srcMac.toBytes()); |
373 | arp.setTargetHardwareAddress(request.getSourceMACAddress()); | 376 | arp.setTargetHardwareAddress(request.getSourceMACAddress()); |
374 | 377 | ||
375 | arp.setTargetProtocolAddress(((ARP) request.getPayload()) | 378 | arp.setTargetProtocolAddress(((ARP) request.getPayload()) | ... | ... |
... | @@ -15,11 +15,7 @@ | ... | @@ -15,11 +15,7 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.resource.impl; | 16 | package org.onlab.onos.net.resource.impl; |
17 | 17 | ||
18 | -import java.util.Collection; | 18 | +import com.google.common.base.MoreObjects; |
19 | -import java.util.Collections; | ||
20 | -import java.util.Map; | ||
21 | -import java.util.Set; | ||
22 | - | ||
23 | import org.onlab.onos.net.Link; | 19 | import org.onlab.onos.net.Link; |
24 | import org.onlab.onos.net.intent.IntentId; | 20 | import org.onlab.onos.net.intent.IntentId; |
25 | import org.onlab.onos.net.resource.LinkResourceAllocations; | 21 | import org.onlab.onos.net.resource.LinkResourceAllocations; |
... | @@ -28,6 +24,11 @@ import org.onlab.onos.net.resource.ResourceAllocation; | ... | @@ -28,6 +24,11 @@ import org.onlab.onos.net.resource.ResourceAllocation; |
28 | import org.onlab.onos.net.resource.ResourceRequest; | 24 | import org.onlab.onos.net.resource.ResourceRequest; |
29 | import org.onlab.onos.net.resource.ResourceType; | 25 | import org.onlab.onos.net.resource.ResourceType; |
30 | 26 | ||
27 | +import java.util.Collection; | ||
28 | +import java.util.Collections; | ||
29 | +import java.util.Map; | ||
30 | +import java.util.Set; | ||
31 | + | ||
31 | /** | 32 | /** |
32 | * Implementation of {@link LinkResourceAllocations}. | 33 | * Implementation of {@link LinkResourceAllocations}. |
33 | */ | 34 | */ |
... | @@ -76,4 +77,10 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations { | ... | @@ -76,4 +77,10 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations { |
76 | return result; | 77 | return result; |
77 | } | 78 | } |
78 | 79 | ||
80 | + @Override | ||
81 | + public String toString() { | ||
82 | + return MoreObjects.toStringHelper(this) | ||
83 | + .add("allocations", allocations) | ||
84 | + .toString(); | ||
85 | + } | ||
79 | } | 86 | } | ... | ... |
... | @@ -19,7 +19,6 @@ import com.google.common.collect.Sets; | ... | @@ -19,7 +19,6 @@ import com.google.common.collect.Sets; |
19 | 19 | ||
20 | import org.junit.After; | 20 | import org.junit.After; |
21 | import org.junit.Before; | 21 | import org.junit.Before; |
22 | -import org.junit.Ignore; | ||
23 | import org.junit.Test; | 22 | import org.junit.Test; |
24 | import org.onlab.onos.cluster.ClusterEventListener; | 23 | import org.onlab.onos.cluster.ClusterEventListener; |
25 | import org.onlab.onos.cluster.ClusterService; | 24 | import org.onlab.onos.cluster.ClusterService; |
... | @@ -181,16 +180,6 @@ public class DeviceManagerTest { | ... | @@ -181,16 +180,6 @@ public class DeviceManagerTest { |
181 | assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1)); | 180 | assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1)); |
182 | } | 181 | } |
183 | 182 | ||
184 | - @Ignore("disabled until we settle the device-mastership wiring") | ||
185 | - @Test | ||
186 | - public void setRole() throws InterruptedException { | ||
187 | - connectDevice(DID1, SW1); | ||
188 | - validateEvents(DEVICE_ADDED, DEVICE_MASTERSHIP_CHANGED); | ||
189 | - assertEquals("incorrect role", MastershipRole.STANDBY, service.getRole(DID1)); | ||
190 | - assertEquals("incorrect device", DID1, provider.deviceReceived.id()); | ||
191 | - assertEquals("incorrect role", MastershipRole.STANDBY, provider.roleReceived); | ||
192 | - } | ||
193 | - | ||
194 | @Test | 183 | @Test |
195 | public void updatePorts() { | 184 | public void updatePorts() { |
196 | connectDevice(DID1, SW1); | 185 | connectDevice(DID1, SW1); |
... | @@ -262,7 +251,7 @@ public class DeviceManagerTest { | ... | @@ -262,7 +251,7 @@ public class DeviceManagerTest { |
262 | 251 | ||
263 | 252 | ||
264 | private class TestProvider extends AbstractProvider implements DeviceProvider { | 253 | private class TestProvider extends AbstractProvider implements DeviceProvider { |
265 | - private Device deviceReceived; | 254 | + private DeviceId deviceReceived; |
266 | private MastershipRole roleReceived; | 255 | private MastershipRole roleReceived; |
267 | 256 | ||
268 | public TestProvider() { | 257 | public TestProvider() { |
... | @@ -274,13 +263,13 @@ public class DeviceManagerTest { | ... | @@ -274,13 +263,13 @@ public class DeviceManagerTest { |
274 | } | 263 | } |
275 | 264 | ||
276 | @Override | 265 | @Override |
277 | - public void roleChanged(Device device, MastershipRole newRole) { | 266 | + public void roleChanged(DeviceId device, MastershipRole newRole) { |
278 | deviceReceived = device; | 267 | deviceReceived = device; |
279 | roleReceived = newRole; | 268 | roleReceived = newRole; |
280 | } | 269 | } |
281 | 270 | ||
282 | @Override | 271 | @Override |
283 | - public boolean isReachable(Device device) { | 272 | + public boolean isReachable(DeviceId device) { |
284 | return false; | 273 | return false; |
285 | } | 274 | } |
286 | } | 275 | } |
... | @@ -360,9 +349,16 @@ public class DeviceManagerTest { | ... | @@ -360,9 +349,16 @@ public class DeviceManagerTest { |
360 | private final class TestClockProviderService implements | 349 | private final class TestClockProviderService implements |
361 | DeviceClockProviderService { | 350 | DeviceClockProviderService { |
362 | 351 | ||
352 | + private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet(); | ||
353 | + | ||
363 | @Override | 354 | @Override |
364 | public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { | 355 | public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { |
365 | - // TODO Auto-generated method stub | 356 | + registerdBefore.add(deviceId); |
357 | + } | ||
358 | + | ||
359 | + @Override | ||
360 | + public boolean isTimestampAvailable(DeviceId deviceId) { | ||
361 | + return registerdBefore.contains(deviceId); | ||
366 | } | 362 | } |
367 | } | 363 | } |
368 | } | 364 | } | ... | ... |
... | @@ -148,7 +148,7 @@ public class FlowRuleManagerTest { | ... | @@ -148,7 +148,7 @@ public class FlowRuleManagerTest { |
148 | int i = 0; | 148 | int i = 0; |
149 | System.err.println("events :" + listener.events); | 149 | System.err.println("events :" + listener.events); |
150 | for (FlowRuleEvent e : listener.events) { | 150 | for (FlowRuleEvent e : listener.events) { |
151 | - assertTrue("unexpected event", e.type().equals(events[i])); | 151 | + assertEquals("unexpected event", events[i], e.type()); |
152 | i++; | 152 | i++; |
153 | } | 153 | } |
154 | 154 | ||
... | @@ -178,15 +178,13 @@ public class FlowRuleManagerTest { | ... | @@ -178,15 +178,13 @@ public class FlowRuleManagerTest { |
178 | RULE_ADDED, RULE_ADDED); | 178 | RULE_ADDED, RULE_ADDED); |
179 | 179 | ||
180 | addFlowRule(1); | 180 | addFlowRule(1); |
181 | + System.err.println("events :" + listener.events); | ||
181 | assertEquals("should still be 2 rules", 2, flowCount()); | 182 | assertEquals("should still be 2 rules", 2, flowCount()); |
182 | 183 | ||
183 | providerService.pushFlowMetrics(DID, ImmutableList.of(fe1)); | 184 | providerService.pushFlowMetrics(DID, ImmutableList.of(fe1)); |
184 | validateEvents(RULE_UPDATED); | 185 | validateEvents(RULE_UPDATED); |
185 | } | 186 | } |
186 | 187 | ||
187 | - | ||
188 | - // TODO: If preserving iteration order is a requirement, redo FlowRuleStore. | ||
189 | - //backing store is sensitive to the order of additions/removals | ||
190 | private boolean validateState(Map<FlowRule, FlowEntryState> expected) { | 188 | private boolean validateState(Map<FlowRule, FlowEntryState> expected) { |
191 | Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected); | 189 | Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected); |
192 | Iterable<FlowEntry> rules = service.getFlowEntries(DID); | 190 | Iterable<FlowEntry> rules = service.getFlowEntries(DID); |
... | @@ -539,17 +537,17 @@ public class FlowRuleManagerTest { | ... | @@ -539,17 +537,17 @@ public class FlowRuleManagerTest { |
539 | 537 | ||
540 | @Override | 538 | @Override |
541 | public boolean cancel(boolean mayInterruptIfRunning) { | 539 | public boolean cancel(boolean mayInterruptIfRunning) { |
542 | - return true; | 540 | + return false; |
543 | } | 541 | } |
544 | 542 | ||
545 | @Override | 543 | @Override |
546 | public boolean isCancelled() { | 544 | public boolean isCancelled() { |
547 | - return true; | 545 | + return false; |
548 | } | 546 | } |
549 | 547 | ||
550 | @Override | 548 | @Override |
551 | public boolean isDone() { | 549 | public boolean isDone() { |
552 | - return false; | 550 | + return true; |
553 | } | 551 | } |
554 | 552 | ||
555 | @Override | 553 | @Override |
... | @@ -562,12 +560,14 @@ public class FlowRuleManagerTest { | ... | @@ -562,12 +560,14 @@ public class FlowRuleManagerTest { |
562 | public CompletedBatchOperation get(long timeout, TimeUnit unit) | 560 | public CompletedBatchOperation get(long timeout, TimeUnit unit) |
563 | throws InterruptedException, | 561 | throws InterruptedException, |
564 | ExecutionException, TimeoutException { | 562 | ExecutionException, TimeoutException { |
565 | - return null; | 563 | + return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet()); |
566 | } | 564 | } |
567 | 565 | ||
568 | @Override | 566 | @Override |
569 | public void addListener(Runnable task, Executor executor) { | 567 | public void addListener(Runnable task, Executor executor) { |
570 | - // TODO: add stuff. | 568 | + if (isDone()) { |
569 | + executor.execute(task); | ||
570 | + } | ||
571 | } | 571 | } |
572 | } | 572 | } |
573 | 573 | ... | ... |
... | @@ -20,11 +20,9 @@ import static org.easymock.EasyMock.expect; | ... | @@ -20,11 +20,9 @@ import static org.easymock.EasyMock.expect; |
20 | import static org.easymock.EasyMock.expectLastCall; | 20 | import static org.easymock.EasyMock.expectLastCall; |
21 | import static org.easymock.EasyMock.replay; | 21 | import static org.easymock.EasyMock.replay; |
22 | import static org.easymock.EasyMock.verify; | 22 | import static org.easymock.EasyMock.verify; |
23 | -import static org.junit.Assert.assertEquals; | 23 | +import static org.junit.Assert.*; |
24 | -import static org.junit.Assert.assertTrue; | ||
25 | 24 | ||
26 | import java.util.ArrayList; | 25 | import java.util.ArrayList; |
27 | -import java.util.Arrays; | ||
28 | import java.util.Collections; | 26 | import java.util.Collections; |
29 | import java.util.List; | 27 | import java.util.List; |
30 | import java.util.Set; | 28 | import java.util.Set; |
... | @@ -155,17 +153,20 @@ public class HostMonitorTest { | ... | @@ -155,17 +153,20 @@ public class HostMonitorTest { |
155 | Instruction instruction = packet.treatment().instructions().get(0); | 153 | Instruction instruction = packet.treatment().instructions().get(0); |
156 | assertTrue(instruction instanceof OutputInstruction); | 154 | assertTrue(instruction instanceof OutputInstruction); |
157 | OutputInstruction oi = (OutputInstruction) instruction; | 155 | OutputInstruction oi = (OutputInstruction) instruction; |
158 | - assertTrue(oi.port().equals(portNum)); | 156 | + assertEquals(portNum, oi.port()); |
159 | 157 | ||
160 | // Check the output packet is correct (well the important bits anyway) | 158 | // Check the output packet is correct (well the important bits anyway) |
161 | Ethernet eth = new Ethernet(); | 159 | Ethernet eth = new Ethernet(); |
162 | - eth.deserialize(packet.data().array(), 0, packet.data().array().length); | 160 | + final byte[] pktData = new byte[packet.data().remaining()]; |
161 | + packet.data().get(pktData); | ||
162 | + eth.deserialize(pktData, 0, pktData.length); | ||
163 | ARP arp = (ARP) eth.getPayload(); | 163 | ARP arp = (ARP) eth.getPayload(); |
164 | - assertTrue(Arrays.equals(arp.getSenderProtocolAddress(), | 164 | + assertArrayEquals(SOURCE_ADDR.toOctets(), |
165 | - SOURCE_ADDR.toOctets())); | 165 | + arp.getSenderProtocolAddress()); |
166 | - assertTrue(Arrays.equals(arp.getSenderHardwareAddress(), sourceMac.toBytes())); | 166 | + assertArrayEquals(sourceMac.toBytes(), |
167 | - assertTrue(Arrays.equals(arp.getTargetProtocolAddress(), | 167 | + arp.getSenderHardwareAddress()); |
168 | - TARGET_IP_ADDR.toOctets())); | 168 | + assertArrayEquals(TARGET_IP_ADDR.toOctets(), |
169 | + arp.getTargetProtocolAddress()); | ||
169 | } | 170 | } |
170 | 171 | ||
171 | class TestPacketService implements PacketService { | 172 | class TestPacketService implements PacketService { | ... | ... |
... | @@ -19,12 +19,9 @@ import static org.easymock.EasyMock.anyObject; | ... | @@ -19,12 +19,9 @@ import static org.easymock.EasyMock.anyObject; |
19 | import static org.easymock.EasyMock.createMock; | 19 | import static org.easymock.EasyMock.createMock; |
20 | import static org.easymock.EasyMock.expect; | 20 | import static org.easymock.EasyMock.expect; |
21 | import static org.easymock.EasyMock.replay; | 21 | import static org.easymock.EasyMock.replay; |
22 | -import static org.junit.Assert.assertEquals; | 22 | +import static org.junit.Assert.*; |
23 | -import static org.junit.Assert.assertFalse; | ||
24 | -import static org.junit.Assert.assertTrue; | ||
25 | 23 | ||
26 | import java.util.ArrayList; | 24 | import java.util.ArrayList; |
27 | -import java.util.Arrays; | ||
28 | import java.util.Collections; | 25 | import java.util.Collections; |
29 | import java.util.Comparator; | 26 | import java.util.Comparator; |
30 | import java.util.List; | 27 | import java.util.List; |
... | @@ -91,6 +88,7 @@ public class ProxyArpManagerTest { | ... | @@ -91,6 +88,7 @@ public class ProxyArpManagerTest { |
91 | private static final PortNumber P1 = PortNumber.portNumber(1); | 88 | private static final PortNumber P1 = PortNumber.portNumber(1); |
92 | private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L); | 89 | private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L); |
93 | private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L); | 90 | private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L); |
91 | + private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes(); | ||
94 | 92 | ||
95 | private ProxyArpManager proxyArp; | 93 | private ProxyArpManager proxyArp; |
96 | 94 | ||
... | @@ -483,7 +481,7 @@ public class ProxyArpManagerTest { | ... | @@ -483,7 +481,7 @@ public class ProxyArpManagerTest { |
483 | */ | 481 | */ |
484 | private void verifyPacketOut(Ethernet expected, ConnectPoint outPort, | 482 | private void verifyPacketOut(Ethernet expected, ConnectPoint outPort, |
485 | OutboundPacket actual) { | 483 | OutboundPacket actual) { |
486 | - assertTrue(Arrays.equals(expected.serialize(), actual.data().array())); | 484 | + assertArrayEquals(expected.serialize(), actual.data().array()); |
487 | assertEquals(1, actual.treatment().instructions().size()); | 485 | assertEquals(1, actual.treatment().instructions().size()); |
488 | assertEquals(outPort.deviceId(), actual.sendThrough()); | 486 | assertEquals(outPort.deviceId(), actual.sendThrough()); |
489 | Instruction instruction = actual.treatment().instructions().get(0); | 487 | Instruction instruction = actual.treatment().instructions().get(0); |
... | @@ -520,12 +518,12 @@ public class ProxyArpManagerTest { | ... | @@ -520,12 +518,12 @@ public class ProxyArpManagerTest { |
520 | Ethernet eth = new Ethernet(); | 518 | Ethernet eth = new Ethernet(); |
521 | 519 | ||
522 | if (dstMac == null) { | 520 | if (dstMac == null) { |
523 | - eth.setDestinationMACAddress(MacAddress.BROADCAST_MAC); | 521 | + eth.setDestinationMACAddress(MacAddress.BROADCAST); |
524 | } else { | 522 | } else { |
525 | - eth.setDestinationMACAddress(dstMac.getAddress()); | 523 | + eth.setDestinationMACAddress(dstMac); |
526 | } | 524 | } |
527 | 525 | ||
528 | - eth.setSourceMACAddress(srcMac.getAddress()); | 526 | + eth.setSourceMACAddress(srcMac); |
529 | eth.setEtherType(Ethernet.TYPE_ARP); | 527 | eth.setEtherType(Ethernet.TYPE_ARP); |
530 | eth.setVlanID(VLAN1.toShort()); | 528 | eth.setVlanID(VLAN1.toShort()); |
531 | 529 | ||
... | @@ -536,12 +534,12 @@ public class ProxyArpManagerTest { | ... | @@ -536,12 +534,12 @@ public class ProxyArpManagerTest { |
536 | 534 | ||
537 | arp.setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH); | 535 | arp.setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH); |
538 | arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH); | 536 | arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH); |
539 | - arp.setSenderHardwareAddress(srcMac.getAddress()); | 537 | + arp.setSenderHardwareAddress(srcMac.toBytes()); |
540 | 538 | ||
541 | if (dstMac == null) { | 539 | if (dstMac == null) { |
542 | - arp.setTargetHardwareAddress(MacAddress.ZERO_MAC_ADDRESS); | 540 | + arp.setTargetHardwareAddress(ZERO_MAC_ADDRESS); |
543 | } else { | 541 | } else { |
544 | - arp.setTargetHardwareAddress(dstMac.getAddress()); | 542 | + arp.setTargetHardwareAddress(dstMac.toBytes()); |
545 | } | 543 | } |
546 | 544 | ||
547 | arp.setSenderProtocolAddress(srcIp.toOctets()); | 545 | arp.setSenderProtocolAddress(srcIp.toOctets()); | ... | ... |
... | @@ -147,8 +147,7 @@ public class DistributedClusterStore | ... | @@ -147,8 +147,7 @@ public class DistributedClusterStore |
147 | } | 147 | } |
148 | 148 | ||
149 | private IpAddress memberAddress(Member member) { | 149 | private IpAddress memberAddress(Member member) { |
150 | - byte[] address = member.getSocketAddress().getAddress().getAddress(); | 150 | + return IpAddress.valueOf(member.getSocketAddress().getAddress()); |
151 | - return IpAddress.valueOf(address); | ||
152 | } | 151 | } |
153 | 152 | ||
154 | // Interceptor for membership events. | 153 | // Interceptor for membership events. | ... | ... |
... | @@ -85,7 +85,6 @@ public class ClusterCommunicationManager | ... | @@ -85,7 +85,6 @@ public class ClusterCommunicationManager |
85 | try { | 85 | try { |
86 | netty.activate(); | 86 | netty.activate(); |
87 | } catch (Exception e) { | 87 | } catch (Exception e) { |
88 | - // TODO Auto-generated catch block | ||
89 | log.error("NettyMessagingService#activate", e); | 88 | log.error("NettyMessagingService#activate", e); |
90 | } | 89 | } |
91 | messagingService = netty; | 90 | messagingService = netty; |
... | @@ -95,6 +94,12 @@ public class ClusterCommunicationManager | ... | @@ -95,6 +94,12 @@ public class ClusterCommunicationManager |
95 | @Deactivate | 94 | @Deactivate |
96 | public void deactivate() { | 95 | public void deactivate() { |
97 | // TODO: cleanup messageingService if needed. | 96 | // TODO: cleanup messageingService if needed. |
97 | + // FIXME: workaround until it becomes a service. | ||
98 | + try { | ||
99 | + ((NettyMessagingService) messagingService).deactivate(); | ||
100 | + } catch (Exception e) { | ||
101 | + log.error("NettyMessagingService#deactivate", e); | ||
102 | + } | ||
98 | log.info("Stopped"); | 103 | log.info("Stopped"); |
99 | } | 104 | } |
100 | 105 | ... | ... |
... | @@ -72,4 +72,9 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid | ... | @@ -72,4 +72,9 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid |
72 | log.info("adding term info {} {}", deviceId, term.master()); | 72 | log.info("adding term info {} {}", deviceId, term.master()); |
73 | deviceMastershipTerms.put(deviceId, term); | 73 | deviceMastershipTerms.put(deviceId, term); |
74 | } | 74 | } |
75 | + | ||
76 | + @Override | ||
77 | + public boolean isTimestampAvailable(DeviceId deviceId) { | ||
78 | + return deviceMastershipTerms.containsKey(deviceId); | ||
79 | + } | ||
75 | } | 80 | } | ... | ... |
... | @@ -1216,7 +1216,7 @@ public class GossipDeviceStore | ... | @@ -1216,7 +1216,7 @@ public class GossipDeviceStore |
1216 | @Override | 1216 | @Override |
1217 | public void handle(ClusterMessage message) { | 1217 | public void handle(ClusterMessage message) { |
1218 | 1218 | ||
1219 | - log.info("Received device update event from peer: {}", message.sender()); | 1219 | + log.debug("Received device update event from peer: {}", message.sender()); |
1220 | InternalDeviceEvent event = (InternalDeviceEvent) SERIALIZER.decode(message.payload()); | 1220 | InternalDeviceEvent event = (InternalDeviceEvent) SERIALIZER.decode(message.payload()); |
1221 | 1221 | ||
1222 | ProviderId providerId = event.providerId(); | 1222 | ProviderId providerId = event.providerId(); |
... | @@ -1231,7 +1231,7 @@ public class GossipDeviceStore | ... | @@ -1231,7 +1231,7 @@ public class GossipDeviceStore |
1231 | @Override | 1231 | @Override |
1232 | public void handle(ClusterMessage message) { | 1232 | public void handle(ClusterMessage message) { |
1233 | 1233 | ||
1234 | - log.info("Received device offline event from peer: {}", message.sender()); | 1234 | + log.debug("Received device offline event from peer: {}", message.sender()); |
1235 | InternalDeviceOfflineEvent event = (InternalDeviceOfflineEvent) SERIALIZER.decode(message.payload()); | 1235 | InternalDeviceOfflineEvent event = (InternalDeviceOfflineEvent) SERIALIZER.decode(message.payload()); |
1236 | 1236 | ||
1237 | DeviceId deviceId = event.deviceId(); | 1237 | DeviceId deviceId = event.deviceId(); |
... | @@ -1245,7 +1245,7 @@ public class GossipDeviceStore | ... | @@ -1245,7 +1245,7 @@ public class GossipDeviceStore |
1245 | @Override | 1245 | @Override |
1246 | public void handle(ClusterMessage message) { | 1246 | public void handle(ClusterMessage message) { |
1247 | 1247 | ||
1248 | - log.info("Received device removed event from peer: {}", message.sender()); | 1248 | + log.debug("Received device removed event from peer: {}", message.sender()); |
1249 | InternalDeviceRemovedEvent event = (InternalDeviceRemovedEvent) SERIALIZER.decode(message.payload()); | 1249 | InternalDeviceRemovedEvent event = (InternalDeviceRemovedEvent) SERIALIZER.decode(message.payload()); |
1250 | 1250 | ||
1251 | DeviceId deviceId = event.deviceId(); | 1251 | DeviceId deviceId = event.deviceId(); |
... | @@ -1259,13 +1259,19 @@ public class GossipDeviceStore | ... | @@ -1259,13 +1259,19 @@ public class GossipDeviceStore |
1259 | @Override | 1259 | @Override |
1260 | public void handle(ClusterMessage message) { | 1260 | public void handle(ClusterMessage message) { |
1261 | 1261 | ||
1262 | - log.info("Received port update event from peer: {}", message.sender()); | 1262 | + log.debug("Received port update event from peer: {}", message.sender()); |
1263 | InternalPortEvent event = (InternalPortEvent) SERIALIZER.decode(message.payload()); | 1263 | InternalPortEvent event = (InternalPortEvent) SERIALIZER.decode(message.payload()); |
1264 | 1264 | ||
1265 | ProviderId providerId = event.providerId(); | 1265 | ProviderId providerId = event.providerId(); |
1266 | DeviceId deviceId = event.deviceId(); | 1266 | DeviceId deviceId = event.deviceId(); |
1267 | Timestamped<List<PortDescription>> portDescriptions = event.portDescriptions(); | 1267 | Timestamped<List<PortDescription>> portDescriptions = event.portDescriptions(); |
1268 | 1268 | ||
1269 | + if (getDevice(deviceId) == null) { | ||
1270 | + log.info("{} not found on this node yet, ignoring.", deviceId); | ||
1271 | + // Note: dropped information will be recovered by anti-entropy | ||
1272 | + return; | ||
1273 | + } | ||
1274 | + | ||
1269 | notifyDelegate(updatePortsInternal(providerId, deviceId, portDescriptions)); | 1275 | notifyDelegate(updatePortsInternal(providerId, deviceId, portDescriptions)); |
1270 | } | 1276 | } |
1271 | } | 1277 | } |
... | @@ -1274,14 +1280,19 @@ public class GossipDeviceStore | ... | @@ -1274,14 +1280,19 @@ public class GossipDeviceStore |
1274 | @Override | 1280 | @Override |
1275 | public void handle(ClusterMessage message) { | 1281 | public void handle(ClusterMessage message) { |
1276 | 1282 | ||
1277 | - log.info("Received port status update event from peer: {}", message.sender()); | 1283 | + log.debug("Received port status update event from peer: {}", message.sender()); |
1278 | InternalPortStatusEvent event = (InternalPortStatusEvent) SERIALIZER.decode(message.payload()); | 1284 | InternalPortStatusEvent event = (InternalPortStatusEvent) SERIALIZER.decode(message.payload()); |
1279 | - log.info("{}", event); | ||
1280 | 1285 | ||
1281 | ProviderId providerId = event.providerId(); | 1286 | ProviderId providerId = event.providerId(); |
1282 | DeviceId deviceId = event.deviceId(); | 1287 | DeviceId deviceId = event.deviceId(); |
1283 | Timestamped<PortDescription> portDescription = event.portDescription(); | 1288 | Timestamped<PortDescription> portDescription = event.portDescription(); |
1284 | 1289 | ||
1290 | + if (getDevice(deviceId) == null) { | ||
1291 | + log.info("{} not found on this node yet, ignoring.", deviceId); | ||
1292 | + // Note: dropped information will be recovered by anti-entropy | ||
1293 | + return; | ||
1294 | + } | ||
1295 | + | ||
1285 | notifyDelegateIfNotNull(updatePortStatusInternal(providerId, deviceId, portDescription)); | 1296 | notifyDelegateIfNotNull(updatePortStatusInternal(providerId, deviceId, portDescription)); |
1286 | } | 1297 | } |
1287 | } | 1298 | } | ... | ... |
... | @@ -36,7 +36,7 @@ public class ReplicaInfoEvent extends AbstractEvent<ReplicaInfoEvent.Type, Devic | ... | @@ -36,7 +36,7 @@ public class ReplicaInfoEvent extends AbstractEvent<ReplicaInfoEvent.Type, Devic |
36 | */ | 36 | */ |
37 | MASTER_CHANGED, | 37 | MASTER_CHANGED, |
38 | // | 38 | // |
39 | - // BACKUPS_CHANGED? | 39 | + BACKUPS_CHANGED, |
40 | } | 40 | } |
41 | 41 | ||
42 | 42 | ... | ... |
... | @@ -284,9 +284,10 @@ public class DistributedFlowRuleStore | ... | @@ -284,9 +284,10 @@ public class DistributedFlowRuleStore |
284 | 284 | ||
285 | if (!replicaInfo.master().isPresent()) { | 285 | if (!replicaInfo.master().isPresent()) { |
286 | log.warn("No master for {}", deviceId); | 286 | log.warn("No master for {}", deviceId); |
287 | - // TODO: revisit if this should be returning empty collection. | 287 | + // TODO: revisit if this should be returning empty collection or throwing exception. |
288 | // FIXME: throw a FlowStoreException | 288 | // FIXME: throw a FlowStoreException |
289 | - throw new RuntimeException("No master for " + deviceId); | 289 | + //throw new RuntimeException("No master for " + deviceId); |
290 | + return Collections.emptyList(); | ||
290 | } | 291 | } |
291 | 292 | ||
292 | if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) { | 293 | if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) { | ... | ... |
... | @@ -18,10 +18,9 @@ package org.onlab.onos.store.flow.impl; | ... | @@ -18,10 +18,9 @@ package org.onlab.onos.store.flow.impl; |
18 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
19 | import static org.slf4j.LoggerFactory.getLogger; | 19 | import static org.slf4j.LoggerFactory.getLogger; |
20 | import static org.onlab.onos.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED; | 20 | import static org.onlab.onos.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED; |
21 | +import static org.onlab.onos.store.flow.ReplicaInfoEvent.Type.BACKUPS_CHANGED; | ||
21 | 22 | ||
22 | import java.util.Collections; | 23 | import java.util.Collections; |
23 | -import java.util.List; | ||
24 | - | ||
25 | import org.apache.felix.scr.annotations.Activate; | 24 | import org.apache.felix.scr.annotations.Activate; |
26 | import org.apache.felix.scr.annotations.Component; | 25 | import org.apache.felix.scr.annotations.Component; |
27 | import org.apache.felix.scr.annotations.Deactivate; | 26 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -96,12 +95,24 @@ public class ReplicaInfoManager implements ReplicaInfoService { | ... | @@ -96,12 +95,24 @@ public class ReplicaInfoManager implements ReplicaInfoService { |
96 | 95 | ||
97 | @Override | 96 | @Override |
98 | public void event(MastershipEvent event) { | 97 | public void event(MastershipEvent event) { |
99 | - // TODO: distinguish stby list update, when MastershipService, | 98 | + final ReplicaInfo replicaInfo |
100 | - // start publishing them | 99 | + = new ReplicaInfo(event.roleInfo().master(), |
101 | - final List<NodeId> standbyList = Collections.<NodeId>emptyList(); | 100 | + event.roleInfo().backups()); |
101 | + | ||
102 | + switch (event.type()) { | ||
103 | + case MASTER_CHANGED: | ||
102 | eventDispatcher.post(new ReplicaInfoEvent(MASTER_CHANGED, | 104 | eventDispatcher.post(new ReplicaInfoEvent(MASTER_CHANGED, |
103 | event.subject(), | 105 | event.subject(), |
104 | - new ReplicaInfo(event.roleInfo().master(), standbyList))); | 106 | + replicaInfo)); |
107 | + break; | ||
108 | + case BACKUPS_CHANGED: | ||
109 | + eventDispatcher.post(new ReplicaInfoEvent(BACKUPS_CHANGED, | ||
110 | + event.subject(), | ||
111 | + replicaInfo)); | ||
112 | + break; | ||
113 | + default: | ||
114 | + break; | ||
115 | + } | ||
105 | } | 116 | } |
106 | } | 117 | } |
107 | 118 | ... | ... |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | package org.onlab.onos.store.mastership.impl; | 16 | package org.onlab.onos.store.mastership.impl; |
17 | 17 | ||
18 | import static org.onlab.onos.mastership.MastershipEvent.Type.MASTER_CHANGED; | 18 | import static org.onlab.onos.mastership.MastershipEvent.Type.MASTER_CHANGED; |
19 | +import static org.onlab.onos.mastership.MastershipEvent.Type.BACKUPS_CHANGED; | ||
19 | import static org.apache.commons.lang3.concurrent.ConcurrentUtils.putIfAbsent; | 20 | import static org.apache.commons.lang3.concurrent.ConcurrentUtils.putIfAbsent; |
20 | 21 | ||
21 | import java.util.HashSet; | 22 | import java.util.HashSet; |
... | @@ -43,6 +44,7 @@ import org.onlab.onos.store.serializers.KryoNamespaces; | ... | @@ -43,6 +44,7 @@ import org.onlab.onos.store.serializers.KryoNamespaces; |
43 | import org.onlab.onos.store.serializers.KryoSerializer; | 44 | import org.onlab.onos.store.serializers.KryoSerializer; |
44 | import org.onlab.util.KryoNamespace; | 45 | import org.onlab.util.KryoNamespace; |
45 | 46 | ||
47 | +import com.google.common.base.Objects; | ||
46 | import com.hazelcast.core.EntryEvent; | 48 | import com.hazelcast.core.EntryEvent; |
47 | import com.hazelcast.core.EntryListener; | 49 | import com.hazelcast.core.EntryListener; |
48 | import com.hazelcast.core.IAtomicLong; | 50 | import com.hazelcast.core.IAtomicLong; |
... | @@ -297,8 +299,7 @@ implements MastershipStore { | ... | @@ -297,8 +299,7 @@ implements MastershipStore { |
297 | case NONE: | 299 | case NONE: |
298 | rv.reassign(nodeId, NONE, STANDBY); | 300 | rv.reassign(nodeId, NONE, STANDBY); |
299 | roleMap.put(deviceId, rv); | 301 | roleMap.put(deviceId, rv); |
300 | - // TODO: BACKUPS_CHANGED? | 302 | + return new MastershipEvent(BACKUPS_CHANGED, deviceId, rv.roleInfo()); |
301 | - return null; | ||
302 | default: | 303 | default: |
303 | log.warn("unknown Mastership Role {}", currentRole); | 304 | log.warn("unknown Mastership Role {}", currentRole); |
304 | } | 305 | } |
... | @@ -327,7 +328,8 @@ implements MastershipStore { | ... | @@ -327,7 +328,8 @@ implements MastershipStore { |
327 | roleMap.put(deviceId, rv); | 328 | roleMap.put(deviceId, rv); |
328 | return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo()); | 329 | return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo()); |
329 | } else { | 330 | } else { |
330 | - // no master candidate | 331 | + // No master candidate - no more backups, device is likely |
332 | + // fully disconnected | ||
331 | roleMap.put(deviceId, rv); | 333 | roleMap.put(deviceId, rv); |
332 | // Should there be new event type? | 334 | // Should there be new event type? |
333 | return null; | 335 | return null; |
... | @@ -338,8 +340,7 @@ implements MastershipStore { | ... | @@ -338,8 +340,7 @@ implements MastershipStore { |
338 | boolean modified = rv.reassign(nodeId, STANDBY, NONE); | 340 | boolean modified = rv.reassign(nodeId, STANDBY, NONE); |
339 | if (modified) { | 341 | if (modified) { |
340 | roleMap.put(deviceId, rv); | 342 | roleMap.put(deviceId, rv); |
341 | - // TODO: BACKUPS_CHANGED? | 343 | + return new MastershipEvent(BACKUPS_CHANGED, deviceId, rv.roleInfo()); |
342 | - return null; | ||
343 | } | 344 | } |
344 | return null; | 345 | return null; |
345 | default: | 346 | default: |
... | @@ -441,8 +442,24 @@ implements MastershipStore { | ... | @@ -441,8 +442,24 @@ implements MastershipStore { |
441 | 442 | ||
442 | @Override | 443 | @Override |
443 | public void entryUpdated(EntryEvent<DeviceId, RoleValue> event) { | 444 | public void entryUpdated(EntryEvent<DeviceId, RoleValue> event) { |
445 | + // compare old and current RoleValues. If master is different, | ||
446 | + // emit MASTER_CHANGED. else, emit BACKUPS_CHANGED. | ||
447 | + RoleValue oldValue = event.getOldValue(); | ||
448 | + RoleValue newValue = event.getValue(); | ||
449 | + | ||
450 | + NodeId oldMaster = null; | ||
451 | + if (oldValue != null) { | ||
452 | + oldMaster = oldValue.get(MASTER); | ||
453 | + } | ||
454 | + NodeId newMaster = newValue.get(MASTER); | ||
455 | + | ||
456 | + if (Objects.equal(oldMaster, newMaster)) { | ||
444 | notifyDelegate(new MastershipEvent( | 457 | notifyDelegate(new MastershipEvent( |
445 | MASTER_CHANGED, event.getKey(), event.getValue().roleInfo())); | 458 | MASTER_CHANGED, event.getKey(), event.getValue().roleInfo())); |
459 | + } else { | ||
460 | + notifyDelegate(new MastershipEvent( | ||
461 | + BACKUPS_CHANGED, event.getKey(), event.getValue().roleInfo())); | ||
462 | + } | ||
446 | } | 463 | } |
447 | 464 | ||
448 | @Override | 465 | @Override | ... | ... |
... | @@ -55,6 +55,13 @@ final class RoleValue { | ... | @@ -55,6 +55,13 @@ final class RoleValue { |
55 | return value.get(type); | 55 | return value.get(type); |
56 | } | 56 | } |
57 | 57 | ||
58 | + /** | ||
59 | + * Returns the first node to match the MastershipRole, or if there | ||
60 | + * are none, null. | ||
61 | + * | ||
62 | + * @param type the role | ||
63 | + * @return a node ID or null | ||
64 | + */ | ||
58 | public NodeId get(MastershipRole type) { | 65 | public NodeId get(MastershipRole type) { |
59 | return value.get(type).isEmpty() ? null : value.get(type).get(0); | 66 | return value.get(type).isEmpty() ? null : value.get(type).get(0); |
60 | } | 67 | } | ... | ... |
... | @@ -214,11 +214,11 @@ public class DistributedMastershipStoreTest { | ... | @@ -214,11 +214,11 @@ public class DistributedMastershipStoreTest { |
214 | dms.roleMap.get(DID1).nodesOfRole(STANDBY).size()); | 214 | dms.roleMap.get(DID1).nodesOfRole(STANDBY).size()); |
215 | 215 | ||
216 | //If STANDBY, should drop to NONE | 216 | //If STANDBY, should drop to NONE |
217 | - assertNull("wrong event:", dms.relinquishRole(N1, DID1)); | 217 | + assertEquals("wrong event:", Type.BACKUPS_CHANGED, dms.relinquishRole(N1, DID1).type()); |
218 | assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID1)); | 218 | assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID1)); |
219 | 219 | ||
220 | //NONE - nothing happens | 220 | //NONE - nothing happens |
221 | - assertNull("wrong event:", dms.relinquishRole(N1, DID2)); | 221 | + assertEquals("wrong event:", Type.BACKUPS_CHANGED, dms.relinquishRole(N1, DID2).type()); |
222 | assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID2)); | 222 | assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID2)); |
223 | 223 | ||
224 | } | 224 | } | ... | ... |
... | @@ -46,7 +46,13 @@ public class IpAddressSerializer extends Serializer<IpAddress> { | ... | @@ -46,7 +46,13 @@ public class IpAddressSerializer extends Serializer<IpAddress> { |
46 | final int octLen = input.readInt(); | 46 | final int octLen = input.readInt(); |
47 | byte[] octs = new byte[octLen]; | 47 | byte[] octs = new byte[octLen]; |
48 | input.readBytes(octs); | 48 | input.readBytes(octs); |
49 | - return IpAddress.valueOf(octs); | 49 | + // Use the address size to decide whether it is IPv4 or IPv6 address |
50 | + if (octLen == IpAddress.INET_BYTE_LENGTH) { | ||
51 | + return IpAddress.valueOf(IpAddress.Version.INET, octs); | ||
52 | + } | ||
53 | + if (octLen == IpAddress.INET6_BYTE_LENGTH) { | ||
54 | + return IpAddress.valueOf(IpAddress.Version.INET6, octs); | ||
55 | + } | ||
56 | + return null; // Shouldn't be reached | ||
50 | } | 57 | } |
51 | - | ||
52 | } | 58 | } | ... | ... |
... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.store.serializers; | 16 | package org.onlab.onos.store.serializers; |
17 | 17 | ||
18 | +import org.onlab.packet.IpAddress; | ||
18 | import org.onlab.packet.IpPrefix; | 19 | import org.onlab.packet.IpPrefix; |
19 | 20 | ||
20 | import com.esotericsoftware.kryo.Kryo; | 21 | import com.esotericsoftware.kryo.Kryo; |
... | @@ -51,6 +52,13 @@ public final class IpPrefixSerializer extends Serializer<IpPrefix> { | ... | @@ -51,6 +52,13 @@ public final class IpPrefixSerializer extends Serializer<IpPrefix> { |
51 | byte[] octs = new byte[octLen]; | 52 | byte[] octs = new byte[octLen]; |
52 | input.readBytes(octs); | 53 | input.readBytes(octs); |
53 | int prefLen = input.readInt(); | 54 | int prefLen = input.readInt(); |
54 | - return IpPrefix.valueOf(octs, prefLen); | 55 | + // Use the address size to decide whether it is IPv4 or IPv6 address |
56 | + if (octLen == IpAddress.INET_BYTE_LENGTH) { | ||
57 | + return IpPrefix.valueOf(IpAddress.Version.INET, octs, prefLen); | ||
58 | + } | ||
59 | + if (octLen == IpAddress.INET6_BYTE_LENGTH) { | ||
60 | + return IpPrefix.valueOf(IpAddress.Version.INET6, octs, prefLen); | ||
61 | + } | ||
62 | + return null; // Shouldn't be reached | ||
55 | } | 63 | } |
56 | } | 64 | } | ... | ... |
... | @@ -36,7 +36,7 @@ public class MacAddressSerializer extends Serializer<MacAddress> { | ... | @@ -36,7 +36,7 @@ public class MacAddressSerializer extends Serializer<MacAddress> { |
36 | 36 | ||
37 | @Override | 37 | @Override |
38 | public void write(Kryo kryo, Output output, MacAddress object) { | 38 | public void write(Kryo kryo, Output output, MacAddress object) { |
39 | - output.writeBytes(object.getAddress()); | 39 | + output.writeBytes(object.toBytes()); |
40 | } | 40 | } |
41 | 41 | ||
42 | @Override | 42 | @Override | ... | ... |
... | @@ -15,13 +15,16 @@ | ... | @@ -15,13 +15,16 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.store.trivial.impl; | 16 | package org.onlab.onos.store.trivial.impl; |
17 | 17 | ||
18 | +import java.util.Set; | ||
19 | + | ||
18 | import org.apache.felix.scr.annotations.Component; | 20 | import org.apache.felix.scr.annotations.Component; |
19 | import org.apache.felix.scr.annotations.Service; | 21 | import org.apache.felix.scr.annotations.Service; |
20 | import org.onlab.onos.mastership.MastershipTerm; | 22 | import org.onlab.onos.mastership.MastershipTerm; |
21 | import org.onlab.onos.net.DeviceId; | 23 | import org.onlab.onos.net.DeviceId; |
22 | import org.onlab.onos.net.device.DeviceClockProviderService; | 24 | import org.onlab.onos.net.device.DeviceClockProviderService; |
23 | 25 | ||
24 | -//FIXME: Code clone in onos-core-trivial, onos-core-hz-net | 26 | +import com.google.common.collect.Sets; |
27 | + | ||
25 | /** | 28 | /** |
26 | * Dummy implementation of {@link DeviceClockProviderService}. | 29 | * Dummy implementation of {@link DeviceClockProviderService}. |
27 | */ | 30 | */ |
... | @@ -29,7 +32,15 @@ import org.onlab.onos.net.device.DeviceClockProviderService; | ... | @@ -29,7 +32,15 @@ import org.onlab.onos.net.device.DeviceClockProviderService; |
29 | @Service | 32 | @Service |
30 | public class NoOpClockProviderService implements DeviceClockProviderService { | 33 | public class NoOpClockProviderService implements DeviceClockProviderService { |
31 | 34 | ||
35 | + private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet(); | ||
36 | + | ||
32 | @Override | 37 | @Override |
33 | public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { | 38 | public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { |
39 | + registerdBefore.add(deviceId); | ||
40 | + } | ||
41 | + | ||
42 | + @Override | ||
43 | + public boolean isTimestampAvailable(DeviceId deviceId) { | ||
44 | + return registerdBefore.contains(deviceId); | ||
34 | } | 45 | } |
35 | } | 46 | } | ... | ... |
... | @@ -16,8 +16,12 @@ | ... | @@ -16,8 +16,12 @@ |
16 | package org.onlab.onos.store.trivial.impl; | 16 | package org.onlab.onos.store.trivial.impl; |
17 | 17 | ||
18 | import com.google.common.base.Function; | 18 | import com.google.common.base.Function; |
19 | +import com.google.common.cache.Cache; | ||
20 | +import com.google.common.cache.CacheBuilder; | ||
19 | import com.google.common.collect.FluentIterable; | 21 | import com.google.common.collect.FluentIterable; |
20 | import com.google.common.util.concurrent.Futures; | 22 | import com.google.common.util.concurrent.Futures; |
23 | +import com.google.common.util.concurrent.SettableFuture; | ||
24 | + | ||
21 | import org.apache.felix.scr.annotations.Activate; | 25 | import org.apache.felix.scr.annotations.Activate; |
22 | import org.apache.felix.scr.annotations.Component; | 26 | import org.apache.felix.scr.annotations.Component; |
23 | import org.apache.felix.scr.annotations.Deactivate; | 27 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -43,13 +47,15 @@ import org.onlab.onos.store.AbstractStore; | ... | @@ -43,13 +47,15 @@ import org.onlab.onos.store.AbstractStore; |
43 | import org.onlab.util.NewConcurrentHashMap; | 47 | import org.onlab.util.NewConcurrentHashMap; |
44 | import org.slf4j.Logger; | 48 | import org.slf4j.Logger; |
45 | 49 | ||
46 | -import java.util.Arrays; | 50 | +import java.util.ArrayList; |
47 | import java.util.Collections; | 51 | import java.util.Collections; |
48 | import java.util.List; | 52 | import java.util.List; |
49 | import java.util.concurrent.ConcurrentHashMap; | 53 | import java.util.concurrent.ConcurrentHashMap; |
50 | import java.util.concurrent.ConcurrentMap; | 54 | import java.util.concurrent.ConcurrentMap; |
51 | import java.util.concurrent.CopyOnWriteArrayList; | 55 | import java.util.concurrent.CopyOnWriteArrayList; |
52 | import java.util.concurrent.Future; | 56 | import java.util.concurrent.Future; |
57 | +import java.util.concurrent.TimeUnit; | ||
58 | +import java.util.concurrent.atomic.AtomicInteger; | ||
53 | 59 | ||
54 | import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; | 60 | import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; |
55 | import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; | 61 | import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; |
... | @@ -72,6 +78,18 @@ public class SimpleFlowRuleStore | ... | @@ -72,6 +78,18 @@ public class SimpleFlowRuleStore |
72 | private final ConcurrentMap<DeviceId, ConcurrentMap<FlowId, List<StoredFlowEntry>>> | 78 | private final ConcurrentMap<DeviceId, ConcurrentMap<FlowId, List<StoredFlowEntry>>> |
73 | flowEntries = new ConcurrentHashMap<>(); | 79 | flowEntries = new ConcurrentHashMap<>(); |
74 | 80 | ||
81 | + private final AtomicInteger localBatchIdGen = new AtomicInteger(); | ||
82 | + | ||
83 | + // TODO: make this configurable | ||
84 | + private int pendingFutureTimeoutMinutes = 5; | ||
85 | + | ||
86 | + private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = | ||
87 | + CacheBuilder.newBuilder() | ||
88 | + .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) | ||
89 | + // TODO Explicitly fail the future if expired? | ||
90 | + //.removalListener(listener) | ||
91 | + .build(); | ||
92 | + | ||
75 | @Activate | 93 | @Activate |
76 | public void activate() { | 94 | public void activate() { |
77 | log.info("Started"); | 95 | log.info("Started"); |
... | @@ -173,10 +191,6 @@ public class SimpleFlowRuleStore | ... | @@ -173,10 +191,6 @@ public class SimpleFlowRuleStore |
173 | } | 191 | } |
174 | // new flow rule added | 192 | // new flow rule added |
175 | existing.add(f); | 193 | existing.add(f); |
176 | - notifyDelegate(FlowRuleBatchEvent.requested( | ||
177 | - new FlowRuleBatchRequest(1, /* FIXME generate something */ | ||
178 | - Arrays.<FlowEntry>asList(f), | ||
179 | - Collections.<FlowEntry>emptyList()))); | ||
180 | } | 194 | } |
181 | } | 195 | } |
182 | 196 | ||
... | @@ -190,11 +204,6 @@ public class SimpleFlowRuleStore | ... | @@ -190,11 +204,6 @@ public class SimpleFlowRuleStore |
190 | if (entry.equals(rule)) { | 204 | if (entry.equals(rule)) { |
191 | synchronized (entry) { | 205 | synchronized (entry) { |
192 | entry.setState(FlowEntryState.PENDING_REMOVE); | 206 | entry.setState(FlowEntryState.PENDING_REMOVE); |
193 | - // TODO: Should we notify only if it's "remote" event? | ||
194 | - notifyDelegate(FlowRuleBatchEvent.requested( | ||
195 | - new FlowRuleBatchRequest(1, /* FIXME generate something */ | ||
196 | - Collections.<FlowEntry>emptyList(), | ||
197 | - Arrays.<FlowEntry>asList(entry)))); | ||
198 | } | 207 | } |
199 | } | 208 | } |
200 | } | 209 | } |
... | @@ -251,20 +260,47 @@ public class SimpleFlowRuleStore | ... | @@ -251,20 +260,47 @@ public class SimpleFlowRuleStore |
251 | @Override | 260 | @Override |
252 | public Future<CompletedBatchOperation> storeBatch( | 261 | public Future<CompletedBatchOperation> storeBatch( |
253 | FlowRuleBatchOperation batchOperation) { | 262 | FlowRuleBatchOperation batchOperation) { |
263 | + List<FlowRule> toAdd = new ArrayList<>(); | ||
264 | + List<FlowRule> toRemove = new ArrayList<>(); | ||
254 | for (FlowRuleBatchEntry entry : batchOperation.getOperations()) { | 265 | for (FlowRuleBatchEntry entry : batchOperation.getOperations()) { |
266 | + final FlowRule flowRule = entry.getTarget(); | ||
255 | if (entry.getOperator().equals(FlowRuleOperation.ADD)) { | 267 | if (entry.getOperator().equals(FlowRuleOperation.ADD)) { |
256 | - storeFlowRule(entry.getTarget()); | 268 | + if (!getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) { |
269 | + storeFlowRule(flowRule); | ||
270 | + toAdd.add(flowRule); | ||
271 | + } | ||
257 | } else if (entry.getOperator().equals(FlowRuleOperation.REMOVE)) { | 272 | } else if (entry.getOperator().equals(FlowRuleOperation.REMOVE)) { |
258 | - deleteFlowRule(entry.getTarget()); | 273 | + if (getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) { |
274 | + deleteFlowRule(flowRule); | ||
275 | + toRemove.add(flowRule); | ||
276 | + } | ||
259 | } else { | 277 | } else { |
260 | throw new UnsupportedOperationException("Unsupported operation type"); | 278 | throw new UnsupportedOperationException("Unsupported operation type"); |
261 | } | 279 | } |
262 | } | 280 | } |
263 | - return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet())); | 281 | + |
282 | + if (toAdd.isEmpty() && toRemove.isEmpty()) { | ||
283 | + return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowRule>emptySet())); | ||
284 | + } | ||
285 | + | ||
286 | + SettableFuture<CompletedBatchOperation> r = SettableFuture.create(); | ||
287 | + final int batchId = localBatchIdGen.incrementAndGet(); | ||
288 | + | ||
289 | + pendingFutures.put(batchId, r); | ||
290 | + notifyDelegate(FlowRuleBatchEvent.requested(new FlowRuleBatchRequest(batchId, toAdd, toRemove))); | ||
291 | + | ||
292 | + return r; | ||
264 | } | 293 | } |
265 | 294 | ||
266 | @Override | 295 | @Override |
267 | public void batchOperationComplete(FlowRuleBatchEvent event) { | 296 | public void batchOperationComplete(FlowRuleBatchEvent event) { |
297 | + final Integer batchId = event.subject().batchId(); | ||
298 | + SettableFuture<CompletedBatchOperation> future | ||
299 | + = pendingFutures.getIfPresent(batchId); | ||
300 | + if (future != null) { | ||
301 | + future.set(event.result()); | ||
302 | + pendingFutures.invalidate(batchId); | ||
303 | + } | ||
268 | notifyDelegate(event); | 304 | notifyDelegate(event); |
269 | } | 305 | } |
270 | } | 306 | } | ... | ... |
... | @@ -115,17 +115,25 @@ public interface OpenFlowSwitch { | ... | @@ -115,17 +115,25 @@ public interface OpenFlowSwitch { |
115 | public String serialNumber(); | 115 | public String serialNumber(); |
116 | 116 | ||
117 | /** | 117 | /** |
118 | + * Checks if the switch is still connected. | ||
119 | + * | ||
120 | + * @return whether the switch is still connected | ||
121 | + */ | ||
122 | + public boolean isConnected(); | ||
123 | + | ||
124 | + /** | ||
118 | * Disconnects the switch by closing the TCP connection. Results in a call | 125 | * Disconnects the switch by closing the TCP connection. Results in a call |
119 | * to the channel handler's channelDisconnected method for cleanup | 126 | * to the channel handler's channelDisconnected method for cleanup |
120 | */ | 127 | */ |
121 | public void disconnectSwitch(); | 128 | public void disconnectSwitch(); |
122 | 129 | ||
123 | /** | 130 | /** |
124 | - * Notifies the controller that role assertion has failed. | 131 | + * Notifies the controller that the device has responded to a set-role request. |
125 | * | 132 | * |
126 | - * @param role the failed role | 133 | + * @param requested the role requested by the controller |
134 | + * @param response the role set at the device | ||
127 | */ | 135 | */ |
128 | - public void returnRoleAssertFailure(RoleState role); | 136 | + public void returnRoleReply(RoleState requested, RoleState reponse); |
129 | 137 | ||
130 | /** | 138 | /** |
131 | * Indicates if this switch is optical. | 139 | * Indicates if this switch is optical. | ... | ... |
... | @@ -53,5 +53,5 @@ public interface OpenFlowSwitchListener { | ... | @@ -53,5 +53,5 @@ public interface OpenFlowSwitchListener { |
53 | * @param dpid the switch that failed role assertion | 53 | * @param dpid the switch that failed role assertion |
54 | * @param role the role imposed by the controller | 54 | * @param role the role imposed by the controller |
55 | */ | 55 | */ |
56 | - public void roleAssertFailed(Dpid dpid, RoleState role); | 56 | + public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response); |
57 | } | 57 | } | ... | ... |
... | @@ -217,8 +217,8 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { | ... | @@ -217,8 +217,8 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver { |
217 | } | 217 | } |
218 | 218 | ||
219 | @Override | 219 | @Override |
220 | - public void returnRoleAssertFailure(RoleState role) { | 220 | + public void returnRoleReply(RoleState requested, RoleState response) { |
221 | - this.agent.returnRoleAssertFailed(dpid, role); | 221 | + this.agent.returnRoleReply(dpid, requested, response); |
222 | } | 222 | } |
223 | 223 | ||
224 | @Override | 224 | @Override | ... | ... |
... | @@ -97,5 +97,5 @@ public interface OpenFlowAgent { | ... | @@ -97,5 +97,5 @@ public interface OpenFlowAgent { |
97 | * @param dpid the switch that failed role assertion | 97 | * @param dpid the switch that failed role assertion |
98 | * @param role the failed role | 98 | * @param role the failed role |
99 | */ | 99 | */ |
100 | - public void returnRoleAssertFailed(Dpid dpid, RoleState role); | 100 | + public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response); |
101 | } | 101 | } | ... | ... |
... | @@ -187,13 +187,6 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch { | ... | @@ -187,13 +187,6 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch { |
187 | public void setConnected(boolean connected); | 187 | public void setConnected(boolean connected); |
188 | 188 | ||
189 | /** | 189 | /** |
190 | - * Checks if the switch is still connected. | ||
191 | - * | ||
192 | - * @return whether the switch is still connected | ||
193 | - */ | ||
194 | - public boolean isConnected(); | ||
195 | - | ||
196 | - /** | ||
197 | * Writes the message to the output stream | 190 | * Writes the message to the output stream |
198 | * in a driver specific manner. | 191 | * in a driver specific manner. |
199 | * | 192 | * | ... | ... |
... | @@ -374,9 +374,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { | ... | @@ -374,9 +374,9 @@ public class OpenFlowControllerImpl implements OpenFlowController { |
374 | } | 374 | } |
375 | 375 | ||
376 | @Override | 376 | @Override |
377 | - public void returnRoleAssertFailed(Dpid dpid, RoleState role) { | 377 | + public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response) { |
378 | for (OpenFlowSwitchListener l : ofSwitchListener) { | 378 | for (OpenFlowSwitchListener l : ofSwitchListener) { |
379 | - l.roleAssertFailed(dpid, role); | 379 | + l.receivedRoleReply(dpid, requested, response); |
380 | } | 380 | } |
381 | } | 381 | } |
382 | } | 382 | } | ... | ... |
... | @@ -17,6 +17,7 @@ package org.onlab.onos.openflow.controller.impl; | ... | @@ -17,6 +17,7 @@ package org.onlab.onos.openflow.controller.impl; |
17 | 17 | ||
18 | import java.io.IOException; | 18 | import java.io.IOException; |
19 | import java.util.Collections; | 19 | import java.util.Collections; |
20 | +import java.util.concurrent.TimeUnit; | ||
20 | 21 | ||
21 | import org.onlab.onos.openflow.controller.RoleState; | 22 | import org.onlab.onos.openflow.controller.RoleState; |
22 | import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver; | 23 | import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver; |
... | @@ -41,31 +42,29 @@ import org.projectfloodlight.openflow.types.U64; | ... | @@ -41,31 +42,29 @@ import org.projectfloodlight.openflow.types.U64; |
41 | import org.slf4j.Logger; | 42 | import org.slf4j.Logger; |
42 | import org.slf4j.LoggerFactory; | 43 | import org.slf4j.LoggerFactory; |
43 | 44 | ||
45 | +import com.google.common.cache.Cache; | ||
46 | +import com.google.common.cache.CacheBuilder; | ||
47 | + | ||
44 | 48 | ||
45 | /** | 49 | /** |
46 | * A utility class to handle role requests and replies for this channel. | 50 | * A utility class to handle role requests and replies for this channel. |
47 | * After a role request is submitted the role changer keeps track of the | 51 | * After a role request is submitted the role changer keeps track of the |
48 | * pending request, collects the reply (if any) and times out the request | 52 | * pending request, collects the reply (if any) and times out the request |
49 | * if necessary. | 53 | * if necessary. |
50 | - * | ||
51 | - * To simplify role handling we only keep track of the /last/ pending | ||
52 | - * role reply send to the switch. If multiple requests are pending and | ||
53 | - * we receive replies for earlier requests we ignore them. However, this | ||
54 | - * way of handling pending requests implies that we could wait forever if | ||
55 | - * a new request is submitted before the timeout triggers. If necessary | ||
56 | - * we could work around that though. | ||
57 | */ | 54 | */ |
58 | class RoleManager implements RoleHandler { | 55 | class RoleManager implements RoleHandler { |
59 | protected static final long NICIRA_EXPERIMENTER = 0x2320; | 56 | protected static final long NICIRA_EXPERIMENTER = 0x2320; |
60 | 57 | ||
61 | private static Logger log = LoggerFactory.getLogger(RoleManager.class); | 58 | private static Logger log = LoggerFactory.getLogger(RoleManager.class); |
62 | - // indicates that a request is currently pending | 59 | + |
63 | - // needs to be volatile to allow correct double-check idiom | 60 | + // The time until cached XID is evicted. Arbitray for now. |
64 | - private volatile boolean requestPending; | 61 | + private final int pendingXidTimeoutSeconds = 60; |
65 | - // the transaction Id of the pending request | 62 | + |
66 | - private int pendingXid; | 63 | + // The cache for pending expected RoleReplies keyed on expected XID |
67 | - // the role that's pending | 64 | + private Cache<Integer, RoleState> pendingReplies = |
68 | - private RoleState pendingRole; | 65 | + CacheBuilder.newBuilder() |
66 | + .expireAfterWrite(pendingXidTimeoutSeconds, TimeUnit.SECONDS) | ||
67 | + .build(); | ||
69 | 68 | ||
70 | // the expectation set by the caller for the returned role | 69 | // the expectation set by the caller for the returned role |
71 | private RoleRecvStatus expectation; | 70 | private RoleRecvStatus expectation; |
... | @@ -73,9 +72,6 @@ class RoleManager implements RoleHandler { | ... | @@ -73,9 +72,6 @@ class RoleManager implements RoleHandler { |
73 | 72 | ||
74 | 73 | ||
75 | public RoleManager(OpenFlowSwitchDriver sw) { | 74 | public RoleManager(OpenFlowSwitchDriver sw) { |
76 | - this.requestPending = false; | ||
77 | - this.pendingXid = -1; | ||
78 | - this.pendingRole = null; | ||
79 | this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE; | 75 | this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE; |
80 | this.sw = sw; | 76 | this.sw = sw; |
81 | } | 77 | } |
... | @@ -157,15 +153,11 @@ class RoleManager implements RoleHandler { | ... | @@ -157,15 +153,11 @@ class RoleManager implements RoleHandler { |
157 | } | 153 | } |
158 | // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn. | 154 | // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn. |
159 | // make Role.EQUAL become Role.SLAVE | 155 | // make Role.EQUAL become Role.SLAVE |
160 | - pendingRole = role; | 156 | + RoleState roleToSend = (role == RoleState.EQUAL) ? RoleState.SLAVE : role; |
161 | - role = (role == RoleState.EQUAL) ? RoleState.SLAVE : role; | 157 | + pendingReplies.put(sendNxRoleRequest(roleToSend), role); |
162 | - pendingXid = sendNxRoleRequest(role); | ||
163 | - requestPending = true; | ||
164 | } else { | 158 | } else { |
165 | // OF1.3 switch, use OFPT_ROLE_REQUEST message | 159 | // OF1.3 switch, use OFPT_ROLE_REQUEST message |
166 | - pendingXid = sendOF13RoleRequest(role); | 160 | + pendingReplies.put(sendOF13RoleRequest(role), role); |
167 | - pendingRole = role; | ||
168 | - requestPending = true; | ||
169 | } | 161 | } |
170 | return true; | 162 | return true; |
171 | } | 163 | } |
... | @@ -192,12 +184,17 @@ class RoleManager implements RoleHandler { | ... | @@ -192,12 +184,17 @@ class RoleManager implements RoleHandler { |
192 | @Override | 184 | @Override |
193 | public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri) | 185 | public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri) |
194 | throws SwitchStateException { | 186 | throws SwitchStateException { |
195 | - if (!requestPending) { | 187 | + int xid = (int) rri.getXid(); |
188 | + RoleState receivedRole = rri.getRole(); | ||
189 | + RoleState expectedRole = pendingReplies.getIfPresent(xid); | ||
190 | + | ||
191 | + if (expectedRole == null) { | ||
196 | RoleState currentRole = (sw != null) ? sw.getRole() : null; | 192 | RoleState currentRole = (sw != null) ? sw.getRole() : null; |
197 | if (currentRole != null) { | 193 | if (currentRole != null) { |
198 | if (currentRole == rri.getRole()) { | 194 | if (currentRole == rri.getRole()) { |
199 | // Don't disconnect if the role reply we received is | 195 | // Don't disconnect if the role reply we received is |
200 | // for the same role we are already in. | 196 | // for the same role we are already in. |
197 | + // FIXME: but we do from the caller anyways. | ||
201 | log.debug("Received unexpected RoleReply from " | 198 | log.debug("Received unexpected RoleReply from " |
202 | + "Switch: {}. " | 199 | + "Switch: {}. " |
203 | + "Role in reply is same as current role of this " | 200 | + "Role in reply is same as current role of this " |
... | @@ -223,34 +220,33 @@ class RoleManager implements RoleHandler { | ... | @@ -223,34 +220,33 @@ class RoleManager implements RoleHandler { |
223 | return RoleRecvStatus.OTHER_EXPECTATION; | 220 | return RoleRecvStatus.OTHER_EXPECTATION; |
224 | } | 221 | } |
225 | 222 | ||
226 | - int xid = (int) rri.getXid(); | 223 | + // XXX Should check generation id meaningfully and other cases of expectations |
227 | - RoleState role = rri.getRole(); | 224 | + //if (pendingXid != xid) { |
228 | - // XXX S should check generation id meaningfully and other cases of expectations | 225 | + // log.info("Received older role reply from " + |
229 | - | 226 | + // "switch {} ({}). Ignoring. " + |
230 | - if (pendingXid != xid) { | 227 | + // "Waiting for {}, xid={}", |
231 | - log.debug("Received older role reply from " + | 228 | + // new Object[] {sw.getStringId(), rri, |
232 | - "switch {} ({}). Ignoring. " + | 229 | + // pendingRole, pendingXid }); |
233 | - "Waiting for {}, xid={}", | 230 | + // return RoleRecvStatus.OLD_REPLY; |
234 | - new Object[] {sw.getStringId(), rri, | 231 | + //} |
235 | - pendingRole, pendingXid }); | 232 | + sw.returnRoleReply(expectedRole, receivedRole); |
236 | - return RoleRecvStatus.OLD_REPLY; | 233 | + |
237 | - } | 234 | + if (expectedRole == receivedRole) { |
238 | - | ||
239 | - if (pendingRole == role) { | ||
240 | log.debug("Received role reply message from {} that matched " | 235 | log.debug("Received role reply message from {} that matched " |
241 | + "expected role-reply {} with expectations {}", | 236 | + "expected role-reply {} with expectations {}", |
242 | - new Object[] {sw.getStringId(), role, expectation}); | 237 | + new Object[] {sw.getStringId(), receivedRole, expectation}); |
243 | 238 | ||
239 | + // Done with this RoleReply; Invalidate | ||
240 | + pendingReplies.invalidate(xid); | ||
244 | if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE || | 241 | if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE || |
245 | expectation == RoleRecvStatus.MATCHED_SET_ROLE) { | 242 | expectation == RoleRecvStatus.MATCHED_SET_ROLE) { |
246 | return expectation; | 243 | return expectation; |
247 | } else { | 244 | } else { |
248 | return RoleRecvStatus.OTHER_EXPECTATION; | 245 | return RoleRecvStatus.OTHER_EXPECTATION; |
249 | } | 246 | } |
250 | - } else { | ||
251 | - sw.returnRoleAssertFailure(pendingRole); | ||
252 | } | 247 | } |
253 | 248 | ||
249 | + pendingReplies.invalidate(xid); | ||
254 | // if xids match but role's don't, perhaps its a query (OF1.3) | 250 | // if xids match but role's don't, perhaps its a query (OF1.3) |
255 | if (expectation == RoleRecvStatus.REPLY_QUERY) { | 251 | if (expectation == RoleRecvStatus.REPLY_QUERY) { |
256 | return expectation; | 252 | return expectation; |
... | @@ -270,18 +266,17 @@ class RoleManager implements RoleHandler { | ... | @@ -270,18 +266,17 @@ class RoleManager implements RoleHandler { |
270 | @Override | 266 | @Override |
271 | public synchronized RoleRecvStatus deliverError(OFErrorMsg error) | 267 | public synchronized RoleRecvStatus deliverError(OFErrorMsg error) |
272 | throws SwitchStateException { | 268 | throws SwitchStateException { |
273 | - if (!requestPending) { | 269 | + RoleState errorRole = pendingReplies.getIfPresent(error.getXid()); |
274 | - log.debug("Received an error msg from sw {}, but no pending " | 270 | + if (errorRole == null) { |
275 | - + "requests in role-changer; not handling ...", | ||
276 | - sw.getStringId()); | ||
277 | - return RoleRecvStatus.OTHER_EXPECTATION; | ||
278 | - } | ||
279 | - if (pendingXid != error.getXid()) { | ||
280 | if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) { | 271 | if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) { |
281 | log.debug("Received an error msg from sw {} for a role request," | 272 | log.debug("Received an error msg from sw {} for a role request," |
282 | + " but not for pending request in role-changer; " | 273 | + " but not for pending request in role-changer; " |
283 | + " ignoring error {} ...", | 274 | + " ignoring error {} ...", |
284 | sw.getStringId(), error); | 275 | sw.getStringId(), error); |
276 | + } else { | ||
277 | + log.debug("Received an error msg from sw {}, but no pending " | ||
278 | + + "requests in role-changer; not handling ...", | ||
279 | + sw.getStringId()); | ||
285 | } | 280 | } |
286 | return RoleRecvStatus.OTHER_EXPECTATION; | 281 | return RoleRecvStatus.OTHER_EXPECTATION; |
287 | } | 282 | } |
... | @@ -292,7 +287,7 @@ class RoleManager implements RoleHandler { | ... | @@ -292,7 +287,7 @@ class RoleManager implements RoleHandler { |
292 | + "role-messaging is supported. Possible issues in " | 287 | + "role-messaging is supported. Possible issues in " |
293 | + "switch driver configuration?", new Object[] { | 288 | + "switch driver configuration?", new Object[] { |
294 | ((OFBadRequestErrorMsg) error).toString(), | 289 | ((OFBadRequestErrorMsg) error).toString(), |
295 | - sw.getStringId(), pendingRole | 290 | + sw.getStringId(), errorRole |
296 | }); | 291 | }); |
297 | return RoleRecvStatus.UNSUPPORTED; | 292 | return RoleRecvStatus.UNSUPPORTED; |
298 | } | 293 | } |
... | @@ -316,7 +311,7 @@ class RoleManager implements RoleHandler { | ... | @@ -316,7 +311,7 @@ class RoleManager implements RoleHandler { |
316 | + "received Error to for pending role request [%s]. " | 311 | + "received Error to for pending role request [%s]. " |
317 | + "Error:[%s]. Disconnecting switch ... ", | 312 | + "Error:[%s]. Disconnecting switch ... ", |
318 | sw.getStringId(), | 313 | sw.getStringId(), |
319 | - pendingRole, rrerr); | 314 | + errorRole, rrerr); |
320 | throw new SwitchStateException(msgx); | 315 | throw new SwitchStateException(msgx); |
321 | default: | 316 | default: |
322 | break; | 317 | break; | ... | ... |
... | @@ -175,11 +175,6 @@ public class RoleManagerTest { | ... | @@ -175,11 +175,6 @@ public class RoleManagerTest { |
175 | } | 175 | } |
176 | 176 | ||
177 | @Override | 177 | @Override |
178 | - public void returnRoleAssertFailure(RoleState role) { | ||
179 | - failed = role; | ||
180 | - } | ||
181 | - | ||
182 | - @Override | ||
183 | public boolean isOptical() { | 178 | public boolean isOptical() { |
184 | return false; | 179 | return false; |
185 | } | 180 | } |
... | @@ -300,5 +295,10 @@ public class RoleManagerTest { | ... | @@ -300,5 +295,10 @@ public class RoleManagerTest { |
300 | public void write(List<OFMessage> msgs) { | 295 | public void write(List<OFMessage> msgs) { |
301 | } | 296 | } |
302 | 297 | ||
298 | + @Override | ||
299 | + public void returnRoleReply(RoleState requested, RoleState response) { | ||
300 | + failed = requested; | ||
301 | + } | ||
302 | + | ||
303 | } | 303 | } |
304 | } | 304 | } | ... | ... |
... | @@ -318,6 +318,7 @@ | ... | @@ -318,6 +318,7 @@ |
318 | <groupId>io.netty</groupId> | 318 | <groupId>io.netty</groupId> |
319 | <artifactId>netty-transport-native-epoll</artifactId> | 319 | <artifactId>netty-transport-native-epoll</artifactId> |
320 | <version>${netty4.version}</version> | 320 | <version>${netty4.version}</version> |
321 | + <classifier>${os.detected.classifier}</classifier> | ||
321 | </dependency> | 322 | </dependency> |
322 | <dependency> | 323 | <dependency> |
323 | <groupId>joda-time</groupId> | 324 | <groupId>joda-time</groupId> |
... | @@ -351,6 +352,13 @@ | ... | @@ -351,6 +352,13 @@ |
351 | </dependencies> | 352 | </dependencies> |
352 | 353 | ||
353 | <build> | 354 | <build> |
355 | + <extensions> | ||
356 | + <extension> | ||
357 | + <groupId>kr.motd.maven</groupId> | ||
358 | + <artifactId>os-maven-plugin</artifactId> | ||
359 | + <version>1.2.3.Final</version> | ||
360 | + </extension> | ||
361 | + </extensions> | ||
354 | <pluginManagement> | 362 | <pluginManagement> |
355 | <plugins> | 363 | <plugins> |
356 | <plugin> | 364 | <plugin> | ... | ... |
... | @@ -120,7 +120,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid | ... | @@ -120,7 +120,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid |
120 | if (eth.getEtherType() == Ethernet.TYPE_ARP) { | 120 | if (eth.getEtherType() == Ethernet.TYPE_ARP) { |
121 | ARP arp = (ARP) eth.getPayload(); | 121 | ARP arp = (ARP) eth.getPayload(); |
122 | IpAddress ip = | 122 | IpAddress ip = |
123 | - IpAddress.valueOf(arp.getSenderProtocolAddress()); | 123 | + IpAddress.valueOf(IpAddress.Version.INET, |
124 | + arp.getSenderProtocolAddress()); | ||
124 | HostDescription hdescr = | 125 | HostDescription hdescr = |
125 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); | 126 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); |
126 | providerService.hostDetected(hid, hdescr); | 127 | providerService.hostDetected(hid, hdescr); | ... | ... |
... | @@ -216,7 +216,7 @@ public class HostLocationProviderTest { | ... | @@ -216,7 +216,7 @@ public class HostLocationProviderTest { |
216 | eth.setEtherType(Ethernet.TYPE_ARP) | 216 | eth.setEtherType(Ethernet.TYPE_ARP) |
217 | .setVlanID(VLAN.toShort()) | 217 | .setVlanID(VLAN.toShort()) |
218 | .setSourceMACAddress(MAC.toBytes()) | 218 | .setSourceMACAddress(MAC.toBytes()) |
219 | - .setDestinationMACAddress(BCMAC.getAddress()) | 219 | + .setDestinationMACAddress(BCMAC) |
220 | .setPayload(arp); | 220 | .setPayload(arp); |
221 | ConnectPoint receivedFrom = new ConnectPoint(DeviceId.deviceId(deviceId), | 221 | ConnectPoint receivedFrom = new ConnectPoint(DeviceId.deviceId(deviceId), |
222 | PortNumber.portNumber(INPORT)); | 222 | PortNumber.portNumber(INPORT)); | ... | ... |
... | @@ -127,18 +127,19 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -127,18 +127,19 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
127 | return; | 127 | return; |
128 | } | 128 | } |
129 | log.trace("{} {} {}", event.type(), event.subject(), event); | 129 | log.trace("{} {} {}", event.type(), event.subject(), event); |
130 | + final DeviceId deviceId = device.id(); | ||
130 | switch (event.type()) { | 131 | switch (event.type()) { |
131 | case DEVICE_ADDED: | 132 | case DEVICE_ADDED: |
132 | case DEVICE_UPDATED: | 133 | case DEVICE_UPDATED: |
133 | - ld = discoverers.get(device.id()); | 134 | + ld = discoverers.get(deviceId); |
134 | if (ld == null) { | 135 | if (ld == null) { |
135 | - log.debug("Device added ({}) {}", event.type(), device.id()); | 136 | + log.debug("Device added ({}) {}", event.type(), deviceId); |
136 | - discoverers.put(device.id(), | 137 | + discoverers.put(deviceId, |
137 | new LinkDiscovery(device, packetSevice, masterService, | 138 | new LinkDiscovery(device, packetSevice, masterService, |
138 | providerService, useBDDP)); | 139 | providerService, useBDDP)); |
139 | } else { | 140 | } else { |
140 | if (ld.isStopped()) { | 141 | if (ld.isStopped()) { |
141 | - log.debug("Device restarted ({}) {}", event.type(), device.id()); | 142 | + log.debug("Device restarted ({}) {}", event.type(), deviceId); |
142 | ld.start(); | 143 | ld.start(); |
143 | } | 144 | } |
144 | } | 145 | } |
... | @@ -146,7 +147,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -146,7 +147,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
146 | case PORT_ADDED: | 147 | case PORT_ADDED: |
147 | case PORT_UPDATED: | 148 | case PORT_UPDATED: |
148 | if (port.isEnabled()) { | 149 | if (port.isEnabled()) { |
149 | - ld = discoverers.get(device.id()); | 150 | + ld = discoverers.get(deviceId); |
150 | if (ld == null) { | 151 | if (ld == null) { |
151 | return; | 152 | return; |
152 | } | 153 | } |
... | @@ -156,47 +157,47 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { | ... | @@ -156,47 +157,47 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { |
156 | } | 157 | } |
157 | } else { | 158 | } else { |
158 | log.debug("Port down {}", port); | 159 | log.debug("Port down {}", port); |
159 | - ConnectPoint point = new ConnectPoint(device.id(), | 160 | + ConnectPoint point = new ConnectPoint(deviceId, |
160 | port.number()); | 161 | port.number()); |
161 | providerService.linksVanished(point); | 162 | providerService.linksVanished(point); |
162 | } | 163 | } |
163 | break; | 164 | break; |
164 | case PORT_REMOVED: | 165 | case PORT_REMOVED: |
165 | log.debug("Port removed {}", port); | 166 | log.debug("Port removed {}", port); |
166 | - ConnectPoint point = new ConnectPoint(device.id(), | 167 | + ConnectPoint point = new ConnectPoint(deviceId, |
167 | port.number()); | 168 | port.number()); |
168 | providerService.linksVanished(point); | 169 | providerService.linksVanished(point); |
169 | // TODO: Don't we need to removePort from ld? | 170 | // TODO: Don't we need to removePort from ld? |
170 | break; | 171 | break; |
171 | case DEVICE_REMOVED: | 172 | case DEVICE_REMOVED: |
172 | case DEVICE_SUSPENDED: | 173 | case DEVICE_SUSPENDED: |
173 | - log.debug("Device removed {}", device.id()); | 174 | + log.debug("Device removed {}", deviceId); |
174 | - ld = discoverers.get(device.id()); | 175 | + ld = discoverers.get(deviceId); |
175 | if (ld == null) { | 176 | if (ld == null) { |
176 | return; | 177 | return; |
177 | } | 178 | } |
178 | ld.stop(); | 179 | ld.stop(); |
179 | - providerService.linksVanished(device.id()); | 180 | + providerService.linksVanished(deviceId); |
180 | break; | 181 | break; |
181 | case DEVICE_AVAILABILITY_CHANGED: | 182 | case DEVICE_AVAILABILITY_CHANGED: |
182 | - ld = discoverers.get(device.id()); | 183 | + ld = discoverers.get(deviceId); |
183 | if (ld == null) { | 184 | if (ld == null) { |
184 | return; | 185 | return; |
185 | } | 186 | } |
186 | - if (deviceService.isAvailable(device.id())) { | 187 | + if (deviceService.isAvailable(deviceId)) { |
187 | - log.debug("Device up {}", device.id()); | 188 | + log.debug("Device up {}", deviceId); |
188 | ld.start(); | 189 | ld.start(); |
189 | } else { | 190 | } else { |
190 | - providerService.linksVanished(device.id()); | 191 | + providerService.linksVanished(deviceId); |
191 | - log.debug("Device down {}", device.id()); | 192 | + log.debug("Device down {}", deviceId); |
192 | ld.stop(); | 193 | ld.stop(); |
193 | } | 194 | } |
194 | break; | 195 | break; |
195 | case DEVICE_MASTERSHIP_CHANGED: | 196 | case DEVICE_MASTERSHIP_CHANGED: |
196 | - if (!discoverers.containsKey(device.id())) { | 197 | + if (!discoverers.containsKey(deviceId)) { |
197 | // TODO: ideally, should never reach here | 198 | // TODO: ideally, should never reach here |
198 | - log.debug("Device mastership changed ({}) {}", event.type(), device.id()); | 199 | + log.debug("Device mastership changed ({}) {}", event.type(), deviceId); |
199 | - discoverers.put(device.id(), | 200 | + discoverers.put(deviceId, |
200 | new LinkDiscovery(device, packetSevice, masterService, | 201 | new LinkDiscovery(device, packetSevice, masterService, |
201 | providerService, useBDDP)); | 202 | providerService, useBDDP)); |
202 | } | 203 | } | ... | ... |
... | @@ -39,7 +39,6 @@ import org.onlab.onos.openflow.controller.OpenFlowController; | ... | @@ -39,7 +39,6 @@ import org.onlab.onos.openflow.controller.OpenFlowController; |
39 | import org.onlab.onos.openflow.controller.OpenFlowSwitch; | 39 | import org.onlab.onos.openflow.controller.OpenFlowSwitch; |
40 | import org.onlab.onos.openflow.controller.OpenFlowSwitchListener; | 40 | import org.onlab.onos.openflow.controller.OpenFlowSwitchListener; |
41 | import org.onlab.onos.openflow.controller.RoleState; | 41 | import org.onlab.onos.openflow.controller.RoleState; |
42 | -import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver; | ||
43 | import org.onlab.packet.ChassisId; | 42 | import org.onlab.packet.ChassisId; |
44 | import org.projectfloodlight.openflow.protocol.OFFactory; | 43 | import org.projectfloodlight.openflow.protocol.OFFactory; |
45 | import org.projectfloodlight.openflow.protocol.OFPortConfig; | 44 | import org.projectfloodlight.openflow.protocol.OFPortConfig; |
... | @@ -112,27 +111,39 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -112,27 +111,39 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
112 | 111 | ||
113 | 112 | ||
114 | @Override | 113 | @Override |
115 | - public boolean isReachable(Device device) { | 114 | + public boolean isReachable(DeviceId deviceId) { |
116 | - // FIXME if possible, we might want this to be part of | 115 | + OpenFlowSwitch sw = controller.getSwitch(dpid(deviceId.uri())); |
117 | - // OpenFlowSwitch interface so the driver interface isn't misused. | 116 | + if (sw == null || !sw.isConnected()) { |
118 | - OpenFlowSwitch sw = controller.getSwitch(dpid(device.id().uri())); | ||
119 | - if (sw == null || !((OpenFlowSwitchDriver) sw).isConnected()) { | ||
120 | return false; | 117 | return false; |
121 | } | 118 | } |
122 | return true; | 119 | return true; |
123 | - //return checkChannel(device, sw); | ||
124 | } | 120 | } |
125 | 121 | ||
126 | @Override | 122 | @Override |
127 | public void triggerProbe(Device device) { | 123 | public void triggerProbe(Device device) { |
128 | - LOG.info("Triggering probe on device {}", device.id()); | 124 | + final DeviceId deviceId = device.id(); |
125 | + LOG.info("Triggering probe on device {}", deviceId); | ||
129 | 126 | ||
130 | - OpenFlowSwitch sw = controller.getSwitch(dpid(device.id().uri())); | 127 | + final Dpid dpid = dpid(deviceId.uri()); |
131 | - //if (!checkChannel(device, sw)) { | 128 | + OpenFlowSwitch sw = controller.getSwitch(dpid); |
132 | - // LOG.error("Failed to probe device {} on sw={}", device, sw); | 129 | + if (sw == null || !sw.isConnected()) { |
133 | - // providerService.deviceDisconnected(device.id()); | 130 | + LOG.error("Failed to probe device {} on sw={}", device, sw); |
134 | - //return; | 131 | + providerService.deviceDisconnected(deviceId); |
135 | - //} | 132 | + } else { |
133 | + LOG.trace("Confirmed device {} connection", device); | ||
134 | + // FIXME require something like below to match javadoc description | ||
135 | + // but this starts infinite loop with current DeviceManager | ||
136 | +// final ChassisId cId = new ChassisId(dpid.value()); | ||
137 | +// final Type deviceType = device.type(); | ||
138 | +// DeviceDescription description = | ||
139 | +// new DefaultDeviceDescription(deviceId.uri(), deviceType, | ||
140 | +// sw.manfacturerDescription(), | ||
141 | +// sw.hardwareDescription(), | ||
142 | +// sw.softwareDescription(), | ||
143 | +// sw.serialNumber(), | ||
144 | +// cId); | ||
145 | +// providerService.deviceConnected(deviceId, description); | ||
146 | + } | ||
136 | 147 | ||
137 | // Prompt an update of port information. We can use any XID for this. | 148 | // Prompt an update of port information. We can use any XID for this. |
138 | OFFactory fact = sw.factory(); | 149 | OFFactory fact = sw.factory(); |
... | @@ -159,22 +170,22 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -159,22 +170,22 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
159 | // } | 170 | // } |
160 | 171 | ||
161 | @Override | 172 | @Override |
162 | - public void roleChanged(Device device, MastershipRole newRole) { | 173 | + public void roleChanged(DeviceId deviceId, MastershipRole newRole) { |
163 | switch (newRole) { | 174 | switch (newRole) { |
164 | case MASTER: | 175 | case MASTER: |
165 | - controller.setRole(dpid(device.id().uri()), RoleState.MASTER); | 176 | + controller.setRole(dpid(deviceId.uri()), RoleState.MASTER); |
166 | break; | 177 | break; |
167 | case STANDBY: | 178 | case STANDBY: |
168 | - controller.setRole(dpid(device.id().uri()), RoleState.EQUAL); | 179 | + controller.setRole(dpid(deviceId.uri()), RoleState.EQUAL); |
169 | break; | 180 | break; |
170 | case NONE: | 181 | case NONE: |
171 | - controller.setRole(dpid(device.id().uri()), RoleState.SLAVE); | 182 | + controller.setRole(dpid(deviceId.uri()), RoleState.SLAVE); |
172 | break; | 183 | break; |
173 | default: | 184 | default: |
174 | LOG.error("Unknown Mastership state : {}", newRole); | 185 | LOG.error("Unknown Mastership state : {}", newRole); |
175 | 186 | ||
176 | } | 187 | } |
177 | - LOG.info("Accepting mastership role change for device {}", device.id()); | 188 | + LOG.info("Accepting mastership role change for device {}", deviceId); |
178 | } | 189 | } |
179 | 190 | ||
180 | private class InternalDeviceProvider implements OpenFlowSwitchListener { | 191 | private class InternalDeviceProvider implements OpenFlowSwitchListener { |
... | @@ -226,23 +237,31 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr | ... | @@ -226,23 +237,31 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr |
226 | } | 237 | } |
227 | 238 | ||
228 | @Override | 239 | @Override |
229 | - public void roleAssertFailed(Dpid dpid, RoleState role) { | 240 | + public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) { |
230 | - MastershipRole failed; | 241 | + MastershipRole request = roleOf(requested); |
231 | - switch (role) { | 242 | + MastershipRole reply = roleOf(response); |
243 | + | ||
244 | + providerService.receivedRoleReply(deviceId(uri(dpid)), request, reply); | ||
245 | + } | ||
246 | + | ||
247 | + /** | ||
248 | + * Translates a RoleState to the corresponding MastershipRole. | ||
249 | + * | ||
250 | + * @param response | ||
251 | + * @return a MastershipRole | ||
252 | + */ | ||
253 | + private MastershipRole roleOf(RoleState response) { | ||
254 | + switch (response) { | ||
232 | case MASTER: | 255 | case MASTER: |
233 | - failed = MastershipRole.MASTER; | 256 | + return MastershipRole.MASTER; |
234 | - break; | ||
235 | case EQUAL: | 257 | case EQUAL: |
236 | - failed = MastershipRole.STANDBY; | 258 | + return MastershipRole.STANDBY; |
237 | - break; | ||
238 | case SLAVE: | 259 | case SLAVE: |
239 | - failed = MastershipRole.NONE; | 260 | + return MastershipRole.NONE; |
240 | - break; | ||
241 | default: | 261 | default: |
242 | - LOG.warn("unknown role {}", role); | 262 | + LOG.warn("unknown role {}", response); |
243 | - return; | 263 | + return null; |
244 | } | 264 | } |
245 | - providerService.unableToAssertRole(deviceId(uri(dpid)), failed); | ||
246 | } | 265 | } |
247 | 266 | ||
248 | /** | 267 | /** | ... | ... |
... | @@ -105,11 +105,11 @@ public class OpenFlowDeviceProviderTest { | ... | @@ -105,11 +105,11 @@ public class OpenFlowDeviceProviderTest { |
105 | 105 | ||
106 | @Test | 106 | @Test |
107 | public void roleChanged() { | 107 | public void roleChanged() { |
108 | - provider.roleChanged(DEV1, MASTER); | 108 | + provider.roleChanged(DID1, MASTER); |
109 | assertEquals("Should be MASTER", RoleState.MASTER, controller.roleMap.get(DPID1)); | 109 | assertEquals("Should be MASTER", RoleState.MASTER, controller.roleMap.get(DPID1)); |
110 | - provider.roleChanged(DEV1, STANDBY); | 110 | + provider.roleChanged(DID1, STANDBY); |
111 | assertEquals("Should be EQUAL", RoleState.EQUAL, controller.roleMap.get(DPID1)); | 111 | assertEquals("Should be EQUAL", RoleState.EQUAL, controller.roleMap.get(DPID1)); |
112 | - provider.roleChanged(DEV1, NONE); | 112 | + provider.roleChanged(DID1, NONE); |
113 | assertEquals("Should be SLAVE", RoleState.SLAVE, controller.roleMap.get(DPID1)); | 113 | assertEquals("Should be SLAVE", RoleState.SLAVE, controller.roleMap.get(DPID1)); |
114 | } | 114 | } |
115 | 115 | ||
... | @@ -136,12 +136,13 @@ public class OpenFlowDeviceProviderTest { | ... | @@ -136,12 +136,13 @@ public class OpenFlowDeviceProviderTest { |
136 | } | 136 | } |
137 | 137 | ||
138 | @Test | 138 | @Test |
139 | - public void roleAssertFailed() { | 139 | + public void receivedRoleReply() { |
140 | - controller.listener.roleAssertFailed(DPID1, RoleState.MASTER); | 140 | + // check translation capabilities |
141 | + controller.listener.receivedRoleReply(DPID1, RoleState.MASTER, RoleState.MASTER); | ||
141 | assertEquals("wrong role reported", DPID1, registry.roles.get(MASTER)); | 142 | assertEquals("wrong role reported", DPID1, registry.roles.get(MASTER)); |
142 | - controller.listener.roleAssertFailed(DPID1, RoleState.EQUAL); | 143 | + controller.listener.receivedRoleReply(DPID1, RoleState.EQUAL, RoleState.MASTER); |
143 | assertEquals("wrong role reported", DPID1, registry.roles.get(STANDBY)); | 144 | assertEquals("wrong role reported", DPID1, registry.roles.get(STANDBY)); |
144 | - controller.listener.roleAssertFailed(DPID1, RoleState.SLAVE); | 145 | + controller.listener.receivedRoleReply(DPID1, RoleState.SLAVE, RoleState.MASTER); |
145 | assertEquals("wrong role reported", DPID1, registry.roles.get(NONE)); | 146 | assertEquals("wrong role reported", DPID1, registry.roles.get(NONE)); |
146 | } | 147 | } |
147 | 148 | ||
... | @@ -210,8 +211,9 @@ public class OpenFlowDeviceProviderTest { | ... | @@ -210,8 +211,9 @@ public class OpenFlowDeviceProviderTest { |
210 | } | 211 | } |
211 | 212 | ||
212 | @Override | 213 | @Override |
213 | - public void unableToAssertRole(DeviceId deviceId, MastershipRole role) { | 214 | + public void receivedRoleReply(DeviceId deviceId, |
214 | - roles.put(role, Dpid.dpid(deviceId.uri())); | 215 | + MastershipRole requested, MastershipRole response) { |
216 | + roles.put(requested, Dpid.dpid(deviceId.uri())); | ||
215 | } | 217 | } |
216 | 218 | ||
217 | } | 219 | } |
... | @@ -368,11 +370,12 @@ public class OpenFlowDeviceProviderTest { | ... | @@ -368,11 +370,12 @@ public class OpenFlowDeviceProviderTest { |
368 | } | 370 | } |
369 | 371 | ||
370 | @Override | 372 | @Override |
371 | - public void disconnectSwitch() { | 373 | + public boolean isConnected() { |
374 | + return true; | ||
372 | } | 375 | } |
373 | 376 | ||
374 | @Override | 377 | @Override |
375 | - public void returnRoleAssertFailure(RoleState role) { | 378 | + public void disconnectSwitch() { |
376 | } | 379 | } |
377 | 380 | ||
378 | @Override | 381 | @Override |
... | @@ -380,6 +383,10 @@ public class OpenFlowDeviceProviderTest { | ... | @@ -380,6 +383,10 @@ public class OpenFlowDeviceProviderTest { |
380 | return false; | 383 | return false; |
381 | } | 384 | } |
382 | 385 | ||
386 | + @Override | ||
387 | + public void returnRoleReply(RoleState requested, RoleState reponse) { | ||
388 | + } | ||
389 | + | ||
383 | } | 390 | } |
384 | 391 | ||
385 | } | 392 | } | ... | ... |
... | @@ -147,7 +147,8 @@ public abstract class FlowModBuilder { | ... | @@ -147,7 +147,8 @@ public abstract class FlowModBuilder { |
147 | ip = (IPCriterion) c; | 147 | ip = (IPCriterion) c; |
148 | if (ip.ip().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH) { | 148 | if (ip.ip().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH) { |
149 | IpAddress maskAddr = | 149 | IpAddress maskAddr = |
150 | - IpAddress.makeMaskPrefix(ip.ip().prefixLength()); | 150 | + IpAddress.makeMaskPrefix(ip.ip().address().version(), |
151 | + ip.ip().prefixLength()); | ||
151 | Masked<IPv4Address> maskedIp = | 152 | Masked<IPv4Address> maskedIp = |
152 | Masked.of(IPv4Address.of(ip.ip().address().toInt()), | 153 | Masked.of(IPv4Address.of(ip.ip().address().toInt()), |
153 | IPv4Address.of(maskAddr.toInt())); | 154 | IPv4Address.of(maskAddr.toInt())); |
... | @@ -161,7 +162,8 @@ public abstract class FlowModBuilder { | ... | @@ -161,7 +162,8 @@ public abstract class FlowModBuilder { |
161 | ip = (IPCriterion) c; | 162 | ip = (IPCriterion) c; |
162 | if (ip.ip().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH) { | 163 | if (ip.ip().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH) { |
163 | IpAddress maskAddr = | 164 | IpAddress maskAddr = |
164 | - IpAddress.makeMaskPrefix(ip.ip().prefixLength()); | 165 | + IpAddress.makeMaskPrefix(ip.ip().address().version(), |
166 | + ip.ip().prefixLength()); | ||
165 | Masked<IPv4Address> maskedIp = | 167 | Masked<IPv4Address> maskedIp = |
166 | Masked.of(IPv4Address.of(ip.ip().address().toInt()), | 168 | Masked.of(IPv4Address.of(ip.ip().address().toInt()), |
167 | IPv4Address.of(maskAddr.toInt())); | 169 | IPv4Address.of(maskAddr.toInt())); | ... | ... |
providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
... | @@ -302,7 +302,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -302,7 +302,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
302 | } | 302 | } |
303 | 303 | ||
304 | @Override | 304 | @Override |
305 | - public void roleAssertFailed(Dpid dpid, RoleState role) {} | 305 | + public void receivedRoleReply(Dpid dpid, RoleState requested, |
306 | + RoleState response) { | ||
307 | + // Do nothing here for now. | ||
308 | + } | ||
306 | 309 | ||
307 | private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) { | 310 | private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) { |
308 | if (stats.getStatsType() != OFStatsType.FLOW) { | 311 | if (stats.getStatsType() != OFStatsType.FLOW) { | ... | ... |
providers/openflow/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
... | @@ -126,7 +126,8 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid | ... | @@ -126,7 +126,8 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid |
126 | if (eth.getEtherType() == Ethernet.TYPE_ARP) { | 126 | if (eth.getEtherType() == Ethernet.TYPE_ARP) { |
127 | ARP arp = (ARP) eth.getPayload(); | 127 | ARP arp = (ARP) eth.getPayload(); |
128 | IpAddress ip = | 128 | IpAddress ip = |
129 | - IpAddress.valueOf(arp.getSenderProtocolAddress()); | 129 | + IpAddress.valueOf(IpAddress.Version.INET, |
130 | + arp.getSenderProtocolAddress()); | ||
130 | HostDescription hdescr = | 131 | HostDescription hdescr = |
131 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); | 132 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); |
132 | providerService.hostDetected(hid, hdescr); | 133 | providerService.hostDetected(hid, hdescr); | ... | ... |
... | @@ -213,8 +213,8 @@ public class OpenFlowHostProviderTest { | ... | @@ -213,8 +213,8 @@ public class OpenFlowHostProviderTest { |
213 | Ethernet eth = new Ethernet(); | 213 | Ethernet eth = new Ethernet(); |
214 | eth.setEtherType(Ethernet.TYPE_ARP) | 214 | eth.setEtherType(Ethernet.TYPE_ARP) |
215 | .setVlanID(VLAN.toShort()) | 215 | .setVlanID(VLAN.toShort()) |
216 | - .setSourceMACAddress(MAC.toBytes()) | 216 | + .setSourceMACAddress(MAC) |
217 | - .setDestinationMACAddress(BCMAC.getAddress()) | 217 | + .setDestinationMACAddress(BCMAC) |
218 | .setPayload(arp); | 218 | .setPayload(arp); |
219 | 219 | ||
220 | return eth; | 220 | return eth; | ... | ... |
providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
... | @@ -160,7 +160,8 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid | ... | @@ -160,7 +160,8 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid |
160 | } | 160 | } |
161 | 161 | ||
162 | @Override | 162 | @Override |
163 | - public void roleAssertFailed(Dpid dpid, RoleState role) { | 163 | + public void receivedRoleReply(Dpid dpid, RoleState requested, |
164 | + RoleState response) { | ||
164 | // do nothing for this. | 165 | // do nothing for this. |
165 | } | 166 | } |
166 | 167 | ... | ... |
... | @@ -475,11 +475,12 @@ public class OpenFlowLinkProviderTest { | ... | @@ -475,11 +475,12 @@ public class OpenFlowLinkProviderTest { |
475 | } | 475 | } |
476 | 476 | ||
477 | @Override | 477 | @Override |
478 | - public void disconnectSwitch() { | 478 | + public boolean isConnected() { |
479 | + return true; | ||
479 | } | 480 | } |
480 | 481 | ||
481 | @Override | 482 | @Override |
482 | - public void returnRoleAssertFailure(RoleState role) { | 483 | + public void disconnectSwitch() { |
483 | } | 484 | } |
484 | 485 | ||
485 | @Override | 486 | @Override |
... | @@ -487,5 +488,9 @@ public class OpenFlowLinkProviderTest { | ... | @@ -487,5 +488,9 @@ public class OpenFlowLinkProviderTest { |
487 | return false; | 488 | return false; |
488 | } | 489 | } |
489 | 490 | ||
491 | + @Override | ||
492 | + public void returnRoleReply(RoleState requested, RoleState reponse) { | ||
493 | + } | ||
494 | + | ||
490 | } | 495 | } |
491 | } | 496 | } | ... | ... |
... | @@ -406,11 +406,12 @@ public class OpenFlowPacketProviderTest { | ... | @@ -406,11 +406,12 @@ public class OpenFlowPacketProviderTest { |
406 | } | 406 | } |
407 | 407 | ||
408 | @Override | 408 | @Override |
409 | - public void disconnectSwitch() { | 409 | + public boolean isConnected() { |
410 | + return true; | ||
410 | } | 411 | } |
411 | 412 | ||
412 | @Override | 413 | @Override |
413 | - public void returnRoleAssertFailure(RoleState role) { | 414 | + public void disconnectSwitch() { |
414 | } | 415 | } |
415 | 416 | ||
416 | @Override | 417 | @Override |
... | @@ -418,6 +419,10 @@ public class OpenFlowPacketProviderTest { | ... | @@ -418,6 +419,10 @@ public class OpenFlowPacketProviderTest { |
418 | return false; | 419 | return false; |
419 | } | 420 | } |
420 | 421 | ||
422 | + @Override | ||
423 | + public void returnRoleReply(RoleState requested, RoleState reponse) { | ||
424 | + } | ||
425 | + | ||
421 | } | 426 | } |
422 | 427 | ||
423 | } | 428 | } | ... | ... |
tools/test/bin/find-node.sh
0 → 100644
1 | +#!/bin/bash | ||
2 | + | ||
3 | +validate_number () { | ||
4 | + local re="^[0-9]+$" | ||
5 | + if [[ ! $1 =~ $re ]] ; then | ||
6 | + return 1 | ||
7 | + fi | ||
8 | + | ||
9 | + return 0 | ||
10 | +} | ||
11 | + | ||
12 | +find_node () { | ||
13 | + if validate_number $1 ; then | ||
14 | + # input is a number, try to find if an OC node is defined | ||
15 | + | ||
16 | + oc_try="OC$1" | ||
17 | + node=${!oc_try} | ||
18 | + | ||
19 | + if [ -n "$node" ]; then | ||
20 | + # node lookup succeeded, return node | ||
21 | + echo $node | ||
22 | + else | ||
23 | + # node lookup failed, return original input | ||
24 | + echo $1 | ||
25 | + fi | ||
26 | + | ||
27 | + else | ||
28 | + echo $1 | ||
29 | + fi | ||
30 | + | ||
31 | + return 0 | ||
32 | +} |
... | @@ -5,8 +5,9 @@ | ... | @@ -5,8 +5,9 @@ |
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 | +. $ONOS_ROOT/tools/test/bin/find-node.sh | ||
8 | 9 | ||
9 | [ "$1" = "-w" ] && shift && onos-wait-for-start $1 | 10 | [ "$1" = "-w" ] && shift && onos-wait-for-start $1 |
10 | 11 | ||
11 | -[ -n "$1" ] && OCI=$1 && shift | 12 | +[ -n "$1" ] && OCI=$(find_node $1) && shift |
12 | client -h $OCI -u karaf "$@" 2>/dev/null | 13 | client -h $OCI -u karaf "$@" 2>/dev/null | ... | ... |
... | @@ -5,12 +5,14 @@ | ... | @@ -5,12 +5,14 @@ |
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 | +. $ONOS_ROOT/tools/test/bin/find-node.sh | ||
8 | 9 | ||
9 | less=0 | 10 | less=0 |
10 | - | ||
11 | [ "$1" = "-l" ] && shift && less=1 | 11 | [ "$1" = "-l" ] && shift && less=1 |
12 | 12 | ||
13 | -remote=$ONOS_USER@${1:-$OCI} | 13 | +remote=$(find_node $1) |
14 | + | ||
15 | +remote=$ONOS_USER@${remote:-$OCI} | ||
14 | instance=$2 | 16 | instance=$2 |
15 | 17 | ||
16 | [ -n "$instance" ] && \ | 18 | [ -n "$instance" ] && \ | ... | ... |
... | @@ -18,6 +18,8 @@ | ... | @@ -18,6 +18,8 @@ |
18 | 18 | ||
19 | package org.onlab.packet; | 19 | package org.onlab.packet; |
20 | 20 | ||
21 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
22 | + | ||
21 | import java.nio.ByteBuffer; | 23 | import java.nio.ByteBuffer; |
22 | import java.util.Arrays; | 24 | import java.util.Arrays; |
23 | import java.util.HashMap; | 25 | import java.util.HashMap; |
... | @@ -86,6 +88,17 @@ public class Ethernet extends BasePacket { | ... | @@ -86,6 +88,17 @@ public class Ethernet extends BasePacket { |
86 | * @param destMac the destination MAC to set | 88 | * @param destMac the destination MAC to set |
87 | * @return the Ethernet frame | 89 | * @return the Ethernet frame |
88 | */ | 90 | */ |
91 | + public Ethernet setDestinationMACAddress(final MacAddress destMac) { | ||
92 | + this.destinationMACAddress = checkNotNull(destMac); | ||
93 | + return this; | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * Sets the destination MAC address. | ||
98 | + * | ||
99 | + * @param destMac the destination MAC to set | ||
100 | + * @return the Ethernet frame | ||
101 | + */ | ||
89 | public Ethernet setDestinationMACAddress(final byte[] destMac) { | 102 | public Ethernet setDestinationMACAddress(final byte[] destMac) { |
90 | this.destinationMACAddress = MacAddress.valueOf(destMac); | 103 | this.destinationMACAddress = MacAddress.valueOf(destMac); |
91 | return this; | 104 | return this; |
... | @@ -126,6 +139,17 @@ public class Ethernet extends BasePacket { | ... | @@ -126,6 +139,17 @@ public class Ethernet extends BasePacket { |
126 | * @param sourceMac the source MAC to set | 139 | * @param sourceMac the source MAC to set |
127 | * @return the Ethernet frame | 140 | * @return the Ethernet frame |
128 | */ | 141 | */ |
142 | + public Ethernet setSourceMACAddress(final MacAddress sourceMac) { | ||
143 | + this.sourceMACAddress = checkNotNull(sourceMac); | ||
144 | + return this; | ||
145 | + } | ||
146 | + | ||
147 | + /** | ||
148 | + * Sets the source MAC address. | ||
149 | + * | ||
150 | + * @param sourceMac the source MAC to set | ||
151 | + * @return the Ethernet frame | ||
152 | + */ | ||
129 | public Ethernet setSourceMACAddress(final byte[] sourceMac) { | 153 | public Ethernet setSourceMACAddress(final byte[] sourceMac) { |
130 | this.sourceMACAddress = MacAddress.valueOf(sourceMac); | 154 | this.sourceMACAddress = MacAddress.valueOf(sourceMac); |
131 | return this; | 155 | return this; | ... | ... |
... | @@ -15,10 +15,18 @@ | ... | @@ -15,10 +15,18 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.packet; | 16 | package org.onlab.packet; |
17 | 17 | ||
18 | +import java.net.InetAddress; | ||
19 | +import java.net.Inet4Address; | ||
20 | +import java.net.Inet6Address; | ||
21 | +import java.net.UnknownHostException; | ||
18 | import java.nio.ByteBuffer; | 22 | import java.nio.ByteBuffer; |
19 | import java.util.Arrays; | 23 | import java.util.Arrays; |
20 | import java.util.Objects; | 24 | import java.util.Objects; |
21 | -import static com.google.common.base.Preconditions.checkNotNull; | 25 | + |
26 | +import com.google.common.net.InetAddresses; | ||
27 | +import com.google.common.primitives.UnsignedBytes; | ||
28 | + | ||
29 | +import static com.google.common.base.Preconditions.checkState; | ||
22 | 30 | ||
23 | /** | 31 | /** |
24 | * A class representing an IP address. | 32 | * A class representing an IP address. |
... | @@ -40,13 +48,74 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -40,13 +48,74 @@ public final class IpAddress implements Comparable<IpAddress> { |
40 | /** | 48 | /** |
41 | * Constructor for given IP address version and address octets. | 49 | * Constructor for given IP address version and address octets. |
42 | * | 50 | * |
51 | + * @param version the IP address version | ||
43 | * @param value the IP address value stored in network byte order | 52 | * @param value the IP address value stored in network byte order |
44 | * (i.e., the most significant byte first) | 53 | * (i.e., the most significant byte first) |
45 | - * @param value the IP address value | 54 | + * @throws IllegalArgumentException if the arguments are invalid |
46 | */ | 55 | */ |
47 | private IpAddress(Version version, byte[] value) { | 56 | private IpAddress(Version version, byte[] value) { |
57 | + checkArguments(version, value, 0); | ||
48 | this.version = version; | 58 | this.version = version; |
59 | + switch (version) { | ||
60 | + case INET: | ||
49 | this.octets = Arrays.copyOf(value, INET_BYTE_LENGTH); | 61 | this.octets = Arrays.copyOf(value, INET_BYTE_LENGTH); |
62 | + break; | ||
63 | + case INET6: | ||
64 | + this.octets = Arrays.copyOf(value, INET6_BYTE_LENGTH); | ||
65 | + break; | ||
66 | + default: | ||
67 | + // Should not be reached | ||
68 | + this.octets = null; | ||
69 | + break; | ||
70 | + } | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * Returns the IP version of this address. | ||
75 | + * | ||
76 | + * @return the version | ||
77 | + */ | ||
78 | + public Version version() { | ||
79 | + return this.version; | ||
80 | + } | ||
81 | + | ||
82 | + /** | ||
83 | + * Returns the IP address as a byte array. | ||
84 | + * | ||
85 | + * @return a byte array | ||
86 | + */ | ||
87 | + public byte[] toOctets() { | ||
88 | + return Arrays.copyOf(octets, octets.length); | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
92 | + * Returns the integral value of this IP address. | ||
93 | + * TODO: This method should be moved to Ip4Address. | ||
94 | + * | ||
95 | + * @return the IP address's value as an integer | ||
96 | + */ | ||
97 | + public int toInt() { | ||
98 | + ByteBuffer bb = ByteBuffer.wrap(octets); | ||
99 | + return bb.getInt(); | ||
100 | + } | ||
101 | + | ||
102 | + /** | ||
103 | + * Computes the IP address byte length for a given IP version. | ||
104 | + * | ||
105 | + * @param version the IP version | ||
106 | + * @return the IP address byte length for the IP version | ||
107 | + * @throws IllegalArgumentException if the IP version is invalid | ||
108 | + */ | ||
109 | + public static int byteLength(Version version) { | ||
110 | + switch (version) { | ||
111 | + case INET: | ||
112 | + return INET_BYTE_LENGTH; | ||
113 | + case INET6: | ||
114 | + return INET6_BYTE_LENGTH; | ||
115 | + default: | ||
116 | + String msg = "Invalid IP version " + version; | ||
117 | + throw new IllegalArgumentException(msg); | ||
118 | + } | ||
50 | } | 119 | } |
51 | 120 | ||
52 | /** | 121 | /** |
... | @@ -64,13 +133,14 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -64,13 +133,14 @@ public final class IpAddress implements Comparable<IpAddress> { |
64 | /** | 133 | /** |
65 | * Converts a byte array into an IP address. | 134 | * Converts a byte array into an IP address. |
66 | * | 135 | * |
136 | + * @param version the IP address version | ||
67 | * @param value the IP address value stored in network byte order | 137 | * @param value the IP address value stored in network byte order |
68 | * (i.e., the most significant byte first) | 138 | * (i.e., the most significant byte first) |
69 | * @return an IP address | 139 | * @return an IP address |
140 | + * @throws IllegalArgumentException if the arguments are invalid | ||
70 | */ | 141 | */ |
71 | - public static IpAddress valueOf(byte[] value) { | 142 | + public static IpAddress valueOf(Version version, byte[] value) { |
72 | - checkNotNull(value); | 143 | + return new IpAddress(version, value); |
73 | - return new IpAddress(Version.INET, value); | ||
74 | } | 144 | } |
75 | 145 | ||
76 | /** | 146 | /** |
... | @@ -80,96 +150,102 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -80,96 +150,102 @@ public final class IpAddress implements Comparable<IpAddress> { |
80 | * The IP address is stored in network byte order (i.e., the most | 150 | * The IP address is stored in network byte order (i.e., the most |
81 | * significant byte first). | 151 | * significant byte first). |
82 | * </p> | 152 | * </p> |
153 | + * @param version the IP address version | ||
83 | * @param value the value to use | 154 | * @param value the value to use |
84 | * @param offset the offset in bytes from the beginning of the byte array | 155 | * @param offset the offset in bytes from the beginning of the byte array |
85 | * @return an IP address | 156 | * @return an IP address |
157 | + * @throws IllegalArgumentException if the arguments are invalid | ||
86 | */ | 158 | */ |
87 | - public static IpAddress valueOf(byte[] value, int offset) { | 159 | + public static IpAddress valueOf(Version version, byte[] value, |
88 | - // Verify the arguments | 160 | + int offset) { |
89 | - if ((offset < 0) || (offset + INET_BYTE_LENGTH > value.length)) { | 161 | + checkArguments(version, value, offset); |
90 | - String msg; | ||
91 | - if (value.length < INET_BYTE_LENGTH) { | ||
92 | - msg = "Invalid IPv4 address array: array length: " + | ||
93 | - value.length + ". Must be at least " + INET_BYTE_LENGTH; | ||
94 | - } else { | ||
95 | - msg = "Invalid IPv4 address array: array offset: " + | ||
96 | - offset + ". Must be in the interval [0, " + | ||
97 | - (value.length - INET_BYTE_LENGTH) + "]"; | ||
98 | - } | ||
99 | - throw new IllegalArgumentException(msg); | ||
100 | - } | ||
101 | - | ||
102 | byte[] bc = Arrays.copyOfRange(value, offset, value.length); | 162 | byte[] bc = Arrays.copyOfRange(value, offset, value.length); |
103 | - return IpAddress.valueOf(bc); | 163 | + return IpAddress.valueOf(version, bc); |
104 | } | 164 | } |
105 | 165 | ||
106 | /** | 166 | /** |
107 | - * Converts a dotted-decimal string (x.x.x.x) into an IPv4 address. | 167 | + * Converts an InetAddress into an IP address. |
108 | * | 168 | * |
109 | - * @param address an IP address in string form, e.g. "10.0.0.1" | 169 | + * @param inetAddress the InetAddress value to use |
110 | * @return an IP address | 170 | * @return an IP address |
171 | + * @throws IllegalArgumentException if the argument is invalid | ||
111 | */ | 172 | */ |
112 | - public static IpAddress valueOf(String address) { | 173 | + public static IpAddress valueOf(InetAddress inetAddress) { |
113 | - final String[] net = address.split("\\."); | 174 | + byte[] bytes = inetAddress.getAddress(); |
114 | - if (net.length != INET_BYTE_LENGTH) { | 175 | + if (inetAddress instanceof Inet4Address) { |
115 | - String msg = "Malformed IPv4 address string: " + address + "." + | 176 | + return new IpAddress(Version.INET, bytes); |
116 | - "Address must have four decimal values separated by dots (.)"; | ||
117 | - throw new IllegalArgumentException(msg); | ||
118 | } | 177 | } |
119 | - final byte[] bytes = new byte[INET_BYTE_LENGTH]; | 178 | + if (inetAddress instanceof Inet6Address) { |
120 | - for (int i = 0; i < INET_BYTE_LENGTH; i++) { | 179 | + return new IpAddress(Version.INET6, bytes); |
121 | - bytes[i] = (byte) Short.parseShort(net[i], 10); | ||
122 | } | 180 | } |
181 | + // Use the number of bytes as a hint | ||
182 | + if (bytes.length == INET_BYTE_LENGTH) { | ||
123 | return new IpAddress(Version.INET, bytes); | 183 | return new IpAddress(Version.INET, bytes); |
124 | } | 184 | } |
125 | - | 185 | + if (bytes.length == INET6_BYTE_LENGTH) { |
126 | - /** | 186 | + return new IpAddress(Version.INET6, bytes); |
127 | - * Returns the IP version of this address. | ||
128 | - * | ||
129 | - * @return the version | ||
130 | - */ | ||
131 | - public Version version() { | ||
132 | - return this.version; | ||
133 | } | 187 | } |
134 | - | 188 | + final String msg = "Unrecognized IP version address string: " + |
135 | - /** | 189 | + inetAddress.toString(); |
136 | - * Returns the IP address as a byte array. | 190 | + throw new IllegalArgumentException(msg); |
137 | - * | ||
138 | - * @return a byte array | ||
139 | - */ | ||
140 | - public byte[] toOctets() { | ||
141 | - return Arrays.copyOf(this.octets, INET_BYTE_LENGTH); | ||
142 | } | 191 | } |
143 | 192 | ||
144 | /** | 193 | /** |
145 | - * Returns the integral value of this IP address. | 194 | + * Converts an IPv4 or IPv6 string literal (e.g., "10.2.3.4" or |
195 | + * "1111:2222::8888") into an IP address. | ||
146 | * | 196 | * |
147 | - * @return the IP address's value as an integer | 197 | + * @param value an IP address value in string form |
198 | + * @return an IP address | ||
199 | + * @throws IllegalArgumentException if the argument is invalid | ||
148 | */ | 200 | */ |
149 | - public int toInt() { | 201 | + public static IpAddress valueOf(String value) { |
150 | - ByteBuffer bb = ByteBuffer.wrap(octets); | 202 | + InetAddress inetAddress = null; |
151 | - return bb.getInt(); | 203 | + try { |
204 | + inetAddress = InetAddresses.forString(value); | ||
205 | + } catch (IllegalArgumentException e) { | ||
206 | + final String msg = "Invalid IP address string: " + value; | ||
207 | + throw new IllegalArgumentException(msg); | ||
208 | + } | ||
209 | + return valueOf(inetAddress); | ||
152 | } | 210 | } |
153 | 211 | ||
154 | /** | 212 | /** |
155 | * Creates an IP network mask prefix. | 213 | * Creates an IP network mask prefix. |
156 | * | 214 | * |
215 | + * @param version the IP address version | ||
157 | * @param prefixLength the length of the mask prefix. Must be in the | 216 | * @param prefixLength the length of the mask prefix. Must be in the |
158 | - * interval [0, 32] for IPv4 | 217 | + * interval [0, 32] for IPv4, or [0, 128] for IPv6 |
159 | * @return a new IP address that contains a mask prefix of the | 218 | * @return a new IP address that contains a mask prefix of the |
160 | * specified length | 219 | * specified length |
220 | + * @throws IllegalArgumentException if the arguments are invalid | ||
161 | */ | 221 | */ |
162 | - public static IpAddress makeMaskPrefix(int prefixLength) { | 222 | + public static IpAddress makeMaskPrefix(Version version, int prefixLength) { |
223 | + int addrByteLength = byteLength(version); | ||
224 | + int addrBitLength = addrByteLength * Byte.SIZE; | ||
225 | + | ||
163 | // Verify the prefix length | 226 | // Verify the prefix length |
164 | - if ((prefixLength < 0) || (prefixLength > INET_BIT_LENGTH)) { | 227 | + if ((prefixLength < 0) || (prefixLength > addrBitLength)) { |
165 | - final String msg = "Invalid IPv4 prefix length: " + prefixLength + | 228 | + final String msg = "Invalid IP prefix length: " + prefixLength + |
166 | - ". Must be in the interval [0, 32]."; | 229 | + ". Must be in the interval [0, " + addrBitLength + "]."; |
167 | throw new IllegalArgumentException(msg); | 230 | throw new IllegalArgumentException(msg); |
168 | } | 231 | } |
169 | 232 | ||
170 | - long v = | 233 | + // Number of bytes and extra bits that should be all 1s |
171 | - (0xffffffffL << (INET_BIT_LENGTH - prefixLength)) & 0xffffffffL; | 234 | + int maskBytes = prefixLength / Byte.SIZE; |
172 | - return IpAddress.valueOf((int) v); | 235 | + int maskBits = prefixLength % Byte.SIZE; |
236 | + byte[] mask = new byte[addrByteLength]; | ||
237 | + | ||
238 | + // Set the bytes and extra bits to 1s | ||
239 | + for (int i = 0; i < maskBytes; i++) { | ||
240 | + mask[i] = (byte) 0xff; // Set mask bytes to 1s | ||
241 | + } | ||
242 | + for (int i = maskBytes; i < addrByteLength; i++) { | ||
243 | + mask[i] = 0; // Set remaining bytes to 0s | ||
244 | + } | ||
245 | + if (maskBits > 0) { | ||
246 | + mask[maskBytes] = (byte) (0xff << (Byte.SIZE - maskBits)); | ||
247 | + } | ||
248 | + return new IpAddress(version, mask); | ||
173 | } | 249 | } |
174 | 250 | ||
175 | /** | 251 | /** |
... | @@ -178,27 +254,38 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -178,27 +254,38 @@ public final class IpAddress implements Comparable<IpAddress> { |
178 | * | 254 | * |
179 | * @param addr the address to mask | 255 | * @param addr the address to mask |
180 | * @param prefixLength the length of the mask prefix. Must be in the | 256 | * @param prefixLength the length of the mask prefix. Must be in the |
181 | - * interval [0, 32] for IPv4 | 257 | + * interval [0, 32] for IPv4, or [0, 128] for IPv6 |
182 | * @return a new IP address that is masked with a mask prefix of the | 258 | * @return a new IP address that is masked with a mask prefix of the |
183 | * specified length | 259 | * specified length |
260 | + * @throws IllegalArgumentException if the prefix length is invalid | ||
184 | */ | 261 | */ |
185 | public static IpAddress makeMaskedAddress(final IpAddress addr, | 262 | public static IpAddress makeMaskedAddress(final IpAddress addr, |
186 | int prefixLength) { | 263 | int prefixLength) { |
187 | - IpAddress mask = IpAddress.makeMaskPrefix(prefixLength); | 264 | + IpAddress mask = IpAddress.makeMaskPrefix(addr.version(), |
188 | - byte[] net = new byte[INET_BYTE_LENGTH]; | 265 | + prefixLength); |
266 | + byte[] net = new byte[mask.octets.length]; | ||
189 | 267 | ||
190 | // Mask each byte | 268 | // Mask each byte |
191 | - for (int i = 0; i < INET_BYTE_LENGTH; i++) { | 269 | + for (int i = 0; i < net.length; i++) { |
192 | net[i] = (byte) (addr.octets[i] & mask.octets[i]); | 270 | net[i] = (byte) (addr.octets[i] & mask.octets[i]); |
193 | } | 271 | } |
194 | - return IpAddress.valueOf(net); | 272 | + return IpAddress.valueOf(addr.version(), net); |
195 | } | 273 | } |
196 | 274 | ||
197 | @Override | 275 | @Override |
198 | public int compareTo(IpAddress o) { | 276 | public int compareTo(IpAddress o) { |
199 | - Long lv = ((long) this.toInt()) & 0xffffffffL; | 277 | + // Compare first the version |
200 | - Long rv = ((long) o.toInt()) & 0xffffffffL; | 278 | + if (this.version != o.version) { |
201 | - return lv.compareTo(rv); | 279 | + return this.version.compareTo(o.version); |
280 | + } | ||
281 | + | ||
282 | + // Compare the bytes, one-by-one | ||
283 | + for (int i = 0; i < this.octets.length; i++) { | ||
284 | + if (this.octets[i] != o.octets[i]) { | ||
285 | + return UnsignedBytes.compare(this.octets[i], o.octets[i]); | ||
286 | + } | ||
287 | + } | ||
288 | + return 0; // Equal | ||
202 | } | 289 | } |
203 | 290 | ||
204 | @Override | 291 | @Override |
... | @@ -222,18 +309,67 @@ public final class IpAddress implements Comparable<IpAddress> { | ... | @@ -222,18 +309,67 @@ public final class IpAddress implements Comparable<IpAddress> { |
222 | @Override | 309 | @Override |
223 | /* | 310 | /* |
224 | * (non-Javadoc) | 311 | * (non-Javadoc) |
225 | - * The format is "x.x.x.x" for IPv4 addresses. | 312 | + * The string representation of the IP address: "x.x.x.x" for IPv4 |
313 | + * addresses, or ':' separated string for IPv6 addresses. | ||
226 | * | 314 | * |
227 | * @see java.lang.Object#toString() | 315 | * @see java.lang.Object#toString() |
228 | */ | 316 | */ |
229 | public String toString() { | 317 | public String toString() { |
230 | - final StringBuilder builder = new StringBuilder(); | 318 | + InetAddress inetAddr = null; |
231 | - for (final byte b : this.octets) { | 319 | + try { |
232 | - if (builder.length() > 0) { | 320 | + inetAddr = InetAddress.getByAddress(octets); |
233 | - builder.append("."); | 321 | + } catch (UnknownHostException e) { |
322 | + // Should never happen | ||
323 | + checkState(false, "Internal error: Ip6Address.toString()"); | ||
324 | + return "[Invalid IP Address]"; | ||
325 | + } | ||
326 | + return InetAddresses.toAddrString(inetAddr); | ||
234 | } | 327 | } |
235 | - builder.append(String.format("%d", b & 0xff)); | 328 | + |
329 | + /** | ||
330 | + * Gets the IP address name for the IP address version. | ||
331 | + * | ||
332 | + * @param version the IP address version | ||
333 | + * @return the IP address name for the IP address version | ||
334 | + */ | ||
335 | + private static String addressName(Version version) { | ||
336 | + switch (version) { | ||
337 | + case INET: | ||
338 | + return "IPv4"; | ||
339 | + case INET6: | ||
340 | + return "IPv6"; | ||
341 | + default: | ||
342 | + break; | ||
343 | + } | ||
344 | + return "UnknownIP(" + version + ")"; | ||
345 | + } | ||
346 | + | ||
347 | + /** | ||
348 | + * Checks whether the arguments are valid. | ||
349 | + * | ||
350 | + * @param version the IP address version | ||
351 | + * @param value the IP address value stored in a byte array | ||
352 | + * @param offset the offset in bytes from the beginning of the byte | ||
353 | + * array with the address | ||
354 | + * @throws IllegalArgumentException if any of the arguments is invalid | ||
355 | + */ | ||
356 | + private static void checkArguments(Version version, byte[] value, | ||
357 | + int offset) { | ||
358 | + // Check the offset and byte array length | ||
359 | + int addrByteLength = byteLength(version); | ||
360 | + if ((offset < 0) || (offset + addrByteLength > value.length)) { | ||
361 | + String msg; | ||
362 | + if (value.length < addrByteLength) { | ||
363 | + msg = "Invalid " + addressName(version) + | ||
364 | + " address array: array length: " + value.length + | ||
365 | + ". Must be at least " + addrByteLength; | ||
366 | + } else { | ||
367 | + msg = "Invalid " + addressName(version) + | ||
368 | + " address array: array offset: " + offset + | ||
369 | + ". Must be in the interval [0, " + | ||
370 | + (value.length - addrByteLength) + "]"; | ||
371 | + } | ||
372 | + throw new IllegalArgumentException(msg); | ||
236 | } | 373 | } |
237 | - return builder.toString(); | ||
238 | } | 374 | } |
239 | } | 375 | } | ... | ... |
... | @@ -76,12 +76,15 @@ public final class IpPrefix { | ... | @@ -76,12 +76,15 @@ public final class IpPrefix { |
76 | /** | 76 | /** |
77 | * Converts a byte array and a prefix length into an IP prefix. | 77 | * Converts a byte array and a prefix length into an IP prefix. |
78 | * | 78 | * |
79 | + * @param version the IP address version | ||
79 | * @param address the IP address value stored in network byte order | 80 | * @param address the IP address value stored in network byte order |
80 | * @param prefixLength the prefix length | 81 | * @param prefixLength the prefix length |
81 | * @return an IP prefix | 82 | * @return an IP prefix |
82 | */ | 83 | */ |
83 | - public static IpPrefix valueOf(byte[] address, int prefixLength) { | 84 | + public static IpPrefix valueOf(IpAddress.Version version, byte[] address, |
84 | - return new IpPrefix(IpAddress.valueOf(address), prefixLength); | 85 | + int prefixLength) { |
86 | + return new IpPrefix(IpAddress.valueOf(version, address), | ||
87 | + prefixLength); | ||
85 | } | 88 | } |
86 | 89 | ||
87 | /** | 90 | /** | ... | ... |
... | @@ -25,9 +25,6 @@ public class MacAddress { | ... | @@ -25,9 +25,6 @@ public class MacAddress { |
25 | public static final MacAddress ZERO = valueOf("00:00:00:00:00:00"); | 25 | public static final MacAddress ZERO = valueOf("00:00:00:00:00:00"); |
26 | public static final MacAddress BROADCAST = valueOf("ff:ff:ff:ff:ff:ff"); | 26 | public static final MacAddress BROADCAST = valueOf("ff:ff:ff:ff:ff:ff"); |
27 | 27 | ||
28 | - public static final byte[] ZERO_MAC_ADDRESS = ZERO.getAddress(); | ||
29 | - public static final byte[] BROADCAST_MAC = BROADCAST.getAddress(); | ||
30 | - | ||
31 | private static final byte[] LL = new byte[]{ | 28 | private static final byte[] LL = new byte[]{ |
32 | 0x01, (byte) 0x80, (byte) 0xc2, 0x00, 0x00, | 29 | 0x01, (byte) 0x80, (byte) 0xc2, 0x00, 0x00, |
33 | 0x00, 0x0e, 0x03 | 30 | 0x00, 0x0e, 0x03 |
... | @@ -217,8 +214,4 @@ public class MacAddress { | ... | @@ -217,8 +214,4 @@ public class MacAddress { |
217 | } | 214 | } |
218 | return builder.toString(); | 215 | return builder.toString(); |
219 | } | 216 | } |
220 | - | ||
221 | - public byte[] getAddress() { | ||
222 | - return this.address; | ||
223 | - } | ||
224 | } | 217 | } | ... | ... |
... | @@ -64,7 +64,7 @@ public class ONOSLLDP extends LLDP { | ... | @@ -64,7 +64,7 @@ public class ONOSLLDP extends LLDP { |
64 | setName(DEFAULT_NAME); | 64 | setName(DEFAULT_NAME); |
65 | setDevice(DEFAULT_DEVICE); | 65 | setDevice(DEFAULT_DEVICE); |
66 | setOptionalTLVList(Lists.<LLDPTLV>newArrayList(nameTLV, deviceTLV)); | 66 | setOptionalTLVList(Lists.<LLDPTLV>newArrayList(nameTLV, deviceTLV)); |
67 | - setTtl(new LLDPTLV().setType((byte) TTL_TLV_TYPE) | 67 | + setTtl(new LLDPTLV().setType(TTL_TLV_TYPE) |
68 | .setLength((short) ttlValue.length) | 68 | .setLength((short) ttlValue.length) |
69 | .setValue(ttlValue)); | 69 | .setValue(ttlValue)); |
70 | 70 | ||
... | @@ -94,7 +94,7 @@ public class ONOSLLDP extends LLDP { | ... | @@ -94,7 +94,7 @@ public class ONOSLLDP extends LLDP { |
94 | public void setChassisId(final ChassisId chassisId) { | 94 | public void setChassisId(final ChassisId chassisId) { |
95 | MacAddress chassisMac = MacAddress.valueOf(chassisId.value()); | 95 | MacAddress chassisMac = MacAddress.valueOf(chassisId.value()); |
96 | byte[] chassis = ArrayUtils.addAll(new byte[] {CHASSIS_TLV_SUBTYPE}, | 96 | byte[] chassis = ArrayUtils.addAll(new byte[] {CHASSIS_TLV_SUBTYPE}, |
97 | - chassisMac.getAddress()); | 97 | + chassisMac.toBytes()); |
98 | 98 | ||
99 | LLDPTLV chassisTLV = new LLDPTLV(); | 99 | LLDPTLV chassisTLV = new LLDPTLV(); |
100 | chassisTLV.setLength(CHASSIS_TLV_SIZE); | 100 | chassisTLV.setLength(CHASSIS_TLV_SIZE); | ... | ... |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onlab.packet; | ||
17 | + | ||
18 | +import com.google.common.net.InetAddresses; | ||
19 | +import com.google.common.testing.EqualsTester; | ||
20 | +import org.junit.Test; | ||
21 | + | ||
22 | +import java.net.InetAddress; | ||
23 | + | ||
24 | +import static org.hamcrest.Matchers.is; | ||
25 | +import static org.junit.Assert.assertThat; | ||
26 | +import static org.junit.Assert.assertTrue; | ||
27 | +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable; | ||
28 | + | ||
29 | +/** | ||
30 | + * Tests for class {@link IpAddress}. | ||
31 | + */ | ||
32 | +public class IpAddressTest { | ||
33 | + /** | ||
34 | + * Tests the immutability of {@link IpAddress}. | ||
35 | + */ | ||
36 | + @Test | ||
37 | + public void testImmutable() { | ||
38 | + assertThatClassIsImmutable(IpAddress.class); | ||
39 | + } | ||
40 | + | ||
41 | + /** | ||
42 | + * Tests the length of the address in bytes (octets). | ||
43 | + */ | ||
44 | + @Test | ||
45 | + public void testAddrByteLength() { | ||
46 | + assertThat(IpAddress.INET_BYTE_LENGTH, is(4)); | ||
47 | + assertThat(IpAddress.INET6_BYTE_LENGTH, is(16)); | ||
48 | + assertThat(IpAddress.byteLength(IpAddress.Version.INET), is(4)); | ||
49 | + assertThat(IpAddress.byteLength(IpAddress.Version.INET6), is(16)); | ||
50 | + } | ||
51 | + | ||
52 | + /** | ||
53 | + * Tests the length of the address in bits. | ||
54 | + */ | ||
55 | + @Test | ||
56 | + public void testAddrBitLength() { | ||
57 | + assertThat(IpAddress.INET_BIT_LENGTH, is(32)); | ||
58 | + assertThat(IpAddress.INET6_BIT_LENGTH, is(128)); | ||
59 | + } | ||
60 | + | ||
61 | + /** | ||
62 | + * Tests returning the IP address version. | ||
63 | + */ | ||
64 | + @Test | ||
65 | + public void testVersion() { | ||
66 | + IpAddress ipAddress; | ||
67 | + | ||
68 | + // IPv4 | ||
69 | + ipAddress = IpAddress.valueOf("0.0.0.0"); | ||
70 | + assertThat(ipAddress.version(), is(IpAddress.Version.INET)); | ||
71 | + | ||
72 | + // IPv6 | ||
73 | + ipAddress = IpAddress.valueOf("::"); | ||
74 | + assertThat(ipAddress.version(), is(IpAddress.Version.INET6)); | ||
75 | + } | ||
76 | + | ||
77 | + /** | ||
78 | + * Tests returning an IPv4 address as a byte array. | ||
79 | + */ | ||
80 | + @Test | ||
81 | + public void testAddressToOctetsIPv4() { | ||
82 | + IpAddress ipAddress; | ||
83 | + | ||
84 | + final byte[] value1 = new byte[] {1, 2, 3, 4}; | ||
85 | + ipAddress = IpAddress.valueOf("1.2.3.4"); | ||
86 | + assertThat(ipAddress.toOctets(), is(value1)); | ||
87 | + | ||
88 | + final byte[] value2 = new byte[] {0, 0, 0, 0}; | ||
89 | + ipAddress = IpAddress.valueOf("0.0.0.0"); | ||
90 | + assertThat(ipAddress.toOctets(), is(value2)); | ||
91 | + | ||
92 | + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff, | ||
93 | + (byte) 0xff, (byte) 0xff}; | ||
94 | + ipAddress = IpAddress.valueOf("255.255.255.255"); | ||
95 | + assertThat(ipAddress.toOctets(), is(value3)); | ||
96 | + } | ||
97 | + | ||
98 | + /** | ||
99 | + * Tests returning an IPv6 address as a byte array. | ||
100 | + */ | ||
101 | + @Test | ||
102 | + public void testAddressToOctetsIPv6() { | ||
103 | + IpAddress ipAddress; | ||
104 | + | ||
105 | + final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22, | ||
106 | + 0x33, 0x33, 0x44, 0x44, | ||
107 | + 0x55, 0x55, 0x66, 0x66, | ||
108 | + 0x77, 0x77, | ||
109 | + (byte) 0x88, (byte) 0x88}; | ||
110 | + ipAddress = | ||
111 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"); | ||
112 | + assertThat(ipAddress.toOctets(), is(value1)); | ||
113 | + | ||
114 | + final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00, | ||
115 | + 0x00, 0x00, 0x00, 0x00, | ||
116 | + 0x00, 0x00, 0x00, 0x00, | ||
117 | + 0x00, 0x00, 0x00, 0x00}; | ||
118 | + ipAddress = IpAddress.valueOf("::"); | ||
119 | + assertThat(ipAddress.toOctets(), is(value2)); | ||
120 | + | ||
121 | + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff, | ||
122 | + (byte) 0xff, (byte) 0xff, | ||
123 | + (byte) 0xff, (byte) 0xff, | ||
124 | + (byte) 0xff, (byte) 0xff, | ||
125 | + (byte) 0xff, (byte) 0xff, | ||
126 | + (byte) 0xff, (byte) 0xff, | ||
127 | + (byte) 0xff, (byte) 0xff, | ||
128 | + (byte) 0xff, (byte) 0xff}; | ||
129 | + ipAddress = | ||
130 | + IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); | ||
131 | + assertThat(ipAddress.toOctets(), is(value3)); | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * Tests returning an IPv4 address asn an integer. | ||
136 | + */ | ||
137 | + @Test | ||
138 | + public void testToint() { | ||
139 | + IpAddress ipAddress; | ||
140 | + | ||
141 | + ipAddress = IpAddress.valueOf("1.2.3.4"); | ||
142 | + assertThat(ipAddress.toInt(), is(0x01020304)); | ||
143 | + | ||
144 | + ipAddress = IpAddress.valueOf("0.0.0.0"); | ||
145 | + assertThat(ipAddress.toInt(), is(0)); | ||
146 | + | ||
147 | + ipAddress = IpAddress.valueOf("255.255.255.255"); | ||
148 | + assertThat(ipAddress.toInt(), is(-1)); | ||
149 | + } | ||
150 | + | ||
151 | + /** | ||
152 | + * Tests valueOf() converter for an integer value. | ||
153 | + */ | ||
154 | + @Test | ||
155 | + public void testValueOfForInteger() { | ||
156 | + IpAddress ipAddress; | ||
157 | + | ||
158 | + ipAddress = IpAddress.valueOf(0x01020304); | ||
159 | + assertThat(ipAddress.toString(), is("1.2.3.4")); | ||
160 | + | ||
161 | + ipAddress = IpAddress.valueOf(0); | ||
162 | + assertThat(ipAddress.toString(), is("0.0.0.0")); | ||
163 | + | ||
164 | + ipAddress = IpAddress.valueOf(0xffffffff); | ||
165 | + assertThat(ipAddress.toString(), is("255.255.255.255")); | ||
166 | + } | ||
167 | + | ||
168 | + /** | ||
169 | + * Tests valueOf() converter for IPv4 byte array. | ||
170 | + */ | ||
171 | + @Test | ||
172 | + public void testValueOfByteArrayIPv4() { | ||
173 | + IpAddress ipAddress; | ||
174 | + | ||
175 | + final byte[] value1 = new byte[] {1, 2, 3, 4}; | ||
176 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value1); | ||
177 | + assertThat(ipAddress.toString(), is("1.2.3.4")); | ||
178 | + | ||
179 | + final byte[] value2 = new byte[] {0, 0, 0, 0}; | ||
180 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value2); | ||
181 | + assertThat(ipAddress.toString(), is("0.0.0.0")); | ||
182 | + | ||
183 | + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff, | ||
184 | + (byte) 0xff, (byte) 0xff}; | ||
185 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value3); | ||
186 | + assertThat(ipAddress.toString(), is("255.255.255.255")); | ||
187 | + } | ||
188 | + | ||
189 | + /** | ||
190 | + * Tests valueOf() converter for IPv6 byte array. | ||
191 | + */ | ||
192 | + @Test | ||
193 | + public void testValueOfByteArrayIPv6() { | ||
194 | + IpAddress ipAddress; | ||
195 | + | ||
196 | + final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22, | ||
197 | + 0x33, 0x33, 0x44, 0x44, | ||
198 | + 0x55, 0x55, 0x66, 0x66, | ||
199 | + 0x77, 0x77, | ||
200 | + (byte) 0x88, (byte) 0x88}; | ||
201 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value1); | ||
202 | + assertThat(ipAddress.toString(), | ||
203 | + is("1111:2222:3333:4444:5555:6666:7777:8888")); | ||
204 | + | ||
205 | + final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00, | ||
206 | + 0x00, 0x00, 0x00, 0x00, | ||
207 | + 0x00, 0x00, 0x00, 0x00, | ||
208 | + 0x00, 0x00, 0x00, 0x00}; | ||
209 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value2); | ||
210 | + assertThat(ipAddress.toString(), is("::")); | ||
211 | + | ||
212 | + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff, | ||
213 | + (byte) 0xff, (byte) 0xff, | ||
214 | + (byte) 0xff, (byte) 0xff, | ||
215 | + (byte) 0xff, (byte) 0xff, | ||
216 | + (byte) 0xff, (byte) 0xff, | ||
217 | + (byte) 0xff, (byte) 0xff, | ||
218 | + (byte) 0xff, (byte) 0xff, | ||
219 | + (byte) 0xff, (byte) 0xff}; | ||
220 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value3); | ||
221 | + assertThat(ipAddress.toString(), | ||
222 | + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); | ||
223 | + } | ||
224 | + | ||
225 | + /** | ||
226 | + * Tests invalid valueOf() converter for a null array for IPv4. | ||
227 | + */ | ||
228 | + @Test(expected = NullPointerException.class) | ||
229 | + public void testInvalidValueOfNullArrayIPv4() { | ||
230 | + IpAddress ipAddress; | ||
231 | + | ||
232 | + final byte[] fromArray = null; | ||
233 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, fromArray); | ||
234 | + } | ||
235 | + | ||
236 | + /** | ||
237 | + * Tests invalid valueOf() converter for a null array for IPv6. | ||
238 | + */ | ||
239 | + @Test(expected = NullPointerException.class) | ||
240 | + public void testInvalidValueOfNullArrayIPv6() { | ||
241 | + IpAddress ipAddress; | ||
242 | + | ||
243 | + final byte[] fromArray = null; | ||
244 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, fromArray); | ||
245 | + } | ||
246 | + | ||
247 | + /** | ||
248 | + * Tests invalid valueOf() converger for an array that is too short for | ||
249 | + * IPv4. | ||
250 | + */ | ||
251 | + @Test(expected = IllegalArgumentException.class) | ||
252 | + public void testInvalidValueOfShortArrayIPv4() { | ||
253 | + IpAddress ipAddress; | ||
254 | + | ||
255 | + final byte[] fromArray = new byte[] {1, 2, 3}; | ||
256 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, fromArray); | ||
257 | + } | ||
258 | + | ||
259 | + /** | ||
260 | + * Tests invalid valueOf() converger for an array that is too short for | ||
261 | + * IPv6. | ||
262 | + */ | ||
263 | + @Test(expected = IllegalArgumentException.class) | ||
264 | + public void testInvalidValueOfShortArrayIPv6() { | ||
265 | + IpAddress ipAddress; | ||
266 | + | ||
267 | + final byte[] fromArray = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9}; | ||
268 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, fromArray); | ||
269 | + } | ||
270 | + | ||
271 | + /** | ||
272 | + * Tests valueOf() converter for IPv4 byte array and an offset. | ||
273 | + */ | ||
274 | + @Test | ||
275 | + public void testValueOfByteArrayOffsetIPv4() { | ||
276 | + IpAddress ipAddress; | ||
277 | + | ||
278 | + final byte[] value1 = new byte[] {11, 22, 33, // Preamble | ||
279 | + 1, 2, 3, 4, | ||
280 | + 44, 55}; // Extra bytes | ||
281 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value1, 3); | ||
282 | + assertThat(ipAddress.toString(), is("1.2.3.4")); | ||
283 | + | ||
284 | + final byte[] value2 = new byte[] {11, 22, // Preamble | ||
285 | + 0, 0, 0, 0, | ||
286 | + 33}; // Extra bytes | ||
287 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value2, 2); | ||
288 | + assertThat(ipAddress.toString(), is("0.0.0.0")); | ||
289 | + | ||
290 | + final byte[] value3 = new byte[] {11, 22, // Preamble | ||
291 | + (byte) 0xff, (byte) 0xff, | ||
292 | + (byte) 0xff, (byte) 0xff, | ||
293 | + 33}; // Extra bytes | ||
294 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value3, 2); | ||
295 | + assertThat(ipAddress.toString(), is("255.255.255.255")); | ||
296 | + } | ||
297 | + | ||
298 | + /** | ||
299 | + * Tests valueOf() converter for IPv6 byte array and an offset. | ||
300 | + */ | ||
301 | + @Test | ||
302 | + public void testValueOfByteArrayOffsetIPv6() { | ||
303 | + IpAddress ipAddress; | ||
304 | + | ||
305 | + final byte[] value1 = new byte[] {11, 22, 33, // Preamble | ||
306 | + 0x11, 0x11, 0x22, 0x22, | ||
307 | + 0x33, 0x33, 0x44, 0x44, | ||
308 | + 0x55, 0x55, 0x66, 0x66, | ||
309 | + 0x77, 0x77, | ||
310 | + (byte) 0x88, (byte) 0x88, | ||
311 | + 44, 55}; // Extra bytes | ||
312 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value1, 3); | ||
313 | + assertThat(ipAddress.toString(), | ||
314 | + is("1111:2222:3333:4444:5555:6666:7777:8888")); | ||
315 | + | ||
316 | + final byte[] value2 = new byte[] {11, 22, // Preamble | ||
317 | + 0x00, 0x00, 0x00, 0x00, | ||
318 | + 0x00, 0x00, 0x00, 0x00, | ||
319 | + 0x00, 0x00, 0x00, 0x00, | ||
320 | + 0x00, 0x00, 0x00, 0x00, | ||
321 | + 33}; // Extra bytes | ||
322 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value2, 2); | ||
323 | + assertThat(ipAddress.toString(), is("::")); | ||
324 | + | ||
325 | + final byte[] value3 = new byte[] {11, 22, // Preamble | ||
326 | + (byte) 0xff, (byte) 0xff, | ||
327 | + (byte) 0xff, (byte) 0xff, | ||
328 | + (byte) 0xff, (byte) 0xff, | ||
329 | + (byte) 0xff, (byte) 0xff, | ||
330 | + (byte) 0xff, (byte) 0xff, | ||
331 | + (byte) 0xff, (byte) 0xff, | ||
332 | + (byte) 0xff, (byte) 0xff, | ||
333 | + (byte) 0xff, (byte) 0xff, | ||
334 | + 33}; // Extra bytes | ||
335 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value3, 2); | ||
336 | + assertThat(ipAddress.toString(), | ||
337 | + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); | ||
338 | + } | ||
339 | + | ||
340 | + /** | ||
341 | + * Tests invalid valueOf() converger for an array and an invalid offset | ||
342 | + * for IPv4. | ||
343 | + */ | ||
344 | + @Test(expected = IllegalArgumentException.class) | ||
345 | + public void testInvalidValueOfArrayInvalidOffsetIPv4() { | ||
346 | + IpAddress ipAddress; | ||
347 | + | ||
348 | + final byte[] value1 = new byte[] {11, 22, 33, // Preamble | ||
349 | + 1, 2, 3, 4, | ||
350 | + 44, 55}; // Extra bytes | ||
351 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value1, 6); | ||
352 | + } | ||
353 | + | ||
354 | + /** | ||
355 | + * Tests invalid valueOf() converger for an array and an invalid offset | ||
356 | + * for IPv6. | ||
357 | + */ | ||
358 | + @Test(expected = IllegalArgumentException.class) | ||
359 | + public void testInvalidValueOfArrayInvalidOffsetIPv6() { | ||
360 | + IpAddress ipAddress; | ||
361 | + | ||
362 | + final byte[] value1 = new byte[] {11, 22, 33, // Preamble | ||
363 | + 0x11, 0x11, 0x22, 0x22, | ||
364 | + 0x33, 0x33, 0x44, 0x44, | ||
365 | + 0x55, 0x55, 0x66, 0x66, | ||
366 | + 0x77, 0x77, | ||
367 | + (byte) 0x88, (byte) 0x88, | ||
368 | + 44, 55}; // Extra bytes | ||
369 | + ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value1, 6); | ||
370 | + } | ||
371 | + | ||
372 | + /** | ||
373 | + * Tests valueOf() converter for IPv4 InetAddress. | ||
374 | + */ | ||
375 | + @Test | ||
376 | + public void testValueOfInetAddressIPv4() { | ||
377 | + IpAddress ipAddress; | ||
378 | + InetAddress inetAddress; | ||
379 | + | ||
380 | + inetAddress = InetAddresses.forString("1.2.3.4"); | ||
381 | + ipAddress = IpAddress.valueOf(inetAddress); | ||
382 | + assertThat(ipAddress.toString(), is("1.2.3.4")); | ||
383 | + | ||
384 | + inetAddress = InetAddresses.forString("0.0.0.0"); | ||
385 | + ipAddress = IpAddress.valueOf(inetAddress); | ||
386 | + assertThat(ipAddress.toString(), is("0.0.0.0")); | ||
387 | + | ||
388 | + inetAddress = InetAddresses.forString("255.255.255.255"); | ||
389 | + ipAddress = IpAddress.valueOf(inetAddress); | ||
390 | + assertThat(ipAddress.toString(), is("255.255.255.255")); | ||
391 | + } | ||
392 | + | ||
393 | + /** | ||
394 | + * Tests valueOf() converter for IPv6 InetAddress. | ||
395 | + */ | ||
396 | + @Test | ||
397 | + public void testValueOfInetAddressIPv6() { | ||
398 | + IpAddress ipAddress; | ||
399 | + InetAddress inetAddress; | ||
400 | + | ||
401 | + inetAddress = | ||
402 | + InetAddresses.forString("1111:2222:3333:4444:5555:6666:7777:8888"); | ||
403 | + ipAddress = IpAddress.valueOf(inetAddress); | ||
404 | + assertThat(ipAddress.toString(), | ||
405 | + is("1111:2222:3333:4444:5555:6666:7777:8888")); | ||
406 | + | ||
407 | + inetAddress = InetAddresses.forString("::"); | ||
408 | + ipAddress = IpAddress.valueOf(inetAddress); | ||
409 | + assertThat(ipAddress.toString(), is("::")); | ||
410 | + | ||
411 | + inetAddress = | ||
412 | + InetAddresses.forString("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); | ||
413 | + ipAddress = IpAddress.valueOf(inetAddress); | ||
414 | + assertThat(ipAddress.toString(), | ||
415 | + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); | ||
416 | + } | ||
417 | + | ||
418 | + /** | ||
419 | + * Tests valueOf() converter for IPv4 string. | ||
420 | + */ | ||
421 | + @Test | ||
422 | + public void testValueOfStringIPv4() { | ||
423 | + IpAddress ipAddress; | ||
424 | + | ||
425 | + ipAddress = IpAddress.valueOf("1.2.3.4"); | ||
426 | + assertThat(ipAddress.toString(), is("1.2.3.4")); | ||
427 | + | ||
428 | + ipAddress = IpAddress.valueOf("0.0.0.0"); | ||
429 | + assertThat(ipAddress.toString(), is("0.0.0.0")); | ||
430 | + | ||
431 | + ipAddress = IpAddress.valueOf("255.255.255.255"); | ||
432 | + assertThat(ipAddress.toString(), is("255.255.255.255")); | ||
433 | + } | ||
434 | + | ||
435 | + /** | ||
436 | + * Tests valueOf() converter for IPv6 string. | ||
437 | + */ | ||
438 | + @Test | ||
439 | + public void testValueOfStringIPv6() { | ||
440 | + IpAddress ipAddress; | ||
441 | + | ||
442 | + ipAddress = | ||
443 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"); | ||
444 | + assertThat(ipAddress.toString(), | ||
445 | + is("1111:2222:3333:4444:5555:6666:7777:8888")); | ||
446 | + | ||
447 | + ipAddress = IpAddress.valueOf("::"); | ||
448 | + assertThat(ipAddress.toString(), is("::")); | ||
449 | + | ||
450 | + ipAddress = | ||
451 | + IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); | ||
452 | + assertThat(ipAddress.toString(), | ||
453 | + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); | ||
454 | + } | ||
455 | + | ||
456 | + /** | ||
457 | + * Tests invalid valueOf() converter for a null string. | ||
458 | + */ | ||
459 | + @Test(expected = NullPointerException.class) | ||
460 | + public void testInvalidValueOfNullString() { | ||
461 | + IpAddress ipAddress; | ||
462 | + | ||
463 | + String fromString = null; | ||
464 | + ipAddress = IpAddress.valueOf(fromString); | ||
465 | + } | ||
466 | + | ||
467 | + /** | ||
468 | + * Tests invalid valueOf() converter for an empty string. | ||
469 | + */ | ||
470 | + @Test(expected = IllegalArgumentException.class) | ||
471 | + public void testInvalidValueOfEmptyString() { | ||
472 | + IpAddress ipAddress; | ||
473 | + | ||
474 | + String fromString = ""; | ||
475 | + ipAddress = IpAddress.valueOf(fromString); | ||
476 | + } | ||
477 | + | ||
478 | + /** | ||
479 | + * Tests invalid valueOf() converter for an incorrect string. | ||
480 | + */ | ||
481 | + @Test(expected = IllegalArgumentException.class) | ||
482 | + public void testInvalidValueOfIncorrectString() { | ||
483 | + IpAddress ipAddress; | ||
484 | + | ||
485 | + String fromString = "NoSuchIpAddress"; | ||
486 | + ipAddress = IpAddress.valueOf(fromString); | ||
487 | + } | ||
488 | + | ||
489 | + /** | ||
490 | + * Tests making a mask prefix for a given prefix length for IPv4. | ||
491 | + */ | ||
492 | + @Test | ||
493 | + public void testMakeMaskPrefixIPv4() { | ||
494 | + IpAddress ipAddress; | ||
495 | + | ||
496 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 25); | ||
497 | + assertThat(ipAddress.toString(), is("255.255.255.128")); | ||
498 | + | ||
499 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 0); | ||
500 | + assertThat(ipAddress.toString(), is("0.0.0.0")); | ||
501 | + | ||
502 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 32); | ||
503 | + assertThat(ipAddress.toString(), is("255.255.255.255")); | ||
504 | + } | ||
505 | + | ||
506 | + /** | ||
507 | + * Tests making a mask prefix for a given prefix length for IPv6. | ||
508 | + */ | ||
509 | + @Test | ||
510 | + public void testMakeMaskPrefixIPv6() { | ||
511 | + IpAddress ipAddress; | ||
512 | + | ||
513 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 8); | ||
514 | + assertThat(ipAddress.toString(), is("ff00::")); | ||
515 | + | ||
516 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 120); | ||
517 | + assertThat(ipAddress.toString(), | ||
518 | + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00")); | ||
519 | + | ||
520 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 0); | ||
521 | + assertThat(ipAddress.toString(), is("::")); | ||
522 | + | ||
523 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 128); | ||
524 | + assertThat(ipAddress.toString(), | ||
525 | + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); | ||
526 | + | ||
527 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 64); | ||
528 | + assertThat(ipAddress.toString(), is("ffff:ffff:ffff:ffff::")); | ||
529 | + } | ||
530 | + | ||
531 | + /** | ||
532 | + * Tests making a mask prefix for an invalid prefix length for IPv4: | ||
533 | + * negative prefix length. | ||
534 | + */ | ||
535 | + @Test(expected = IllegalArgumentException.class) | ||
536 | + public void testInvalidMakeNegativeMaskPrefixIPv4() { | ||
537 | + IpAddress ipAddress; | ||
538 | + | ||
539 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, -1); | ||
540 | + } | ||
541 | + | ||
542 | + /** | ||
543 | + * Tests making a mask prefix for an invalid prefix length for IPv6: | ||
544 | + * negative prefix length. | ||
545 | + */ | ||
546 | + @Test(expected = IllegalArgumentException.class) | ||
547 | + public void testInvalidMakeNegativeMaskPrefixIPv6() { | ||
548 | + IpAddress ipAddress; | ||
549 | + | ||
550 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, -1); | ||
551 | + } | ||
552 | + | ||
553 | + /** | ||
554 | + * Tests making a mask prefix for an invalid prefix length for IPv4: | ||
555 | + * too long prefix length. | ||
556 | + */ | ||
557 | + @Test(expected = IllegalArgumentException.class) | ||
558 | + public void testInvalidMakeTooLongMaskPrefixIPv4() { | ||
559 | + IpAddress ipAddress; | ||
560 | + | ||
561 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 33); | ||
562 | + } | ||
563 | + | ||
564 | + /** | ||
565 | + * Tests making a mask prefix for an invalid prefix length for IPv6: | ||
566 | + * too long prefix length. | ||
567 | + */ | ||
568 | + @Test(expected = IllegalArgumentException.class) | ||
569 | + public void testInvalidMakeTooLongMaskPrefixIPv6() { | ||
570 | + IpAddress ipAddress; | ||
571 | + | ||
572 | + ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 129); | ||
573 | + } | ||
574 | + | ||
575 | + /** | ||
576 | + * Tests making of a masked address for IPv4. | ||
577 | + */ | ||
578 | + @Test | ||
579 | + public void testMakeMaskedAddressIPv4() { | ||
580 | + IpAddress ipAddress = IpAddress.valueOf("1.2.3.5"); | ||
581 | + IpAddress ipAddressMasked; | ||
582 | + | ||
583 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 24); | ||
584 | + assertThat(ipAddressMasked.toString(), is("1.2.3.0")); | ||
585 | + | ||
586 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 0); | ||
587 | + assertThat(ipAddressMasked.toString(), is("0.0.0.0")); | ||
588 | + | ||
589 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 32); | ||
590 | + assertThat(ipAddressMasked.toString(), is("1.2.3.5")); | ||
591 | + } | ||
592 | + | ||
593 | + /** | ||
594 | + * Tests making of a masked address for IPv6. | ||
595 | + */ | ||
596 | + @Test | ||
597 | + public void testMakeMaskedAddressIPv6() { | ||
598 | + IpAddress ipAddress = | ||
599 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8885"); | ||
600 | + IpAddress ipAddressMasked; | ||
601 | + | ||
602 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 8); | ||
603 | + assertThat(ipAddressMasked.toString(), is("1100::")); | ||
604 | + | ||
605 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 120); | ||
606 | + assertThat(ipAddressMasked.toString(), | ||
607 | + is("1111:2222:3333:4444:5555:6666:7777:8800")); | ||
608 | + | ||
609 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 0); | ||
610 | + assertThat(ipAddressMasked.toString(), is("::")); | ||
611 | + | ||
612 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 128); | ||
613 | + assertThat(ipAddressMasked.toString(), | ||
614 | + is("1111:2222:3333:4444:5555:6666:7777:8885")); | ||
615 | + | ||
616 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 64); | ||
617 | + assertThat(ipAddressMasked.toString(), is("1111:2222:3333:4444::")); | ||
618 | + } | ||
619 | + | ||
620 | + /** | ||
621 | + * Tests making of a masked address for invalid prefix length for IPv4: | ||
622 | + * negative prefix length. | ||
623 | + */ | ||
624 | + @Test(expected = IllegalArgumentException.class) | ||
625 | + public void testInvalidMakeNegativeMaskedAddressIPv4() { | ||
626 | + IpAddress ipAddress = IpAddress.valueOf("1.2.3.5"); | ||
627 | + IpAddress ipAddressMasked; | ||
628 | + | ||
629 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, -1); | ||
630 | + } | ||
631 | + | ||
632 | + /** | ||
633 | + * Tests making of a masked address for invalid prefix length for IPv6: | ||
634 | + * negative prefix length. | ||
635 | + */ | ||
636 | + @Test(expected = IllegalArgumentException.class) | ||
637 | + public void testInvalidMakeNegativeMaskedAddressIPv6() { | ||
638 | + IpAddress ipAddress = | ||
639 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8885"); | ||
640 | + IpAddress ipAddressMasked; | ||
641 | + | ||
642 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, -1); | ||
643 | + } | ||
644 | + | ||
645 | + /** | ||
646 | + * Tests making of a masked address for an invalid prefix length for IPv4: | ||
647 | + * too long prefix length. | ||
648 | + */ | ||
649 | + @Test(expected = IllegalArgumentException.class) | ||
650 | + public void testInvalidMakeTooLongMaskedAddressIPv4() { | ||
651 | + IpAddress ipAddress = IpAddress.valueOf("1.2.3.5"); | ||
652 | + IpAddress ipAddressMasked; | ||
653 | + | ||
654 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 33); | ||
655 | + } | ||
656 | + | ||
657 | + /** | ||
658 | + * Tests making of a masked address for an invalid prefix length for IPv6: | ||
659 | + * too long prefix length. | ||
660 | + */ | ||
661 | + @Test(expected = IllegalArgumentException.class) | ||
662 | + public void testInvalidMakeTooLongMaskedAddressIPv6() { | ||
663 | + IpAddress ipAddress = | ||
664 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8885"); | ||
665 | + IpAddress ipAddressMasked; | ||
666 | + | ||
667 | + ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 129); | ||
668 | + } | ||
669 | + | ||
670 | + /** | ||
671 | + * Tests comparison of {@link IpAddress} for IPv4. | ||
672 | + */ | ||
673 | + @Test | ||
674 | + public void testComparisonIPv4() { | ||
675 | + IpAddress addr1, addr2, addr3, addr4; | ||
676 | + | ||
677 | + addr1 = IpAddress.valueOf("1.2.3.4"); | ||
678 | + addr2 = IpAddress.valueOf("1.2.3.4"); | ||
679 | + addr3 = IpAddress.valueOf("1.2.3.3"); | ||
680 | + addr4 = IpAddress.valueOf("1.2.3.5"); | ||
681 | + assertTrue(addr1.compareTo(addr2) == 0); | ||
682 | + assertTrue(addr1.compareTo(addr3) > 0); | ||
683 | + assertTrue(addr1.compareTo(addr4) < 0); | ||
684 | + | ||
685 | + addr1 = IpAddress.valueOf("255.2.3.4"); | ||
686 | + addr2 = IpAddress.valueOf("255.2.3.4"); | ||
687 | + addr3 = IpAddress.valueOf("255.2.3.3"); | ||
688 | + addr4 = IpAddress.valueOf("255.2.3.5"); | ||
689 | + assertTrue(addr1.compareTo(addr2) == 0); | ||
690 | + assertTrue(addr1.compareTo(addr3) > 0); | ||
691 | + assertTrue(addr1.compareTo(addr4) < 0); | ||
692 | + } | ||
693 | + | ||
694 | + /** | ||
695 | + * Tests comparison of {@link IpAddress} for IPv6. | ||
696 | + */ | ||
697 | + @Test | ||
698 | + public void testComparisonIPv6() { | ||
699 | + IpAddress addr1, addr2, addr3, addr4; | ||
700 | + | ||
701 | + addr1 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"); | ||
702 | + addr2 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"); | ||
703 | + addr3 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8887"); | ||
704 | + addr4 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8889"); | ||
705 | + assertTrue(addr1.compareTo(addr2) == 0); | ||
706 | + assertTrue(addr1.compareTo(addr3) > 0); | ||
707 | + assertTrue(addr1.compareTo(addr4) < 0); | ||
708 | + | ||
709 | + addr1 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888"); | ||
710 | + addr2 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888"); | ||
711 | + addr3 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8887"); | ||
712 | + addr4 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8889"); | ||
713 | + assertTrue(addr1.compareTo(addr2) == 0); | ||
714 | + assertTrue(addr1.compareTo(addr3) > 0); | ||
715 | + assertTrue(addr1.compareTo(addr4) < 0); | ||
716 | + | ||
717 | + addr1 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888"); | ||
718 | + addr2 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888"); | ||
719 | + addr3 = IpAddress.valueOf("ffff:2222:3333:4443:5555:6666:7777:8888"); | ||
720 | + addr4 = IpAddress.valueOf("ffff:2222:3333:4445:5555:6666:7777:8888"); | ||
721 | + assertTrue(addr1.compareTo(addr2) == 0); | ||
722 | + assertTrue(addr1.compareTo(addr3) > 0); | ||
723 | + assertTrue(addr1.compareTo(addr4) < 0); | ||
724 | + } | ||
725 | + | ||
726 | + /** | ||
727 | + * Tests equality of {@link IpAddress} for IPv4. | ||
728 | + */ | ||
729 | + @Test | ||
730 | + public void testEqualityIPv4() { | ||
731 | + new EqualsTester() | ||
732 | + .addEqualityGroup(IpAddress.valueOf("1.2.3.4"), | ||
733 | + IpAddress.valueOf("1.2.3.4")) | ||
734 | + .addEqualityGroup(IpAddress.valueOf("1.2.3.5"), | ||
735 | + IpAddress.valueOf("1.2.3.5")) | ||
736 | + .addEqualityGroup(IpAddress.valueOf("0.0.0.0"), | ||
737 | + IpAddress.valueOf("0.0.0.0")) | ||
738 | + .addEqualityGroup(IpAddress.valueOf("255.255.255.255"), | ||
739 | + IpAddress.valueOf("255.255.255.255")) | ||
740 | + .testEquals(); | ||
741 | + } | ||
742 | + | ||
743 | + /** | ||
744 | + * Tests equality of {@link IpAddress} for IPv6. | ||
745 | + */ | ||
746 | + @Test | ||
747 | + public void testEqualityIPv6() { | ||
748 | + new EqualsTester() | ||
749 | + .addEqualityGroup( | ||
750 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"), | ||
751 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888")) | ||
752 | + .addEqualityGroup( | ||
753 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:888a"), | ||
754 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:888a")) | ||
755 | + .addEqualityGroup( | ||
756 | + IpAddress.valueOf("::"), | ||
757 | + IpAddress.valueOf("::")) | ||
758 | + .addEqualityGroup( | ||
759 | + IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"), | ||
760 | + IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")) | ||
761 | + .testEquals(); | ||
762 | + } | ||
763 | + | ||
764 | + /** | ||
765 | + * Tests object string representation for IPv4. | ||
766 | + */ | ||
767 | + @Test | ||
768 | + public void testToStringIPv4() { | ||
769 | + IpAddress ipAddress; | ||
770 | + | ||
771 | + ipAddress = IpAddress.valueOf("1.2.3.4"); | ||
772 | + assertThat(ipAddress.toString(), is("1.2.3.4")); | ||
773 | + | ||
774 | + ipAddress = IpAddress.valueOf("0.0.0.0"); | ||
775 | + assertThat(ipAddress.toString(), is("0.0.0.0")); | ||
776 | + | ||
777 | + ipAddress = IpAddress.valueOf("255.255.255.255"); | ||
778 | + assertThat(ipAddress.toString(), is("255.255.255.255")); | ||
779 | + } | ||
780 | + | ||
781 | + /** | ||
782 | + * Tests object string representation for IPv6. | ||
783 | + */ | ||
784 | + @Test | ||
785 | + public void testToStringIPv6() { | ||
786 | + IpAddress ipAddress; | ||
787 | + | ||
788 | + ipAddress = | ||
789 | + IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"); | ||
790 | + assertThat(ipAddress.toString(), | ||
791 | + is("1111:2222:3333:4444:5555:6666:7777:8888")); | ||
792 | + | ||
793 | + ipAddress = IpAddress.valueOf("1111::8888"); | ||
794 | + assertThat(ipAddress.toString(), is("1111::8888")); | ||
795 | + | ||
796 | + ipAddress = IpAddress.valueOf("1111::"); | ||
797 | + assertThat(ipAddress.toString(), is("1111::")); | ||
798 | + | ||
799 | + ipAddress = IpAddress.valueOf("::8888"); | ||
800 | + assertThat(ipAddress.toString(), is("::8888")); | ||
801 | + | ||
802 | + ipAddress = IpAddress.valueOf("::"); | ||
803 | + assertThat(ipAddress.toString(), is("::")); | ||
804 | + | ||
805 | + ipAddress = | ||
806 | + IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); | ||
807 | + assertThat(ipAddress.toString(), | ||
808 | + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); | ||
809 | + } | ||
810 | +} |
... | @@ -38,9 +38,11 @@ public class IpPrefixTest { | ... | @@ -38,9 +38,11 @@ public class IpPrefixTest { |
38 | 38 | ||
39 | @Test | 39 | @Test |
40 | public void testEquality() { | 40 | public void testEquality() { |
41 | - IpPrefix ip1 = IpPrefix.valueOf(BYTES1, IpPrefix.MAX_INET_MASK_LENGTH); | 41 | + IpPrefix ip1 = IpPrefix.valueOf(IpAddress.Version.INET, |
42 | + BYTES1, IpPrefix.MAX_INET_MASK_LENGTH); | ||
42 | IpPrefix ip2 = IpPrefix.valueOf(INTVAL1, IpPrefix.MAX_INET_MASK_LENGTH); | 43 | IpPrefix ip2 = IpPrefix.valueOf(INTVAL1, IpPrefix.MAX_INET_MASK_LENGTH); |
43 | - IpPrefix ip3 = IpPrefix.valueOf(BYTES2, IpPrefix.MAX_INET_MASK_LENGTH); | 44 | + IpPrefix ip3 = IpPrefix.valueOf(IpAddress.Version.INET, |
45 | + BYTES2, IpPrefix.MAX_INET_MASK_LENGTH); | ||
44 | IpPrefix ip4 = IpPrefix.valueOf(INTVAL2, IpPrefix.MAX_INET_MASK_LENGTH); | 46 | IpPrefix ip4 = IpPrefix.valueOf(INTVAL2, IpPrefix.MAX_INET_MASK_LENGTH); |
45 | IpPrefix ip5 = IpPrefix.valueOf(STRVAL); | 47 | IpPrefix ip5 = IpPrefix.valueOf(STRVAL); |
46 | 48 | ||
... | @@ -50,16 +52,19 @@ public class IpPrefixTest { | ... | @@ -50,16 +52,19 @@ public class IpPrefixTest { |
50 | .testEquals(); | 52 | .testEquals(); |
51 | 53 | ||
52 | // string conversions | 54 | // string conversions |
53 | - IpPrefix ip6 = IpPrefix.valueOf(BYTES1, MASK_LENGTH); | 55 | + IpPrefix ip6 = IpPrefix.valueOf(IpAddress.Version.INET, |
56 | + BYTES1, MASK_LENGTH); | ||
54 | IpPrefix ip7 = IpPrefix.valueOf("10.0.0.10/16"); | 57 | IpPrefix ip7 = IpPrefix.valueOf("10.0.0.10/16"); |
55 | - IpPrefix ip8 = IpPrefix.valueOf(new byte [] {0xa, 0x0, 0x0, 0xc}, 16); | 58 | + IpPrefix ip8 = IpPrefix.valueOf(IpAddress.Version.INET, |
59 | + new byte [] {0xa, 0x0, 0x0, 0xc}, 16); | ||
56 | assertEquals("incorrect address conversion", ip6, ip7); | 60 | assertEquals("incorrect address conversion", ip6, ip7); |
57 | assertEquals("incorrect address conversion", ip5, ip8); | 61 | assertEquals("incorrect address conversion", ip5, ip8); |
58 | } | 62 | } |
59 | 63 | ||
60 | @Test | 64 | @Test |
61 | public void basics() { | 65 | public void basics() { |
62 | - IpPrefix ip1 = IpPrefix.valueOf(BYTES1, MASK_LENGTH); | 66 | + IpPrefix ip1 = IpPrefix.valueOf(IpAddress.Version.INET, |
67 | + BYTES1, MASK_LENGTH); | ||
63 | final byte [] bytes = new byte [] {0xa, 0x0, 0x0, 0x0}; | 68 | final byte [] bytes = new byte [] {0xa, 0x0, 0x0, 0x0}; |
64 | 69 | ||
65 | // check fields | 70 | // check fields |
... | @@ -74,7 +79,8 @@ public class IpPrefixTest { | ... | @@ -74,7 +79,8 @@ public class IpPrefixTest { |
74 | @Test | 79 | @Test |
75 | public void netmasks() { | 80 | public void netmasks() { |
76 | // masked | 81 | // masked |
77 | - IpPrefix ip1 = IpPrefix.valueOf(BYTES1, MASK_LENGTH); | 82 | + IpPrefix ip1 = IpPrefix.valueOf(IpAddress.Version.INET, |
83 | + BYTES1, MASK_LENGTH); | ||
78 | IpPrefix ip2 = IpPrefix.valueOf("10.0.0.10/16"); | 84 | IpPrefix ip2 = IpPrefix.valueOf("10.0.0.10/16"); |
79 | IpPrefix ip3 = IpPrefix.valueOf("10.0.0.0/16"); | 85 | IpPrefix ip3 = IpPrefix.valueOf("10.0.0.0/16"); |
80 | assertEquals("incorrect binary masked address", | 86 | assertEquals("incorrect binary masked address", |
... | @@ -87,9 +93,12 @@ public class IpPrefixTest { | ... | @@ -87,9 +93,12 @@ public class IpPrefixTest { |
87 | 93 | ||
88 | @Test | 94 | @Test |
89 | public void testContainsIpPrefix() { | 95 | public void testContainsIpPrefix() { |
90 | - IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31); | 96 | + IpPrefix slash31 = IpPrefix.valueOf(IpAddress.Version.INET, |
91 | - IpPrefix slash32 = IpPrefix.valueOf(BYTES1, 32); | 97 | + BYTES1, 31); |
92 | - IpPrefix differentSlash32 = IpPrefix.valueOf(BYTES2, 32); | 98 | + IpPrefix slash32 = IpPrefix.valueOf(IpAddress.Version.INET, |
99 | + BYTES1, 32); | ||
100 | + IpPrefix differentSlash32 = IpPrefix.valueOf(IpAddress.Version.INET, | ||
101 | + BYTES2, 32); | ||
93 | 102 | ||
94 | assertTrue(slash31.contains(differentSlash32)); | 103 | assertTrue(slash31.contains(differentSlash32)); |
95 | assertFalse(differentSlash32.contains(slash31)); | 104 | assertFalse(differentSlash32.contains(slash31)); |
... | @@ -109,8 +118,9 @@ public class IpPrefixTest { | ... | @@ -109,8 +118,9 @@ public class IpPrefixTest { |
109 | 118 | ||
110 | @Test | 119 | @Test |
111 | public void testContainsIpAddress() { | 120 | public void testContainsIpAddress() { |
112 | - IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31); | 121 | + IpPrefix slash31 = IpPrefix.valueOf(IpAddress.Version.INET, |
113 | - IpAddress addr32 = IpAddress.valueOf(BYTES1); | 122 | + BYTES1, 31); |
123 | + IpAddress addr32 = IpAddress.valueOf(IpAddress.Version.INET, BYTES1); | ||
114 | 124 | ||
115 | assertTrue(slash31.contains(addr32)); | 125 | assertTrue(slash31.contains(addr32)); |
116 | 126 | ... | ... |
... | @@ -73,6 +73,7 @@ | ... | @@ -73,6 +73,7 @@ |
73 | <dependency> | 73 | <dependency> |
74 | <groupId>io.netty</groupId> | 74 | <groupId>io.netty</groupId> |
75 | <artifactId>netty-transport-native-epoll</artifactId> | 75 | <artifactId>netty-transport-native-epoll</artifactId> |
76 | + <version>${netty4.version}</version> | ||
76 | </dependency> | 77 | </dependency> |
77 | </dependencies> | 78 | </dependencies> |
78 | 79 | ... | ... |
... | @@ -244,7 +244,7 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -244,7 +244,7 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
244 | } | 244 | } |
245 | 245 | ||
246 | @Override | 246 | @Override |
247 | - public void roleChanged(Device device, MastershipRole newRole) { | 247 | + public void roleChanged(DeviceId device, MastershipRole newRole) { |
248 | } | 248 | } |
249 | 249 | ||
250 | @Override | 250 | @Override |
... | @@ -257,7 +257,7 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -257,7 +257,7 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
257 | } | 257 | } |
258 | 258 | ||
259 | @Override | 259 | @Override |
260 | - public boolean isReachable(Device device) { | 260 | + public boolean isReachable(DeviceId device) { |
261 | return false; | 261 | return false; |
262 | } | 262 | } |
263 | } | 263 | } | ... | ... |
... | @@ -101,7 +101,7 @@ public class TopologyResource extends BaseResource { | ... | @@ -101,7 +101,7 @@ public class TopologyResource extends BaseResource { |
101 | new Prop("Vendor", device.manufacturer()), | 101 | new Prop("Vendor", device.manufacturer()), |
102 | new Prop("H/W Version", device.hwVersion()), | 102 | new Prop("H/W Version", device.hwVersion()), |
103 | new Prop("S/W Version", device.swVersion()), | 103 | new Prop("S/W Version", device.swVersion()), |
104 | - new Prop("S/W Version", device.serialNumber()), | 104 | + new Prop("Serial Number", device.serialNumber()), |
105 | new Separator(), | 105 | new Separator(), |
106 | new Prop("Latitude", annot.value("latitude")), | 106 | new Prop("Latitude", annot.value("latitude")), |
107 | new Prop("Longitude", annot.value("longitude")), | 107 | new Prop("Longitude", annot.value("longitude")), | ... | ... |
-
Please register or login to post a comment