mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-05 04:06:49 +02:00
[ONOS-5607] Revise LISP ctrl impl class to track msgs and routers
Change-Id: I4a51a8ef9162e3feee543f40fa92a0435186d1c9
This commit is contained in:
parent
7ccc3a862f
commit
834ff723ce
@ -28,6 +28,13 @@ public interface LispController {
|
||||
*/
|
||||
Iterable<LispRouter> getRouters();
|
||||
|
||||
/**
|
||||
* Obtains all subscribed LISP routers known to this LISP controllers.
|
||||
*
|
||||
* @return Iterable of LISP router elements
|
||||
*/
|
||||
Iterable<LispRouter> getSubscribedRouters();
|
||||
|
||||
/**
|
||||
* Obtains the actual router for the given LispRouterId.
|
||||
*
|
||||
|
||||
@ -80,4 +80,47 @@ public interface LispRouter {
|
||||
* @return whether the router is connected
|
||||
*/
|
||||
boolean isConnected();
|
||||
|
||||
/**
|
||||
* Sets whether the router is connected.
|
||||
*
|
||||
* @param connected whether the router is connected
|
||||
*/
|
||||
void setConnected(boolean connected);
|
||||
|
||||
/**
|
||||
* Checks if the router is subscribed.
|
||||
* As long as a router sends Map-Request message,
|
||||
* we treat the router is subscribed.
|
||||
*
|
||||
* @return whether the router is subscribed
|
||||
*/
|
||||
boolean isSubscribed();
|
||||
|
||||
/**
|
||||
* Sets whether the router is subscribed.
|
||||
*
|
||||
* @param subscribed whether the router is subscribed
|
||||
*/
|
||||
void setSubscribed(boolean subscribed);
|
||||
|
||||
/**
|
||||
* Sets the LISP agent to be used. This method can only be invoked once.
|
||||
*
|
||||
* @param agent the agent to set
|
||||
*/
|
||||
void setAgent(LispRouterAgent agent);
|
||||
|
||||
/**
|
||||
* Announces to the LISP agent that this router has connected.
|
||||
*
|
||||
* @return true if successful, false if duplicate router
|
||||
*/
|
||||
boolean connectRouter();
|
||||
|
||||
/**
|
||||
* Disconnects the router by closing UDP connection.
|
||||
* Results in a call to the channel handler's close method for cleanup.
|
||||
*/
|
||||
void disconnectRouter();
|
||||
}
|
||||
|
||||
@ -24,6 +24,11 @@ public class LispControllerAdapter implements LispController {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<LispRouter> getSubscribedRouters() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LispRouter getRouter(LispRouterId routerId) {
|
||||
return null;
|
||||
|
||||
@ -63,4 +63,34 @@ public class LispRouterAdapter implements LispRouter {
|
||||
public boolean isConnected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConnected(boolean connected) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubscribed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubscribed(boolean subscribed) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAgent(LispRouterAgent agent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connectRouter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnectRouter() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ TEST_DEPS = [
|
||||
'//lib:TEST_ADAPTERS',
|
||||
'//utils/osgi:onlab-osgi-tests',
|
||||
'//core/api:onos-api-tests',
|
||||
'//protocols/lisp/api:onos-protocols-lisp-api-tests',
|
||||
]
|
||||
|
||||
osgi_jar_with_tests (
|
||||
|
||||
@ -61,6 +61,14 @@
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.onosproject</groupId>
|
||||
<artifactId>onos-lisp-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -48,6 +48,7 @@ public class LispControllerBootstrap {
|
||||
|
||||
private EventLoopGroup eventLoopGroup;
|
||||
private Class<? extends AbstractChannel> channelClass;
|
||||
private List<ChannelFuture> channelFutures = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* Stitches all channel handlers into server bootstrap.
|
||||
@ -59,8 +60,6 @@ public class LispControllerBootstrap {
|
||||
|
||||
configBootstrapOptions(bootstrap);
|
||||
|
||||
List<ChannelFuture> channelFutures = Lists.newArrayList();
|
||||
|
||||
lispPorts.forEach(p -> {
|
||||
InetSocketAddress sa = new InetSocketAddress(p);
|
||||
channelFutures.add(bootstrap.bind(sa));
|
||||
@ -152,6 +151,7 @@ public class LispControllerBootstrap {
|
||||
try {
|
||||
// try to shutdown all open event groups
|
||||
eventLoopGroup.shutdownGracefully().sync();
|
||||
closeChannels(channelFutures);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Failed to stop LISP controller. Reasons: {}.", e.getMessage());
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.onosproject.lisp.ctl.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.felix.scr.annotations.Activate;
|
||||
import org.apache.felix.scr.annotations.Component;
|
||||
import org.apache.felix.scr.annotations.Deactivate;
|
||||
@ -29,18 +30,29 @@ import org.onosproject.core.CoreService;
|
||||
import org.onosproject.lisp.ctl.LispController;
|
||||
import org.onosproject.lisp.ctl.LispMessageListener;
|
||||
import org.onosproject.lisp.ctl.LispRouter;
|
||||
import org.onosproject.lisp.ctl.LispRouterAgent;
|
||||
import org.onosproject.lisp.ctl.LispRouterId;
|
||||
import org.onosproject.lisp.ctl.LispRouterListener;
|
||||
import org.onosproject.lisp.msg.authentication.LispAuthenticationConfig;
|
||||
import org.onosproject.net.device.DeviceService;
|
||||
import org.onosproject.lisp.msg.protocols.LispInfoReply;
|
||||
import org.onosproject.lisp.msg.protocols.LispInfoRequest;
|
||||
import org.onosproject.lisp.msg.protocols.LispMessage;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static java.util.concurrent.Executors.newFixedThreadPool;
|
||||
import static java.util.stream.Collectors.toConcurrentMap;
|
||||
import static org.onlab.util.Tools.get;
|
||||
import static org.onlab.util.Tools.getIntegerProperty;
|
||||
import static org.onlab.util.Tools.groupedThreads;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* LISP controller initiation class.
|
||||
@ -51,8 +63,7 @@ public class LispControllerImpl implements LispController {
|
||||
|
||||
private static final String APP_ID = "org.onosproject.lisp-base";
|
||||
|
||||
private static final Logger log =
|
||||
LoggerFactory.getLogger(LispControllerImpl.class);
|
||||
private static final Logger log = getLogger(LispControllerImpl.class);
|
||||
|
||||
private static final String DEFAULT_LISP_AUTH_KEY = "onos";
|
||||
private static final short DEFAULT_LISP_AUTH_KEY_ID = 1;
|
||||
@ -60,46 +71,65 @@ public class LispControllerImpl implements LispController {
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected CoreService coreService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected DeviceService deviceService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||
protected ComponentConfigService cfgService;
|
||||
|
||||
@Property(name = "lispAuthKey", value = DEFAULT_LISP_AUTH_KEY,
|
||||
label = "Authentication key which is used to calculate authentication " +
|
||||
"data for LISP control message; default value is onos")
|
||||
protected String lispAuthKey = DEFAULT_LISP_AUTH_KEY;
|
||||
private String lispAuthKey = DEFAULT_LISP_AUTH_KEY;
|
||||
|
||||
@Property(name = "lispAuthKeyId", intValue = DEFAULT_LISP_AUTH_KEY_ID,
|
||||
label = "Authentication key id which denotes the authentication method " +
|
||||
"that ONOS uses to calculate the authentication data; " +
|
||||
"1 denotes HMAC SHA1 encryption, 2 denotes HMAC SHA256 encryption; " +
|
||||
"default value is 1")
|
||||
protected int lispAuthKeyId = DEFAULT_LISP_AUTH_KEY_ID;
|
||||
private int lispAuthKeyId = DEFAULT_LISP_AUTH_KEY_ID;
|
||||
|
||||
ExecutorService executorMessages =
|
||||
newFixedThreadPool(4, groupedThreads("onos/lisp", "event-stats-%d", log));
|
||||
|
||||
protected LispRouterAgent agent = new DefaultLispRouterAgent();
|
||||
|
||||
ConcurrentMap<LispRouterId, LispRouter> connectedRouters = Maps.newConcurrentMap();
|
||||
|
||||
private Set<LispRouterListener> lispRouterListeners = new CopyOnWriteArraySet<>();
|
||||
private Set<LispMessageListener> lispMessageListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private final LispControllerBootstrap bootstrap = new LispControllerBootstrap();
|
||||
private final LispAuthenticationConfig authConfig = LispAuthenticationConfig.getInstance();
|
||||
|
||||
@Activate
|
||||
public void activate(ComponentContext context) {
|
||||
coreService.registerApplication(APP_ID, this::cleanup);
|
||||
cfgService.registerProperties(getClass());
|
||||
coreService.registerApplication(APP_ID);
|
||||
initAuthConfig(context.getProperties());
|
||||
bootstrap.start();
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdowns all listening channel and all LISP channels.
|
||||
* Clean information about routers before deactivating.
|
||||
*/
|
||||
private void cleanup() {
|
||||
bootstrap.stop();
|
||||
connectedRouters.values().forEach(LispRouter::disconnectRouter);
|
||||
connectedRouters.clear();
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
cleanup();
|
||||
cfgService.unregisterProperties(getClass(), false);
|
||||
bootstrap.stop();
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
@Modified
|
||||
public void modified(ComponentContext context) {
|
||||
readComponentConfiguration(context);
|
||||
bootstrap.stop();
|
||||
bootstrap.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,31 +168,189 @@ public class LispControllerImpl implements LispController {
|
||||
|
||||
@Override
|
||||
public Iterable<LispRouter> getRouters() {
|
||||
return null;
|
||||
return connectedRouters.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<LispRouter> getSubscribedRouters() {
|
||||
return connectedRouters.entrySet()
|
||||
.stream()
|
||||
.filter(e -> e.getValue().isSubscribed())
|
||||
.collect(toConcurrentMap(Map.Entry::getKey,
|
||||
Map.Entry::getValue)).values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LispRouter getRouter(LispRouterId routerId) {
|
||||
return null;
|
||||
return connectedRouters.get(routerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRouterListener(LispRouterListener listener) {
|
||||
|
||||
if (!lispRouterListeners.contains(listener)) {
|
||||
lispRouterListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRouterListener(LispRouterListener listener) {
|
||||
|
||||
lispRouterListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessageListener(LispMessageListener listener) {
|
||||
|
||||
if (!lispMessageListeners.contains(listener)) {
|
||||
lispMessageListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMessageListener(LispMessageListener listener) {
|
||||
lispMessageListeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of a LISP agent which is responsible for keeping track of
|
||||
* connected LISP routers and the state in which they are in.
|
||||
*/
|
||||
public final class DefaultLispRouterAgent implements LispRouterAgent {
|
||||
|
||||
private final Logger log = getLogger(DefaultLispRouterAgent.class);
|
||||
|
||||
/**
|
||||
* Prevents object instantiation from external class.
|
||||
*/
|
||||
private DefaultLispRouterAgent() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addConnectedRouter(LispRouterId routerId, LispRouter router) {
|
||||
|
||||
if (connectedRouters.get(routerId) != null) {
|
||||
log.error("Trying to add connectedRouter but found a previous " +
|
||||
"value for routerId: {}", routerId);
|
||||
return false;
|
||||
} else {
|
||||
log.info("Added router {}", routerId);
|
||||
connectedRouters.put(routerId, router);
|
||||
for (LispRouterListener listener : lispRouterListeners) {
|
||||
listener.routerAdded(routerId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConnectedRouter(LispRouterId routerId) {
|
||||
|
||||
if (connectedRouters.get(routerId) == null) {
|
||||
log.error("Trying to remove router {} from connectedRouter " +
|
||||
"list but no element was found", routerId);
|
||||
} else {
|
||||
log.info("Removed router {}", routerId);
|
||||
connectedRouters.remove(routerId);
|
||||
for (LispRouterListener listener : lispRouterListeners) {
|
||||
listener.routerRemoved(routerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processUpstreamMessage(LispRouterId routerId, LispMessage message) {
|
||||
|
||||
switch (message.getType()) {
|
||||
case LISP_MAP_REGISTER:
|
||||
case LISP_MAP_REQUEST:
|
||||
executorMessages.execute(
|
||||
new LispIncomingMessageHandler(routerId, message));
|
||||
break;
|
||||
case LISP_INFO:
|
||||
if (message instanceof LispInfoRequest) {
|
||||
executorMessages.execute(
|
||||
new LispIncomingMessageHandler(routerId, message));
|
||||
} else {
|
||||
log.warn("Not incoming LISP control message");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log.warn("Not incoming LISP control message");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDownstreamMessage(LispRouterId routerId, LispMessage message) {
|
||||
|
||||
switch (message.getType()) {
|
||||
case LISP_MAP_NOTIFY:
|
||||
case LISP_MAP_REPLY:
|
||||
executorMessages.execute(
|
||||
new LispOutgoingMessageHandler(routerId, message));
|
||||
break;
|
||||
case LISP_INFO:
|
||||
if (message instanceof LispInfoReply) {
|
||||
executorMessages.execute(
|
||||
new LispOutgoingMessageHandler(routerId, message));
|
||||
} else {
|
||||
log.warn("Not outgoing LISP control message");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log.warn("Not outgoing LISP control message");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LISP message handler.
|
||||
*/
|
||||
protected class LispMessageHandler implements Runnable {
|
||||
|
||||
private final LispRouterId routerId;
|
||||
private final LispMessage message;
|
||||
private final boolean isIncoming;
|
||||
|
||||
LispMessageHandler(LispRouterId routerId,
|
||||
LispMessage message, boolean isIncoming) {
|
||||
this.routerId = routerId;
|
||||
this.message = message;
|
||||
this.isIncoming = isIncoming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
for (LispMessageListener listener : lispMessageListeners) {
|
||||
if (isIncoming) {
|
||||
listener.handleIncomingMessage(routerId, message);
|
||||
} else {
|
||||
listener.handleOutgoingMessage(routerId, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LISP incoming message handler.
|
||||
*/
|
||||
protected final class LispIncomingMessageHandler
|
||||
extends LispMessageHandler implements Runnable {
|
||||
|
||||
LispIncomingMessageHandler(LispRouterId routerId,
|
||||
LispMessage message) {
|
||||
super(routerId, message, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LISP outgoing message handler.
|
||||
*/
|
||||
protected final class LispOutgoingMessageHandler
|
||||
extends LispMessageHandler implements Runnable {
|
||||
|
||||
LispOutgoingMessageHandler(LispRouterId routerId,
|
||||
LispMessage message) {
|
||||
super(routerId, message, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,329 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.onosproject.lisp.ctl.impl;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.easymock.EasyMock;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onosproject.cfg.ComponentConfigService;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.lisp.ctl.LispMessageListener;
|
||||
import org.onosproject.lisp.ctl.LispRouter;
|
||||
import org.onosproject.lisp.ctl.LispRouterAdapter;
|
||||
import org.onosproject.lisp.ctl.LispRouterAgent;
|
||||
import org.onosproject.lisp.ctl.LispRouterId;
|
||||
import org.onosproject.lisp.ctl.LispRouterListener;
|
||||
import org.onosproject.lisp.msg.protocols.DefaultLispMapNotify.DefaultNotifyBuilder;
|
||||
import org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
|
||||
import org.onosproject.lisp.msg.protocols.DefaultLispMapRegister.DefaultRegisterBuilder;
|
||||
import org.onosproject.lisp.msg.protocols.LispMapNotify;
|
||||
import org.onosproject.lisp.msg.protocols.LispMapNotify.NotifyBuilder;
|
||||
import org.onosproject.lisp.msg.protocols.LispMapRecord;
|
||||
import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
|
||||
import org.onosproject.lisp.msg.protocols.LispMapRegister;
|
||||
import org.onosproject.lisp.msg.protocols.LispMapRegister.RegisterBuilder;
|
||||
import org.onosproject.lisp.msg.protocols.LispMapReplyAction;
|
||||
import org.onosproject.lisp.msg.protocols.LispMessage;
|
||||
import org.onosproject.lisp.msg.types.LispIpv4Address;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static junit.framework.TestCase.fail;
|
||||
import static org.easymock.EasyMock.anyObject;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.expectLastCall;
|
||||
import static org.easymock.EasyMock.replay;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
/**
|
||||
* Unit tests for the LISP controller implementation class.
|
||||
*/
|
||||
public class LispControllerImplTest {
|
||||
|
||||
private LispRouterId routerId1;
|
||||
private LispRouterId routerId2;
|
||||
private LispRouterId routerId3;
|
||||
private LispRouter router1;
|
||||
private LispRouter router2;
|
||||
private LispRouter router3;
|
||||
|
||||
private LispControllerImpl controller;
|
||||
private LispRouterAgent agent;
|
||||
private TestRouterListener routerListener;
|
||||
private TestMessageListener messageListener;
|
||||
|
||||
/**
|
||||
* Tests harness for a router routerListener.
|
||||
*/
|
||||
static final class TestRouterListener implements LispRouterListener {
|
||||
|
||||
final List<LispRouterId> removedIds = Lists.newArrayList();
|
||||
final List<LispRouterId> addedIds = Lists.newArrayList();
|
||||
final List<LispRouterId> changedIds = Lists.newArrayList();
|
||||
|
||||
@Override
|
||||
public void routerAdded(LispRouterId routerId) {
|
||||
addedIds.add(routerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void routerRemoved(LispRouterId routerId) {
|
||||
removedIds.add(routerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void routerChanged(LispRouterId routerId) {
|
||||
changedIds.add(routerId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests harness for a router messageListener.
|
||||
*/
|
||||
static final class TestMessageListener implements LispMessageListener {
|
||||
|
||||
final List<LispMessage> incomingMessages = Lists.newArrayList();
|
||||
final List<LispMessage> outgoingMessages = Lists.newArrayList();
|
||||
|
||||
CountDownLatch incomingLatch = new CountDownLatch(1);
|
||||
CountDownLatch outgoingLatch = new CountDownLatch(1);
|
||||
|
||||
@Override
|
||||
public void handleIncomingMessage(LispRouterId routerId, LispMessage msg) {
|
||||
synchronized (incomingMessages) {
|
||||
incomingMessages.add(msg);
|
||||
incomingLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleOutgoingMessage(LispRouterId routerId, LispMessage msg) {
|
||||
synchronized (outgoingMessages) {
|
||||
outgoingMessages.add(msg);
|
||||
outgoingLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
public void waitUntilUpdateIsCalled() throws InterruptedException {
|
||||
incomingLatch.await();
|
||||
outgoingLatch.await();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up routers to use as data, mocks and launches a controller instance.
|
||||
*/
|
||||
@Before
|
||||
public void setUp() {
|
||||
try {
|
||||
router1 = new LispRouterAdapter();
|
||||
routerId1 = LispRouterId.routerId(new URI("lisp:10.1.1.1"));
|
||||
router2 = new LispRouterAdapter();
|
||||
routerId2 = LispRouterId.routerId(new URI("lisp:10.1.1.2"));
|
||||
router3 = new LispRouterAdapter();
|
||||
routerId3 = LispRouterId.routerId(new URI("lisp:10.1.1.3"));
|
||||
|
||||
} catch (URISyntaxException e) {
|
||||
// this will never happen...
|
||||
fail();
|
||||
}
|
||||
|
||||
controller = new LispControllerImpl();
|
||||
agent = controller.agent;
|
||||
|
||||
routerListener = new TestRouterListener();
|
||||
controller.addRouterListener(routerListener);
|
||||
|
||||
messageListener = new TestMessageListener();
|
||||
controller.addMessageListener(messageListener);
|
||||
|
||||
controller.coreService = EasyMock.createMock(CoreService.class);
|
||||
|
||||
ComponentConfigService mockConfigService =
|
||||
EasyMock.createMock(ComponentConfigService.class);
|
||||
expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
|
||||
mockConfigService.registerProperties(controller.getClass());
|
||||
expectLastCall();
|
||||
mockConfigService.unregisterProperties(controller.getClass(), false);
|
||||
expectLastCall();
|
||||
expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
|
||||
controller.cfgService = mockConfigService;
|
||||
replay(mockConfigService);
|
||||
|
||||
ComponentContext mockContext = EasyMock.createMock(ComponentContext.class);
|
||||
Dictionary<String, Object> properties = new Hashtable<>();
|
||||
properties.put("lispAuthKey", "onos");
|
||||
properties.put("lispAuthKeyId", 1);
|
||||
expect(mockContext.getProperties()).andReturn(properties);
|
||||
replay(mockContext);
|
||||
controller.activate(mockContext);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
|
||||
controller.removeRouterListener(routerListener);
|
||||
controller.removeMessageListener(messageListener);
|
||||
controller.deactivate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding and removing connected routers.
|
||||
*/
|
||||
@Test
|
||||
public void testAddRemoveConnectedRouter() {
|
||||
|
||||
// Test adding connected routers into agent
|
||||
boolean addRouter1 = agent.addConnectedRouter(routerId1, router1);
|
||||
assertThat(addRouter1, is(true));
|
||||
boolean addRouter2 = agent.addConnectedRouter(routerId2, router2);
|
||||
assertThat(addRouter2, is(true));
|
||||
boolean addRouter3 = agent.addConnectedRouter(routerId3, router3);
|
||||
assertThat(addRouter3, is(true));
|
||||
|
||||
// Test the callback methods that contained in router listener is fired
|
||||
assertThat(routerListener.addedIds, hasSize(3));
|
||||
assertThat(routerListener.addedIds, hasItems(routerId1, routerId2, routerId3));
|
||||
|
||||
// Test adding a router twice (duplicated router)
|
||||
// this should return false to indicate that there is already a router
|
||||
// has been added previously
|
||||
boolean addBadRouter1 = agent.addConnectedRouter(routerId1, router1);
|
||||
assertThat(addBadRouter1, is(false));
|
||||
|
||||
// Also make sure that the duplicated router will never increase the counter
|
||||
assertThat(controller.connectedRouters.size(), is(3));
|
||||
|
||||
// Test querying the router list
|
||||
Stream<LispRouter> queriedRouters = makeIntoStream(controller.getRouters());
|
||||
long routerCount = queriedRouters.count();
|
||||
assertThat(routerCount, is(3L));
|
||||
|
||||
// Test querying the individual router
|
||||
LispRouter queriedRouter = controller.getRouter(routerId1);
|
||||
assertThat(queriedRouter, is(router1));
|
||||
|
||||
// Test removing a router from connected router collection
|
||||
agent.removeConnectedRouter(routerId2);
|
||||
Stream<LispRouter> queriedRoutersAfterRemoval =
|
||||
makeIntoStream(controller.getRouters());
|
||||
long routerCountAfterRemoval = queriedRoutersAfterRemoval.count();
|
||||
assertThat(routerCountAfterRemoval, is(2L));
|
||||
|
||||
// Test the callback methods that contained in router listener is fired
|
||||
assertThat(routerListener.removedIds, hasSize(1));
|
||||
assertThat(routerListener.removedIds, hasItems(routerId2));
|
||||
|
||||
// Test querying the removed switch
|
||||
LispRouter queriedRouterAfterRemoval = controller.getRouter(routerId2);
|
||||
assertThat(queriedRouterAfterRemoval, nullValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests adding and removing LISP messages.
|
||||
*/
|
||||
@Test
|
||||
public void testLispMessagePopulate() throws InterruptedException {
|
||||
|
||||
RegisterBuilder registerBuilder = new DefaultRegisterBuilder();
|
||||
List<LispMapRecord> records = ImmutableList.of(getMapRecord(), getMapRecord());
|
||||
LispMapRegister register = registerBuilder
|
||||
.withIsProxyMapReply(true)
|
||||
.withIsWantMapNotify(false)
|
||||
.withKeyId((short) 1)
|
||||
.withAuthKey("onos")
|
||||
.withNonce(1L)
|
||||
.withMapRecords(records)
|
||||
.build();
|
||||
|
||||
NotifyBuilder notifyBuilder = new DefaultNotifyBuilder();
|
||||
LispMapNotify notify = notifyBuilder
|
||||
.withKeyId((short) 1)
|
||||
.withAuthKey("onos")
|
||||
.withNonce(1L)
|
||||
.withMapRecords(records)
|
||||
.build();
|
||||
|
||||
// Test the callback methods that contained in message listener is fired
|
||||
agent.processUpstreamMessage(routerId1, register);
|
||||
// Following line will be ignored
|
||||
agent.processUpstreamMessage(routerId1, notify);
|
||||
|
||||
agent.processDownstreamMessage(routerId1, notify);
|
||||
// Following line will be ignored
|
||||
agent.processDownstreamMessage(routerId1, register);
|
||||
|
||||
messageListener.waitUntilUpdateIsCalled();
|
||||
|
||||
assertThat(messageListener.incomingMessages, hasSize(1));
|
||||
assertThat(messageListener.incomingMessages, hasItems(register));
|
||||
|
||||
assertThat(messageListener.outgoingMessages, hasSize(1));
|
||||
assertThat(messageListener.outgoingMessages, hasItems(notify));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates and returns a map record.
|
||||
*
|
||||
* @return a map record
|
||||
*/
|
||||
private LispMapRecord getMapRecord() {
|
||||
MapRecordBuilder builder1 = new DefaultMapRecordBuilder();
|
||||
|
||||
LispIpv4Address ipv4Locator1 = new LispIpv4Address(IpAddress.valueOf("192.168.1.1"));
|
||||
|
||||
return builder1
|
||||
.withRecordTtl(100)
|
||||
.withAuthoritative(true)
|
||||
.withMapVersionNumber((short) 1)
|
||||
.withMaskLength((byte) 0x01)
|
||||
.withAction(LispMapReplyAction.NativelyForward)
|
||||
.withEidPrefixAfi(ipv4Locator1)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an Iterable of some type into a stream of that type.
|
||||
*
|
||||
* @param items Iterable of objects
|
||||
* @param <T> type of the items in the iterable
|
||||
* @return stream of objects of type T
|
||||
*/
|
||||
private <T> Stream<T> makeIntoStream(Iterable<T> items) {
|
||||
return StreamSupport.stream(
|
||||
Spliterators.spliteratorUnknownSize(
|
||||
items.iterator(), Spliterator.ORDERED), false);
|
||||
}
|
||||
}
|
||||
@ -57,6 +57,10 @@
|
||||
<artifactId>easymock</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user