Committed by
Gerrit Code Review
Route CLI improvements and bug fixes
Change-Id: I4b4547f578cc053dc150066dadb68b6b2cbb82ee
Showing
10 changed files
with
280 additions
and
7 deletions
1 | +/* | ||
2 | + * Copyright 2016 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 | + | ||
17 | +package org.onosproject.cli.net; | ||
18 | + | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.incubator.net.routing.NextHop; | ||
22 | +import org.onosproject.incubator.net.routing.Route; | ||
23 | +import org.onosproject.incubator.net.routing.RouteService; | ||
24 | + | ||
25 | +import java.util.Collection; | ||
26 | +import java.util.Set; | ||
27 | + | ||
28 | +/** | ||
29 | + * Command to show information about routing next hops. | ||
30 | + */ | ||
31 | +@Command(scope = "onos", name = "next-hops", | ||
32 | + description = "Lists all next hops in the route store") | ||
33 | +public class NextHopsListCommand extends AbstractShellCommand { | ||
34 | + | ||
35 | + private static final String FORMAT_HEADER = | ||
36 | + " Network Next Hop"; | ||
37 | + private static final String FORMAT_ROUTE = | ||
38 | + " %-18s %-15s"; | ||
39 | + | ||
40 | + private static final String FORMAT_TABLE = "Table: %s"; | ||
41 | + private static final String FORMAT_TOTAL = " Total: %d"; | ||
42 | + | ||
43 | + private static final String FORMAT = "ip=%s, mac=%s, numRoutes=%s"; | ||
44 | + | ||
45 | + @Override | ||
46 | + protected void execute() { | ||
47 | + RouteService service = AbstractShellCommand.get(RouteService.class); | ||
48 | + | ||
49 | + Set<NextHop> nextHops = service.getNextHops(); | ||
50 | + | ||
51 | + nextHops.forEach(nextHop -> { | ||
52 | + Collection<Route> routes = service.getRoutesForNextHop(nextHop.ip()); | ||
53 | + print(FORMAT, nextHop.ip(), nextHop.mac(), routes.size()); | ||
54 | + }); | ||
55 | + | ||
56 | + } | ||
57 | + | ||
58 | +} |
... | @@ -18,6 +18,7 @@ package org.onosproject.cli.net; | ... | @@ -18,6 +18,7 @@ package org.onosproject.cli.net; |
18 | 18 | ||
19 | import org.apache.karaf.shell.commands.Argument; | 19 | import org.apache.karaf.shell.commands.Argument; |
20 | import org.apache.karaf.shell.commands.Command; | 20 | import org.apache.karaf.shell.commands.Command; |
21 | +import org.onlab.packet.IpAddress; | ||
21 | import org.onlab.packet.IpPrefix; | 22 | import org.onlab.packet.IpPrefix; |
22 | import org.onosproject.cli.AbstractShellCommand; | 23 | import org.onosproject.cli.AbstractShellCommand; |
23 | import org.onosproject.incubator.net.routing.Route; | 24 | import org.onosproject.incubator.net.routing.Route; |
... | @@ -36,13 +37,18 @@ public class RouteRemoveCommand extends AbstractShellCommand { | ... | @@ -36,13 +37,18 @@ public class RouteRemoveCommand extends AbstractShellCommand { |
36 | required = true) | 37 | required = true) |
37 | String prefixString = null; | 38 | String prefixString = null; |
38 | 39 | ||
40 | + @Argument(index = 1, name = "prefix", description = "Next hop IP address", | ||
41 | + required = true) | ||
42 | + String nextHopString = null; | ||
43 | + | ||
39 | @Override | 44 | @Override |
40 | protected void execute() { | 45 | protected void execute() { |
41 | RouteAdminService service = AbstractShellCommand.get(RouteAdminService.class); | 46 | RouteAdminService service = AbstractShellCommand.get(RouteAdminService.class); |
42 | 47 | ||
43 | IpPrefix prefix = IpPrefix.valueOf(prefixString); | 48 | IpPrefix prefix = IpPrefix.valueOf(prefixString); |
49 | + IpAddress nextHop = IpAddress.valueOf(nextHopString); | ||
44 | 50 | ||
45 | - service.withdraw(Collections.singleton(new Route(Route.Source.STATIC, prefix, null))); | 51 | + service.withdraw(Collections.singleton(new Route(Route.Source.STATIC, prefix, nextHop))); |
46 | } | 52 | } |
47 | 53 | ||
48 | } | 54 | } | ... | ... |
... | @@ -505,6 +505,9 @@ | ... | @@ -505,6 +505,9 @@ |
505 | <command> | 505 | <command> |
506 | <action class="org.onosproject.cli.net.RouteRemoveCommand"/> | 506 | <action class="org.onosproject.cli.net.RouteRemoveCommand"/> |
507 | </command> | 507 | </command> |
508 | + <command> | ||
509 | + <action class="org.onosproject.cli.net.NextHopsListCommand"/> | ||
510 | + </command> | ||
508 | 511 | ||
509 | <command> | 512 | <command> |
510 | <action class="org.onosproject.cli.net.GlobalLabelCommand"/> | 513 | <action class="org.onosproject.cli.net.GlobalLabelCommand"/> | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016 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 | + | ||
17 | +package org.onosproject.incubator.net.routing; | ||
18 | + | ||
19 | +import org.onlab.packet.IpAddress; | ||
20 | +import org.onlab.packet.MacAddress; | ||
21 | + | ||
22 | +import java.util.Objects; | ||
23 | + | ||
24 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
25 | + | ||
26 | +/** | ||
27 | + * Describes a routing next hop. | ||
28 | + */ | ||
29 | +public class NextHop { | ||
30 | + | ||
31 | + private final IpAddress ip; | ||
32 | + private final MacAddress mac; | ||
33 | + | ||
34 | + /** | ||
35 | + * Creates a new next hop. | ||
36 | + * | ||
37 | + * @param ip IP address | ||
38 | + * @param mac MAC address | ||
39 | + */ | ||
40 | + public NextHop(IpAddress ip, MacAddress mac) { | ||
41 | + this.ip = ip; | ||
42 | + this.mac = mac; | ||
43 | + } | ||
44 | + | ||
45 | + /** | ||
46 | + * Returns the IP address of the next hop. | ||
47 | + * | ||
48 | + * @return IP address | ||
49 | + */ | ||
50 | + public IpAddress ip() { | ||
51 | + return ip; | ||
52 | + } | ||
53 | + | ||
54 | + /** | ||
55 | + * Returns the MAC address of the next hop. | ||
56 | + * | ||
57 | + * @return MAC address | ||
58 | + */ | ||
59 | + public MacAddress mac() { | ||
60 | + return mac; | ||
61 | + } | ||
62 | + | ||
63 | + @Override | ||
64 | + public int hashCode() { | ||
65 | + return Objects.hash(ip, mac); | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public boolean equals(Object other) { | ||
70 | + if (this == other) { | ||
71 | + return true; | ||
72 | + } | ||
73 | + | ||
74 | + if (!(other instanceof NextHop)) { | ||
75 | + return false; | ||
76 | + } | ||
77 | + | ||
78 | + NextHop that = (NextHop) other; | ||
79 | + | ||
80 | + return Objects.equals(this.ip, that.mac) && | ||
81 | + Objects.equals(this.ip, that.mac); | ||
82 | + } | ||
83 | + | ||
84 | + @Override | ||
85 | + public String toString() { | ||
86 | + return toStringHelper(this) | ||
87 | + .add("ip", ip) | ||
88 | + .add("mac", mac) | ||
89 | + .toString(); | ||
90 | + } | ||
91 | +} |
... | @@ -20,6 +20,8 @@ import org.onlab.packet.IpAddress; | ... | @@ -20,6 +20,8 @@ import org.onlab.packet.IpAddress; |
20 | import org.onlab.packet.IpPrefix; | 20 | import org.onlab.packet.IpPrefix; |
21 | import org.onlab.packet.MacAddress; | 21 | import org.onlab.packet.MacAddress; |
22 | 22 | ||
23 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
24 | + | ||
23 | /** | 25 | /** |
24 | * Represents a route with the next hop MAC address resolved. | 26 | * Represents a route with the next hop MAC address resolved. |
25 | */ | 27 | */ |
... | @@ -80,4 +82,13 @@ public class ResolvedRoute { | ... | @@ -80,4 +82,13 @@ public class ResolvedRoute { |
80 | public MacAddress nextHopMac() { | 82 | public MacAddress nextHopMac() { |
81 | return nextHopMac; | 83 | return nextHopMac; |
82 | } | 84 | } |
85 | + | ||
86 | + @Override | ||
87 | + public String toString() { | ||
88 | + return toStringHelper(this) | ||
89 | + .add("prefix", prefix) | ||
90 | + .add("nextHop", nextHop) | ||
91 | + .add("nextHopMac", nextHopMac) | ||
92 | + .toString(); | ||
93 | + } | ||
83 | } | 94 | } | ... | ... |
... | @@ -21,6 +21,7 @@ import org.onlab.packet.IpPrefix; | ... | @@ -21,6 +21,7 @@ import org.onlab.packet.IpPrefix; |
21 | 21 | ||
22 | import java.util.Objects; | 22 | import java.util.Objects; |
23 | 23 | ||
24 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
24 | import static com.google.common.base.Preconditions.checkArgument; | 25 | import static com.google.common.base.Preconditions.checkArgument; |
25 | import static com.google.common.base.Preconditions.checkNotNull; | 26 | import static com.google.common.base.Preconditions.checkNotNull; |
26 | 27 | ||
... | @@ -70,7 +71,8 @@ public class Route { | ... | @@ -70,7 +71,8 @@ public class Route { |
70 | */ | 71 | */ |
71 | public Route(Source source, IpPrefix prefix, IpAddress nextHop) { | 72 | public Route(Source source, IpPrefix prefix, IpAddress nextHop) { |
72 | checkNotNull(prefix); | 73 | checkNotNull(prefix); |
73 | - checkArgument(nextHop == null || prefix.version().equals(nextHop.version()), VERSION_MISMATCH); | 74 | + checkNotNull(nextHop); |
75 | + checkArgument(prefix.version().equals(nextHop.version()), VERSION_MISMATCH); | ||
74 | 76 | ||
75 | this.source = checkNotNull(source); | 77 | this.source = checkNotNull(source); |
76 | this.prefix = prefix; | 78 | this.prefix = prefix; |
... | @@ -124,4 +126,12 @@ public class Route { | ... | @@ -124,4 +126,12 @@ public class Route { |
124 | return Objects.equals(this.prefix, that.prefix) && | 126 | return Objects.equals(this.prefix, that.prefix) && |
125 | Objects.equals(this.nextHop, that.nextHop); | 127 | Objects.equals(this.nextHop, that.nextHop); |
126 | } | 128 | } |
129 | + | ||
130 | + @Override | ||
131 | + public String toString() { | ||
132 | + return toStringHelper(this) | ||
133 | + .add("prefix", prefix) | ||
134 | + .add("nextHop", nextHop) | ||
135 | + .toString(); | ||
136 | + } | ||
127 | } | 137 | } | ... | ... |
... | @@ -21,6 +21,7 @@ import org.onosproject.event.ListenerService; | ... | @@ -21,6 +21,7 @@ import org.onosproject.event.ListenerService; |
21 | 21 | ||
22 | import java.util.Collection; | 22 | import java.util.Collection; |
23 | import java.util.Map; | 23 | import java.util.Map; |
24 | +import java.util.Set; | ||
24 | 25 | ||
25 | /** | 26 | /** |
26 | * Unicast IP route service. | 27 | * Unicast IP route service. |
... | @@ -44,4 +45,19 @@ public interface RouteService extends ListenerService<RouteEvent, RouteListener> | ... | @@ -44,4 +45,19 @@ public interface RouteService extends ListenerService<RouteEvent, RouteListener> |
44 | */ | 45 | */ |
45 | Route longestPrefixMatch(IpAddress ip); | 46 | Route longestPrefixMatch(IpAddress ip); |
46 | 47 | ||
48 | + /** | ||
49 | + * Returns the routes for the given next hop. | ||
50 | + * | ||
51 | + * @param nextHop next hop IP address | ||
52 | + * @return routes for this next hop | ||
53 | + */ | ||
54 | + Collection<Route> getRoutesForNextHop(IpAddress nextHop); | ||
55 | + | ||
56 | + /** | ||
57 | + * Returns all next hops in the route store. | ||
58 | + * | ||
59 | + * @return set of next hops | ||
60 | + */ | ||
61 | + Set<NextHop> getNextHops(); | ||
62 | + | ||
47 | } | 63 | } | ... | ... |
... | @@ -21,6 +21,7 @@ import org.onlab.packet.MacAddress; | ... | @@ -21,6 +21,7 @@ import org.onlab.packet.MacAddress; |
21 | import org.onosproject.store.Store; | 21 | import org.onosproject.store.Store; |
22 | 22 | ||
23 | import java.util.Collection; | 23 | import java.util.Collection; |
24 | +import java.util.Map; | ||
24 | import java.util.Set; | 25 | import java.util.Set; |
25 | 26 | ||
26 | /** | 27 | /** |
... | @@ -66,6 +67,14 @@ public interface RouteStore extends Store<RouteEvent, RouteStoreDelegate> { | ... | @@ -66,6 +67,14 @@ public interface RouteStore extends Store<RouteEvent, RouteStoreDelegate> { |
66 | Route longestPrefixMatch(IpAddress ip); | 67 | Route longestPrefixMatch(IpAddress ip); |
67 | 68 | ||
68 | /** | 69 | /** |
70 | + * Returns the routes that point to the given next hop IP address. | ||
71 | + * | ||
72 | + * @param ip IP address of the next hop | ||
73 | + * @return routes for the given next hop | ||
74 | + */ | ||
75 | + Collection<Route> getRoutesForNextHop(IpAddress ip); | ||
76 | + | ||
77 | + /** | ||
69 | * Updates a next hop IP and MAC in the store. | 78 | * Updates a next hop IP and MAC in the store. |
70 | * | 79 | * |
71 | * @param ip IP address | 80 | * @param ip IP address |
... | @@ -88,4 +97,11 @@ public interface RouteStore extends Store<RouteEvent, RouteStoreDelegate> { | ... | @@ -88,4 +97,11 @@ public interface RouteStore extends Store<RouteEvent, RouteStoreDelegate> { |
88 | * @return MAC address | 97 | * @return MAC address |
89 | */ | 98 | */ |
90 | MacAddress getNextHop(IpAddress ip); | 99 | MacAddress getNextHop(IpAddress ip); |
100 | + | ||
101 | + /** | ||
102 | + * Returns all next hops in the route store. | ||
103 | + * | ||
104 | + * @return next hops | ||
105 | + */ | ||
106 | + Map<IpAddress, MacAddress> getNextHops(); | ||
91 | } | 107 | } | ... | ... |
... | @@ -25,6 +25,7 @@ import org.apache.felix.scr.annotations.Service; | ... | @@ -25,6 +25,7 @@ import org.apache.felix.scr.annotations.Service; |
25 | import org.onlab.packet.IpAddress; | 25 | import org.onlab.packet.IpAddress; |
26 | import org.onlab.packet.MacAddress; | 26 | import org.onlab.packet.MacAddress; |
27 | import org.onosproject.event.ListenerService; | 27 | import org.onosproject.event.ListenerService; |
28 | +import org.onosproject.incubator.net.routing.NextHop; | ||
28 | import org.onosproject.incubator.net.routing.ResolvedRoute; | 29 | import org.onosproject.incubator.net.routing.ResolvedRoute; |
29 | import org.onosproject.incubator.net.routing.Route; | 30 | import org.onosproject.incubator.net.routing.Route; |
30 | import org.onosproject.incubator.net.routing.RouteAdminService; | 31 | import org.onosproject.incubator.net.routing.RouteAdminService; |
... | @@ -146,6 +147,7 @@ public class RouteManager implements ListenerService<RouteEvent, RouteListener>, | ... | @@ -146,6 +147,7 @@ public class RouteManager implements ListenerService<RouteEvent, RouteListener>, |
146 | * @param event event | 147 | * @param event event |
147 | */ | 148 | */ |
148 | private void post(RouteEvent event) { | 149 | private void post(RouteEvent event) { |
150 | + log.debug("Sending event {}", event); | ||
149 | synchronized (this) { | 151 | synchronized (this) { |
150 | listeners.values().forEach(l -> l.post(event)); | 152 | listeners.values().forEach(l -> l.post(event)); |
151 | } | 153 | } |
... | @@ -165,9 +167,22 @@ public class RouteManager implements ListenerService<RouteEvent, RouteListener>, | ... | @@ -165,9 +167,22 @@ public class RouteManager implements ListenerService<RouteEvent, RouteListener>, |
165 | } | 167 | } |
166 | 168 | ||
167 | @Override | 169 | @Override |
170 | + public Collection<Route> getRoutesForNextHop(IpAddress nextHop) { | ||
171 | + return routeStore.getRoutesForNextHop(nextHop); | ||
172 | + } | ||
173 | + | ||
174 | + @Override | ||
175 | + public Set<NextHop> getNextHops() { | ||
176 | + return routeStore.getNextHops().entrySet().stream() | ||
177 | + .map(entry -> new NextHop(entry.getKey(), entry.getValue())) | ||
178 | + .collect(Collectors.toSet()); | ||
179 | + } | ||
180 | + | ||
181 | + @Override | ||
168 | public void update(Collection<Route> routes) { | 182 | public void update(Collection<Route> routes) { |
169 | synchronized (this) { | 183 | synchronized (this) { |
170 | routes.forEach(route -> { | 184 | routes.forEach(route -> { |
185 | + log.debug("Received update {}", route); | ||
171 | routeStore.updateRoute(route); | 186 | routeStore.updateRoute(route); |
172 | resolve(route); | 187 | resolve(route); |
173 | }); | 188 | }); |
... | @@ -177,7 +192,10 @@ public class RouteManager implements ListenerService<RouteEvent, RouteListener>, | ... | @@ -177,7 +192,10 @@ public class RouteManager implements ListenerService<RouteEvent, RouteListener>, |
177 | @Override | 192 | @Override |
178 | public void withdraw(Collection<Route> routes) { | 193 | public void withdraw(Collection<Route> routes) { |
179 | synchronized (this) { | 194 | synchronized (this) { |
180 | - routes.forEach(route -> routeStore.removeRoute(route)); | 195 | + routes.forEach(route -> { |
196 | + log.debug("Received withdraw {}", routes); | ||
197 | + routeStore.removeRoute(route); | ||
198 | + }); | ||
181 | } | 199 | } |
182 | } | 200 | } |
183 | 201 | ... | ... |
... | @@ -17,8 +17,10 @@ | ... | @@ -17,8 +17,10 @@ |
17 | package org.onosproject.incubator.store.routing.impl; | 17 | package org.onosproject.incubator.store.routing.impl; |
18 | 18 | ||
19 | import com.google.common.collect.HashMultimap; | 19 | import com.google.common.collect.HashMultimap; |
20 | +import com.google.common.collect.ImmutableMap; | ||
20 | import com.google.common.collect.Multimap; | 21 | import com.google.common.collect.Multimap; |
21 | import com.google.common.collect.Multimaps; | 22 | import com.google.common.collect.Multimaps; |
23 | +import com.googlecode.concurrenttrees.common.KeyValuePair; | ||
22 | import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory; | 24 | import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory; |
23 | import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree; | 25 | import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree; |
24 | import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree; | 26 | import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree; |
... | @@ -35,10 +37,14 @@ import org.onosproject.incubator.net.routing.RouteStore; | ... | @@ -35,10 +37,14 @@ import org.onosproject.incubator.net.routing.RouteStore; |
35 | import org.onosproject.incubator.net.routing.RouteStoreDelegate; | 37 | import org.onosproject.incubator.net.routing.RouteStoreDelegate; |
36 | import org.onosproject.incubator.net.routing.RouteTableId; | 38 | import org.onosproject.incubator.net.routing.RouteTableId; |
37 | import org.onosproject.store.AbstractStore; | 39 | import org.onosproject.store.AbstractStore; |
40 | +import org.slf4j.Logger; | ||
41 | +import org.slf4j.LoggerFactory; | ||
38 | 42 | ||
39 | import java.util.Collection; | 43 | import java.util.Collection; |
40 | import java.util.Collections; | 44 | import java.util.Collections; |
41 | import java.util.Iterator; | 45 | import java.util.Iterator; |
46 | +import java.util.LinkedList; | ||
47 | +import java.util.List; | ||
42 | import java.util.Map; | 48 | import java.util.Map; |
43 | import java.util.Set; | 49 | import java.util.Set; |
44 | import java.util.concurrent.ConcurrentHashMap; | 50 | import java.util.concurrent.ConcurrentHashMap; |
... | @@ -51,6 +57,8 @@ import java.util.concurrent.ConcurrentHashMap; | ... | @@ -51,6 +57,8 @@ import java.util.concurrent.ConcurrentHashMap; |
51 | public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegate> | 57 | public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegate> |
52 | implements RouteStore { | 58 | implements RouteStore { |
53 | 59 | ||
60 | + private Logger log = LoggerFactory.getLogger(getClass()); | ||
61 | + | ||
54 | private Map<RouteTableId, RouteTable> routeTables; | 62 | private Map<RouteTableId, RouteTable> routeTables; |
55 | private static final RouteTableId IPV4 = new RouteTableId("ipv4"); | 63 | private static final RouteTableId IPV4 = new RouteTableId("ipv4"); |
56 | private static final RouteTableId IPV6 = new RouteTableId("ipv6"); | 64 | private static final RouteTableId IPV6 = new RouteTableId("ipv6"); |
... | @@ -74,7 +82,9 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -74,7 +82,9 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
74 | public void removeRoute(Route route) { | 82 | public void removeRoute(Route route) { |
75 | RouteTable table = getDefaultRouteTable(route); | 83 | RouteTable table = getDefaultRouteTable(route); |
76 | table.remove(route); | 84 | table.remove(route); |
77 | - if (table.getRoutesForNextHop(route.nextHop()).isEmpty()) { | 85 | + Collection<Route> routes = table.getRoutesForNextHop(route.nextHop()); |
86 | + | ||
87 | + if (routes.isEmpty()) { | ||
78 | nextHops.remove(route.nextHop()); | 88 | nextHops.remove(route.nextHop()); |
79 | } | 89 | } |
80 | } | 90 | } |
... | @@ -99,8 +109,14 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -99,8 +109,14 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
99 | } | 109 | } |
100 | 110 | ||
101 | @Override | 111 | @Override |
112 | + public Collection<Route> getRoutesForNextHop(IpAddress ip) { | ||
113 | + return getDefaultRouteTable(ip).getRoutesForNextHop(ip); | ||
114 | + } | ||
115 | + | ||
116 | + @Override | ||
102 | public void updateNextHop(IpAddress ip, MacAddress mac) { | 117 | public void updateNextHop(IpAddress ip, MacAddress mac) { |
103 | Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip); | 118 | Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip); |
119 | + | ||
104 | if (!routes.isEmpty() && !mac.equals(nextHops.get(ip))) { | 120 | if (!routes.isEmpty() && !mac.equals(nextHops.get(ip))) { |
105 | nextHops.put(ip, mac); | 121 | nextHops.put(ip, mac); |
106 | 122 | ||
... | @@ -125,6 +141,11 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -125,6 +141,11 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
125 | return nextHops.get(ip); | 141 | return nextHops.get(ip); |
126 | } | 142 | } |
127 | 143 | ||
144 | + @Override | ||
145 | + public Map<IpAddress, MacAddress> getNextHops() { | ||
146 | + return ImmutableMap.copyOf(nextHops); | ||
147 | + } | ||
148 | + | ||
128 | private RouteTable getDefaultRouteTable(Route route) { | 149 | private RouteTable getDefaultRouteTable(Route route) { |
129 | return getDefaultRouteTable(route.prefix().address()); | 150 | return getDefaultRouteTable(route.prefix().address()); |
130 | } | 151 | } |
... | @@ -179,14 +200,27 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -179,14 +200,27 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
179 | routeTable.put(createBinaryString(route.prefix()), route); | 200 | routeTable.put(createBinaryString(route.prefix()), route); |
180 | 201 | ||
181 | // TODO manage routes from multiple providers | 202 | // TODO manage routes from multiple providers |
182 | - reverseIndex.remove(route.nextHop(), oldRoute); | 203 | + |
183 | reverseIndex.put(route.nextHop(), route); | 204 | reverseIndex.put(route.nextHop(), route); |
184 | 205 | ||
206 | + if (oldRoute != null) { | ||
207 | + reverseIndex.remove(oldRoute.nextHop(), oldRoute); | ||
208 | + | ||
209 | + if (reverseIndex.get(oldRoute.nextHop()).isEmpty()) { | ||
210 | + nextHops.remove(oldRoute.nextHop()); | ||
211 | + } | ||
212 | + } | ||
213 | + | ||
185 | if (oldRoute != null && !oldRoute.nextHop().equals(route.nextHop())) { | 214 | if (oldRoute != null && !oldRoute.nextHop().equals(route.nextHop())) { |
186 | // Remove old route because new one is different | 215 | // Remove old route because new one is different |
187 | // TODO ROUTE_UPDATED? | 216 | // TODO ROUTE_UPDATED? |
188 | notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(oldRoute, null))); | 217 | notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(oldRoute, null))); |
189 | } | 218 | } |
219 | + | ||
220 | + MacAddress nextHopMac = nextHops.get(route.nextHop()); | ||
221 | + if (nextHopMac != null) { | ||
222 | + notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, new ResolvedRoute(route, nextHopMac))); | ||
223 | + } | ||
190 | } | 224 | } |
191 | } | 225 | } |
192 | 226 | ||
... | @@ -199,9 +233,9 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -199,9 +233,9 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
199 | synchronized (this) { | 233 | synchronized (this) { |
200 | Route removed = routes.remove(route.prefix()); | 234 | Route removed = routes.remove(route.prefix()); |
201 | routeTable.remove(createBinaryString(route.prefix())); | 235 | routeTable.remove(createBinaryString(route.prefix())); |
202 | - reverseIndex.remove(route.nextHop(), route); | ||
203 | 236 | ||
204 | if (removed != null) { | 237 | if (removed != null) { |
238 | + reverseIndex.remove(removed.nextHop(), removed); | ||
205 | notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(route, null))); | 239 | notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(route, null))); |
206 | } | 240 | } |
207 | } | 241 | } |
... | @@ -223,7 +257,17 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat | ... | @@ -223,7 +257,17 @@ public class LocalRouteStore extends AbstractStore<RouteEvent, RouteStoreDelegat |
223 | * @return all routes | 257 | * @return all routes |
224 | */ | 258 | */ |
225 | public Collection<Route> getRoutes() { | 259 | public Collection<Route> getRoutes() { |
226 | - return routes.values(); | 260 | + Iterator<KeyValuePair<Route>> it = |
261 | + routeTable.getKeyValuePairsForKeysStartingWith("").iterator(); | ||
262 | + | ||
263 | + List<Route> routes = new LinkedList<>(); | ||
264 | + | ||
265 | + while (it.hasNext()) { | ||
266 | + KeyValuePair<Route> entry = it.next(); | ||
267 | + routes.add(entry.getValue()); | ||
268 | + } | ||
269 | + | ||
270 | + return routes; | ||
227 | } | 271 | } |
228 | 272 | ||
229 | /** | 273 | /** | ... | ... |
-
Please register or login to post a comment