[GEANT] Adaptation to routing API deprecation
Change-Id: I7d5cfac89a4ac5c82dc079b0c2240abadc3bbcba
diff --git a/sdx-l3/pom.xml b/sdx-l3/pom.xml
index 694c128..413b82b 100644
--- a/sdx-l3/pom.xml
+++ b/sdx-l3/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- ~ Copyright 2016-present Open Networking Laboratory
+ ~ Copyright 2016 - present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -54,6 +54,14 @@
<dependency>
<groupId>org.onosproject</groupId>
+ <artifactId>onos-incubator-api</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <classifier>tests</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
<artifactId>onos-app-routing</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3Fib.java b/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3Fib.java
index 2a64240..af22d6a 100644
--- a/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3Fib.java
+++ b/sdx-l3/src/main/java/org/onosproject/sdxl3/SdxL3Fib.java
@@ -17,6 +17,7 @@
package org.onosproject.sdxl3;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -30,7 +31,13 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceEvent;
+import org.onosproject.incubator.net.intf.InterfaceListener;
import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.incubator.net.routing.ResolvedRoute;
+import org.onosproject.incubator.net.routing.RouteEvent;
+import org.onosproject.incubator.net.routing.RouteListener;
+import org.onosproject.incubator.net.routing.RouteService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -40,21 +47,15 @@
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.constraint.PartialFailureConstraint;
-import org.onosproject.routing.FibListener;
-import org.onosproject.routing.FibUpdate;
import org.onosproject.routing.IntentSynchronizationService;
-import org.onosproject.routing.RoutingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import static com.google.common.base.Preconditions.checkArgument;
-
/**
* FIB component of SDX-L3.
*/
@@ -72,12 +73,13 @@
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected RoutingService routingService;
+ protected RouteService routeService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected SdxL3PeerService peerService;
- private final InternalFibListener fibListener = new InternalFibListener();
+ private final InternalRouteListener routeListener = new InternalRouteListener();
+ private final InternalInterfaceListener interfaceListener = new InternalInterfaceListener();
private static final int PRIORITY_OFFSET = 100;
private static final int PRIORITY_MULTIPLIER = 5;
@@ -93,68 +95,43 @@
public void activate() {
appId = coreService.getAppId(SdxL3.SDX_L3_APP);
- routingService.addFibListener(fibListener);
- routingService.start();
+ interfaceService.addListener(interfaceListener);
+
+ routeService.addListener(routeListener);
}
@Deactivate
public void deactivate() {
- // TODO remove listener
- routingService.stop();
+ interfaceService.removeListener(interfaceListener);
+ routeService.removeListener(routeListener);
}
- private void update(Collection<FibUpdate> updates, Collection<FibUpdate> withdraws) {
- int submitCount = 0, withdrawCount = 0;
- //
- // NOTE: Semantically, we MUST withdraw existing intents before
- // submitting new intents.
- //
+ private void update(ResolvedRoute route) {
synchronized (this) {
- MultiPointToSinglePointIntent intent;
+ IpPrefix prefix = route.prefix();
+ MultiPointToSinglePointIntent intent =
+ generateRouteIntent(prefix, route.nextHop(), route.nextHopMac());
- //
- // Prepare the Intent batch operations for the intents to withdraw
- //
- for (FibUpdate withdraw : withdraws) {
- checkArgument(withdraw.type() == FibUpdate.Type.DELETE,
- "FibUpdate with wrong type in withdraws list");
-
- IpPrefix prefix = withdraw.entry().prefix();
- intent = routeIntents.remove(prefix);
- if (intent == null) {
- log.trace("SDX-L3 No intent in routeIntents to delete " +
- "for prefix: {}", prefix);
- continue;
- }
- intentSynchronizer.withdraw(intent);
- withdrawCount++;
+ if (intent == null) {
+ log.debug("SDX-L3 no interface found for route {}", route);
+ return;
}
- //
- // Prepare the Intent batch operations for the intents to submit
- //
- for (FibUpdate update : updates) {
- checkArgument(update.type() == FibUpdate.Type.UPDATE,
- "FibUpdate with wrong type in updates list");
+ routeIntents.put(prefix, intent);
+ intentSynchronizer.submit(intent);
+ }
+ }
- IpPrefix prefix = update.entry().prefix();
- intent = generateRouteIntent(prefix, update.entry().nextHopIp(),
- update.entry().nextHopMac());
-
- if (intent == null) {
- // This preserves the old semantics - if an intent can't be
- // generated, we don't do anything with that prefix. But
- // perhaps we should withdraw the old intent anyway?
- continue;
- }
-
- routeIntents.put(prefix, intent);
- intentSynchronizer.submit(intent);
- submitCount++;
+ private void withdraw(ResolvedRoute route) {
+ synchronized (this) {
+ IpPrefix prefix = route.prefix();
+ MultiPointToSinglePointIntent intent = routeIntents.remove(prefix);
+ if (intent == null) {
+ log.trace("SDX-L3 no intent in routeIntents to delete " +
+ "for prefix: {}", prefix);
+ return;
}
-
- log.debug("SDX-L3 submitted {}/{}, withdrew = {}/{}", submitCount,
- updates.size(), withdrawCount, withdraws.size());
+ intentSynchronizer.withdraw(intent);
}
}
@@ -181,26 +158,41 @@
if (egressInterface == null) {
log.warn("No outgoing interface found for {}",
- nextHopIpAddress);
+ nextHopIpAddress);
return null;
}
-
- // Generate the intent itself
- Set<ConnectPoint> ingressPorts = new HashSet<>();
ConnectPoint egressPort = egressInterface.connectPoint();
- log.debug("Generating intent for prefix {}, next hop mac {}",
- prefix, nextHopMacAddress);
- for (Interface intf : interfaceService.getInterfaces()) {
- // TODO this should be only peering interfaces
- if (!intf.connectPoint().equals(egressInterface.connectPoint())) {
- ConnectPoint srcPort = intf.connectPoint();
- ingressPorts.add(srcPort);
+ Set<Interface> ingressInterfaces = new HashSet<>();
+ Set<ConnectPoint> ingressPorts = new HashSet<>();
+ log.debug("Generating intent for prefix {}, next hop mac {}",
+ prefix, nextHopMacAddress);
+
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+
+ // Get ingress interfaces and ports
+ // TODO this should be only peering interfaces
+ interfaceService.getInterfaces().stream()
+ .filter(intf -> !intf.equals(egressInterface))
+ .forEach(intf -> {
+ ingressInterfaces.add(intf);
+ ConnectPoint ingressPort = intf.connectPoint();
+ ingressPorts.add(ingressPort);
+ });
+
+ // By default the ingress traffic is not tagged
+ VlanId ingressVlanId = VlanId.NONE;
+
+ // Match VLAN Id ANY if the source VLAN Id is not null
+ // TODO need to be able to set a different VLAN Id per ingress interface
+ for (Interface intf : ingressInterfaces) {
+ if (!intf.vlan().equals(VlanId.NONE)) {
+ selector.matchVlanId(VlanId.ANY);
+ ingressVlanId = intf.vlan();
}
}
// Match the destination IP prefix at the first hop
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
if (prefix.isIp4()) {
selector.matchEthType(Ethernet.TYPE_IPV4);
// if it is default route, then we do not need match destination
@@ -215,22 +207,29 @@
if (prefix.prefixLength() != 0) {
selector.matchIPv6Dst(prefix);
}
-
}
// Rewrite the destination MAC address
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder()
.setEthDst(nextHopMacAddress);
- if (!egressInterface.vlan().equals(VlanId.NONE)) {
- treatment.setVlanId(egressInterface.vlan());
- // If we set VLAN ID, we have to make sure a VLAN tag exists.
- // TODO support no VLAN -> VLAN routing
- selector.matchVlanId(VlanId.ANY);
+
+ // Set egress VLAN Id
+ // TODO need to make the comparison with different ingress VLAN Ids
+ if (!ingressVlanId.equals(egressInterface.vlan())) {
+ if (egressInterface.vlan().equals(VlanId.NONE)) {
+ treatment.popVlan();
+ } else {
+ treatment.setVlanId(egressInterface.vlan());
+ }
}
+ // Set priority
int priority =
prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
+
+ // Set key
Key key = Key.of(prefix.toString(), appId);
+
return MultiPointToSinglePointIntent.builder()
.appId(appId)
.key(key)
@@ -243,10 +242,84 @@
.build();
}
- private class InternalFibListener implements FibListener {
+ private void updateInterface(Interface intf) {
+ synchronized (this) {
+ for (Map.Entry<IpPrefix, MultiPointToSinglePointIntent> entry : routeIntents.entrySet()) {
+ MultiPointToSinglePointIntent intent = entry.getValue();
+ Set<ConnectPoint> ingress = Sets.newHashSet(intent.ingressPoints());
+ ingress.add(intf.connectPoint());
+
+ MultiPointToSinglePointIntent newIntent =
+ MultiPointToSinglePointIntent.builder(intent)
+ .ingressPoints(ingress)
+ .build();
+
+ routeIntents.put(entry.getKey(), newIntent);
+ intentSynchronizer.submit(newIntent);
+ }
+ }
+ }
+
+ private void removeInterface(Interface intf) {
+ synchronized (this) {
+ for (Map.Entry<IpPrefix, MultiPointToSinglePointIntent> entry : routeIntents.entrySet()) {
+ MultiPointToSinglePointIntent intent = entry.getValue();
+ if (intent.egressPoint().equals(intf.connectPoint())) {
+ // This intent just lost its head. Remove it and let
+ // higher layer routing reroute.
+ intentSynchronizer.withdraw(routeIntents.remove(entry.getKey()));
+ } else {
+ if (intent.ingressPoints().contains(intf.connectPoint())) {
+
+ Set<ConnectPoint> ingress = Sets.newHashSet(intent.ingressPoints());
+ ingress.remove(intf.connectPoint());
+
+ MultiPointToSinglePointIntent newIntent =
+ MultiPointToSinglePointIntent.builder(intent)
+ .ingressPoints(ingress)
+ .build();
+
+ routeIntents.put(entry.getKey(), newIntent);
+ intentSynchronizer.submit(newIntent);
+ }
+ }
+ }
+ }
+ }
+
+ private class InternalRouteListener implements RouteListener {
@Override
- public void update(Collection<FibUpdate> updates, Collection<FibUpdate> withdraws) {
- SdxL3Fib.this.update(updates, withdraws);
+ public void event(RouteEvent event) {
+ switch (event.type()) {
+ case ROUTE_ADDED:
+ case ROUTE_UPDATED:
+ update(event.subject());
+ break;
+ case ROUTE_REMOVED:
+ withdraw(event.subject());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private class InternalInterfaceListener implements InterfaceListener {
+
+ @Override
+ public void event(InterfaceEvent event) {
+ switch (event.type()) {
+ case INTERFACE_ADDED:
+ updateInterface(event.subject());
+ break;
+ case INTERFACE_UPDATED:
+ break;
+ case INTERFACE_REMOVED:
+ removeInterface(event.subject());
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java b/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java
index 90dcb8a..d057324 100644
--- a/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java
+++ b/sdx-l3/src/test/java/org/onosproject/sdxl3/SdxL3FibTest.java
@@ -30,7 +30,13 @@
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceListener;
import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.incubator.net.intf.InterfaceServiceAdapter;
+import org.onosproject.incubator.net.routing.ResolvedRoute;
+import org.onosproject.incubator.net.routing.RouteEvent;
+import org.onosproject.incubator.net.routing.RouteListener;
+import org.onosproject.incubator.net.routing.RouteServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
@@ -42,11 +48,7 @@
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
-import org.onosproject.routing.FibEntry;
-import org.onosproject.routing.FibListener;
-import org.onosproject.routing.FibUpdate;
import org.onosproject.routing.IntentSynchronizationService;
-import org.onosproject.routing.RoutingServiceAdapter;
import java.util.ArrayList;
import java.util.Collections;
@@ -54,8 +56,10 @@
import java.util.List;
import java.util.Set;
+import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
@@ -112,7 +116,8 @@
private static final ApplicationId APPID = TestApplicationId.create("sdxl3");
- private FibListener fibListener;
+ private RouteListener routeListener;
+ private InterfaceListener interfaceListener;
@Override
@Before
@@ -120,6 +125,9 @@
super.setUp();
interfaceService = createMock(InterfaceService.class);
+ interfaceService.addListener(anyObject(InterfaceListener.class));
+ expectLastCall().andDelegateTo(new InterfaceServiceDelegate());
+
peerService = createMock(SdxL3PeerService.class);
// These will set expectations on routingConfig and interfaceService
@@ -132,7 +140,7 @@
intentSynchronizer = createMock(IntentSynchronizationService.class);
sdxL3Fib = new SdxL3Fib();
- sdxL3Fib.routingService = new TestRoutingService();
+ sdxL3Fib.routeService = new TestRouteService();
sdxL3Fib.coreService = new TestCoreService();
sdxL3Fib.interfaceService = interfaceService;
sdxL3Fib.intentSynchronizer = intentSynchronizer;
@@ -182,7 +190,7 @@
interface4 = new Interface("test4",
CONN_POINT4,
interfaceIpAddresses4, MacAddress.valueOf(MAC2),
- VlanId.NONE);
+ VlanId.vlanId((short) 2));
interfaces.add(interface4);
expect(interfaceService.getInterfacesByPort(CONN_POINT1)).andReturn(
@@ -217,28 +225,27 @@
}
/**
- * Tests adding a FIB entry to the IntentSynchronizer. Peers within the same
+ * Tests adding a route to the IntentSynchronizer. Peers within the same
* subnet exist.
*
* We verify that the synchronizer records the correct state and that the
* correct intent is submitted to the IntentService.
*/
@Test
- public void testFibAdd() {
+ public void testRouteAdd() {
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
- FibEntry fibEntry = new FibEntry(prefix,
- Ip4Address.valueOf(PEER1_IP),
- MacAddress.valueOf(MAC1));
+ ResolvedRoute route = new ResolvedRoute(prefix,
+ Ip4Address.valueOf(PEER1_IP),
+ MacAddress.valueOf(MAC1));
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
- selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
- fibEntry.prefix());
+ selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(prefix).matchVlanId(VlanId.ANY);
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
- treatmentBuilder.setEthDst(MacAddress.valueOf(MAC1));
+ treatmentBuilder.setEthDst(MacAddress.valueOf(MAC1)).popVlan();
Set<ConnectPoint> ingressPoints = new HashSet<>();
ingressPoints.add(CONN_POINT2);
@@ -260,31 +267,30 @@
intentSynchronizer.submit(eqExceptId(intent));
replay(intentSynchronizer);
- // Send in the UPDATE FibUpdate
- FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
- fibListener.update(Collections.singleton(fibUpdate), Collections.emptyList());
+ // Send in the added event
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, route));
verify(intentSynchronizer);
}
/**
- * Tests adding a FIB entry with to a next hop in a VLAN.
+ * Tests adding a route entry with a next hop in a VLAN.
*
* We verify that the synchronizer records the correct state and that the
* correct intent is submitted to the IntentService.
*/
@Test
- public void testFibAddWithVlan() {
+ public void testRouteAddWithVlan() {
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
- FibEntry fibEntry = new FibEntry(prefix,
- Ip4Address.valueOf(PEER3_IP),
- MacAddress.valueOf(MAC1));
+ ResolvedRoute route = new ResolvedRoute(prefix,
+ Ip4Address.valueOf(PEER3_IP),
+ MacAddress.valueOf(MAC1));
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(fibEntry.prefix())
+ .matchIPDst(prefix)
.matchVlanId(VlanId.ANY);
TrafficTreatment.Builder treatmentBuilder =
@@ -313,40 +319,40 @@
replay(intentSynchronizer);
- // Send in the UPDATE FibUpdate
- FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
- fibListener.update(Collections.singleton(fibUpdate), Collections.emptyList());
+ // Send in the added event
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, route));
verify(intentSynchronizer);
}
/**
- * Tests updating a FIB entry.
+ * Tests updating a route entry.
*
* We verify that the synchronizer records the correct state and that the
* correct intent is submitted to the IntentService.
*/
@Test
- public void testFibUpdate() {
+ public void testRouteUpdate() {
// Firstly add a route
- testFibAdd();
+ testRouteAdd();
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
// Start to construct a new route entry and new intent
- FibEntry fibEntryUpdate = new FibEntry(prefix,
- Ip4Address.valueOf(PEER2_IP),
- MacAddress.valueOf(MAC1));
+ ResolvedRoute route = new ResolvedRoute(prefix,
+ Ip4Address.valueOf(PEER2_IP),
+ MacAddress.valueOf(MAC1));
// Construct a new MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilderNew =
DefaultTrafficSelector.builder();
- selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
- fibEntryUpdate.prefix());
+ selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(prefix)
+ .matchVlanId(VlanId.ANY);
TrafficTreatment.Builder treatmentBuilderNew =
DefaultTrafficTreatment.builder();
- treatmentBuilderNew.setEthDst(MacAddress.valueOf(MAC1));
+ treatmentBuilderNew.setEthDst(MacAddress.valueOf(MAC1)).popVlan();
Set<ConnectPoint> ingressPointsNew = new HashSet<>();
ingressPointsNew.add(CONN_POINT1);
@@ -371,40 +377,38 @@
intentSynchronizer.submit(eqExceptId(intentNew));
replay(intentSynchronizer);
- // Send in the UPDATE FibUpdate
- FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
- fibEntryUpdate);
- fibListener.update(Collections.singletonList(fibUpdate),
- Collections.emptyList());
+ // Send in the update event
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED, route));
verify(intentSynchronizer);
}
/**
- * Tests deleting a FIB entry.
+ * Tests deleting a route entry.
*
* We verify that the synchronizer records the correct state and that the
* correct intent is withdrawn from the IntentService.
*/
@Test
- public void testFibDelete() {
+ public void testRouteDelete() {
// Firstly add a route
- testFibAdd();
+ testRouteAdd();
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
// Construct the existing route entry
- FibEntry fibEntry = new FibEntry(prefix, null, null);
+ ResolvedRoute route = new ResolvedRoute(prefix, null, null);
// Construct the existing MultiPointToSinglePoint intent
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
- selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
- fibEntry.prefix());
+ selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(prefix)
+ .matchVlanId(VlanId.ANY);
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
- treatmentBuilder.setEthDst(MacAddress.valueOf(MAC1));
+ treatmentBuilder.setEthDst(MacAddress.valueOf(MAC1)).popVlan();
Set<ConnectPoint> ingressPoints = new HashSet<>();
ingressPoints.add(CONN_POINT2);
@@ -428,9 +432,8 @@
intentSynchronizer.withdraw(eqExceptId(addedIntent));
replay(intentSynchronizer);
- // Send in the DELETE FibUpdate
- FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.DELETE, fibEntry);
- fibListener.update(Collections.emptyList(), Collections.singletonList(fibUpdate));
+ // Send in the removed event
+ routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, route));
verify(intentSynchronizer);
}
@@ -442,12 +445,17 @@
}
}
- private class TestRoutingService extends RoutingServiceAdapter {
-
+ private class TestRouteService extends RouteServiceAdapter {
@Override
- public void addFibListener(FibListener fibListener) {
- SdxL3FibTest.this.fibListener = fibListener;
+ public void addListener(RouteListener routeListener) {
+ SdxL3FibTest.this.routeListener = routeListener;
+ }
+ }
+
+ private class InterfaceServiceDelegate extends InterfaceServiceAdapter {
+ @Override
+ public void addListener(InterfaceListener listener) {
+ SdxL3FibTest.this.interfaceListener = listener;
}
}
}
-