Jonathan Hart

Moved BGP code and Router code into their own bundle.

The main goal of this is to allow routing code to be used by multiple
applications.

Changes include:
 * Created an onos-app-routing bundle and moved BGP code and routing code
   into it.
 * Created an onos-app-routing-api bundle as a common API bundle between
   onos-app-routing and onos-app-sdnip, to prevent circular dependencies.
 * Moved API classes into onos-app-routing-api bundle.
 * Made Router and BgpSessionManager into OSGi components. This is not quite
   clean, because there is still a chain of start() method calls from SdnIp
   through to BgpSessionManager to preserve startup order. This should be
   revisted so components can be started using activate()
 * Created BgpService and RoutingService APIs to glue different components
   together.
 * Many unit test changes. A lot of the previous unit tests spanned the
   Router and IntentSynchronizer classes, but this is not possible any more
   since these classes are in different bundles. I had to rewrite some of
   these tests so that each unit test class only tests one real class. A
   nice side-effect is that the tests are now simpler because each test
   tests less functionality.
 * Removed SdnIp test seeing as it doesn't run automatically, was already
   broken and has been largely superseded by other unit tests and the nightly
   functional tests.

Change-Id: I70ecf5391aa353e99e7cdcf7ed38a530c87571bb
Showing 52 changed files with 1602 additions and 2260 deletions
......@@ -46,6 +46,8 @@
<module>oecfg</module>
<module>demo</module>
<module>election</module>
<module>routing</module>
<module>routing-api</module>
</modules>
<properties>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>onos-apps</artifactId>
<groupId>org.onosproject</groupId>
<version>1.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>onos-app-routing-api</artifactId>
<packaging>bundle</packaging>
<description>API for routing applications</description>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
/*
* Copyright 2015 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.routingapi;
/**
* Provides a way of interacting with the BGP protocol component.
*/
public interface BgpService {
/**
* Starts the BGP service.
*
* @param routeListener listener to send route updates to
* @param bgpPort port number to listen on
*/
void start(RouteListener routeListener, int bgpPort);
/**
* Stops the BGP service.
*/
void stop();
}
......@@ -13,12 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
package org.onosproject.routingapi;
import com.google.common.base.MoreObjects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import java.util.Objects;
/**
* An entry in the Forwarding Information Base (FIB).
*/
......@@ -67,4 +70,31 @@ public class FibEntry {
public MacAddress nextHopMac() {
return nextHopMac;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof FibEntry)) {
return false;
}
FibEntry that = (FibEntry) o;
return Objects.equals(this.prefix, that.prefix) &&
Objects.equals(this.nextHopIp, that.nextHopIp) &&
Objects.equals(this.nextHopMac, that.nextHopMac);
}
@Override
public int hashCode() {
return Objects.hash(prefix, nextHopIp, nextHopMac);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("prefix", prefix)
.add("nextHopIp", nextHopIp)
.add("nextHopMac", nextHopMac)
.toString();
}
}
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
package org.onosproject.routingapi;
import java.util.Collection;
......
......@@ -13,7 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
package org.onosproject.routingapi;
import com.google.common.base.MoreObjects;
import java.util.Objects;
/**
* Represents a change to the Forwarding Information Base (FIB).
......@@ -66,4 +70,29 @@ public class FibUpdate {
public FibEntry entry() {
return entry;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof FibUpdate)) {
return false;
}
FibUpdate that = (FibUpdate) o;
return Objects.equals(this.type, that.type) &&
Objects.equals(this.entry, that.entry);
}
@Override
public int hashCode() {
return Objects.hash(type, entry);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("type", type)
.add("entry", entry)
.toString();
}
}
......
......@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
package org.onosproject.routingapi;
import com.google.common.base.MoreObjects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import com.google.common.base.MoreObjects;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a route entry for an IP prefix.
......@@ -77,7 +76,7 @@ public class RouteEntry {
* @param ipPrefix the IP prefix to use
* @return the binary string representation
*/
static String createBinaryString(IpPrefix ipPrefix) {
public static String createBinaryString(IpPrefix ipPrefix) {
if (ipPrefix.prefixLength() == 0) {
return "";
}
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
package org.onosproject.routingapi;
import java.util.Collection;
......
......@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
package org.onosproject.routingapi;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.MoreObjects;
import java.util.Objects;
import com.google.common.base.MoreObjects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a change in routing information.
......
/*
* Copyright 2015 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.routingapi;
import java.util.Collection;
/**
* Provides a way of interacting with the RIB management component.
*/
public interface RoutingService {
/**
* Starts the routing service.
*
* @param listener listener to send FIB updates to
*/
public void start(FibListener listener);
/**
* Stops the routing service.
*/
public void stop();
/**
* Gets all IPv4 routes known to SDN-IP.
*
* @return the SDN-IP IPv4 routes
*/
public Collection<RouteEntry> getRoutes4();
/**
* Gets all IPv6 routes known to SDN-IP.
*
* @return the SDN-IP IPv6 routes
*/
public Collection<RouteEntry> getRoutes6();
}
......@@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
package org.onosproject.routingapi;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
/**
* Unit tests for the RouteEntry class.
*/
......@@ -139,8 +140,8 @@ public class RouteEntryTest {
Ip4Address nextHop3 = Ip4Address.valueOf("5.6.7.9"); // Different
RouteEntry routeEntry3 = new RouteEntry(prefix3, nextHop3);
assertThat(routeEntry1, is(not(routeEntry2)));
assertThat(routeEntry1, is(not(routeEntry3)));
assertThat(routeEntry1, Matchers.is(not(routeEntry2)));
assertThat(routeEntry1, Matchers.is(not(routeEntry3)));
}
/**
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>onos-apps</artifactId>
<groupId>org.onosproject</groupId>
<version>1.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>onos-app-routing</artifactId>
<packaging>bundle</packaging>
<description>Libraries for routing applications</description>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-app-routing-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-thirdparty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip;
package org.onosproject.routing;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimaps;
......@@ -23,6 +23,12 @@ import com.googlecode.concurrenttrees.common.KeyValuePair;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
......@@ -31,6 +37,14 @@ import org.onosproject.net.Host;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.routingapi.BgpService;
import org.onosproject.routingapi.FibEntry;
import org.onosproject.routingapi.FibListener;
import org.onosproject.routingapi.FibUpdate;
import org.onosproject.routingapi.RouteEntry;
import org.onosproject.routingapi.RouteListener;
import org.onosproject.routingapi.RouteUpdate;
import org.onosproject.routingapi.RoutingService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -47,12 +61,16 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* This class processes route updates and maintains a Routing Information Base
* (RIB). After route updates have been processed and next hops have been
* resolved, FIB updates are sent to any listening FIB components.
*/
public class Router implements RouteListener {
@Component(immediate = true)
@Service
public class Router implements RoutingService {
private static final Logger log = LoggerFactory.getLogger(Router.class);
......@@ -62,52 +80,52 @@ public class Router implements RouteListener {
private InvertedRadixTree<RouteEntry> ribTable6;
// Stores all incoming route updates in a queue.
private final BlockingQueue<Collection<RouteUpdate>> routeUpdatesQueue;
private final BlockingQueue<Collection<RouteUpdate>> routeUpdatesQueue
= new LinkedBlockingQueue<>();
// Next-hop IP address to route entry mapping for next hops pending MAC resolution
private final SetMultimap<IpAddress, RouteEntry> routesWaitingOnArp;
private SetMultimap<IpAddress, RouteEntry> routesWaitingOnArp;
// The IPv4 address to MAC address mapping
private final Map<IpAddress, MacAddress> ip2Mac;
private final Map<IpAddress, MacAddress> ip2Mac = new ConcurrentHashMap<>();
private final FibListener fibComponent;
private final HostService hostService;
private final ExecutorService bgpUpdatesExecutor;
private final HostListener hostListener;
private FibListener fibComponent;
/**
* Class constructor.
*
* @param fibComponent the intent synchronizer
* @param hostService the host service
*/
public Router(FibListener fibComponent, HostService hostService) {
// TODO move to a listener model for adding fib listeners
this.fibComponent = fibComponent;
this.hostService = hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
this.hostListener = new InternalHostListener();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected BgpService bgpService;
private ExecutorService bgpUpdatesExecutor;
private final HostListener hostListener = new InternalHostListener();
@Activate
public void activate() {
ribTable4 = new ConcurrentInvertedRadixTree<>(
new DefaultByteArrayNodeFactory());
ribTable6 = new ConcurrentInvertedRadixTree<>(
new DefaultByteArrayNodeFactory());
routeUpdatesQueue = new LinkedBlockingQueue<>();
routesWaitingOnArp = Multimaps.synchronizedSetMultimap(
HashMultimap.<IpAddress, RouteEntry>create());
ip2Mac = new ConcurrentHashMap<>();
bgpUpdatesExecutor = Executors.newSingleThreadExecutor(
new ThreadFactoryBuilder()
.setNameFormat("sdnip-bgp-updates-%d").build());
}
/**
* Starts the router.
*/
public void start() {
@Deactivate
public void deactivate() {
log.debug("Stopped");
}
@Override
public void start(FibListener listener) {
this.fibComponent = checkNotNull(listener);
this.hostService.addListener(hostListener);
bgpService.start(new InternalRouteListener(), 2000);
bgpUpdatesExecutor.execute(new Runnable() {
@Override
public void run() {
......@@ -116,10 +134,10 @@ public class Router implements RouteListener {
});
}
/**
* Stops the router.
*/
@Override
public void stop() {
bgpService.stop();
this.hostService.removeListener(hostListener);
// Stop the thread(s)
......@@ -137,8 +155,12 @@ public class Router implements RouteListener {
}
}
@Override
public void update(Collection<RouteUpdate> routeUpdates) {
/**
* Entry point for route updates.
*
* @param routeUpdates collection of route updates to process
*/
private void update(Collection<RouteUpdate> routeUpdates) {
try {
routeUpdatesQueue.put(routeUpdates);
} catch (InterruptedException e) {
......@@ -294,7 +316,9 @@ public class Router implements RouteListener {
withdrawPrefixes.forEach(p -> fibWithdraws.add(new FibUpdate(
FibUpdate.Type.DELETE, new FibEntry(p, null, null))));
fibComponent.update(fibUpdates, fibWithdraws);
if (!fibUpdates.isEmpty() || !fibWithdraws.isEmpty()) {
fibComponent.update(fibUpdates, fibWithdraws);
}
}
}
......@@ -486,4 +510,14 @@ public class Router implements RouteListener {
}
}
}
/**
* Listener for route events.
*/
private class InternalRouteListener implements RouteListener {
@Override
public void update(Collection<RouteUpdate> routeUpdates) {
Router.this.update(routeUpdates);
}
}
}
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
/**
* BGP related constants.
......
......@@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.MessageHeaderError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -86,9 +85,9 @@ class BgpFrameDecoder extends FrameDecoder {
// ERROR: Connection Not Synchronized
//
// Send NOTIFICATION and close the connection
int errorCode = MessageHeaderError.ERROR_CODE;
int errorCode = BgpConstants.Notifications.MessageHeaderError.ERROR_CODE;
int errorSubcode =
MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED;
BgpConstants.Notifications.MessageHeaderError.CONNECTION_NOT_SYNCHRONIZED;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode,
errorSubcode,
......@@ -162,8 +161,8 @@ class BgpFrameDecoder extends FrameDecoder {
// ERROR: Bad Message Type
//
// Send NOTIFICATION and close the connection
int errorCode = MessageHeaderError.ERROR_CODE;
int errorSubcode = MessageHeaderError.BAD_MESSAGE_TYPE;
int errorCode = BgpConstants.Notifications.MessageHeaderError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.MessageHeaderError.BAD_MESSAGE_TYPE;
ChannelBuffer data = ChannelBuffers.buffer(1);
data.writeByte(type);
ChannelBuffer txMessage =
......
/*
* Copyright 2015 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.routing.bgp;
import java.util.Collection;
/**
* Provides information about BGP peering and routes.
*/
public interface BgpInfoService {
/**
* Gets the BGP sessions.
*
* @return the BGP sessions
*/
public Collection<BgpSession> getBgpSessions();
/**
* Gets the selected IPv4 BGP routes among all BGP sessions.
*
* @return the selected IPv4 BGP routes among all BGP sessions
*/
public Collection<BgpRouteEntry> getBgpRoutes4();
/**
* Gets the selected IPv6 BGP routes among all BGP sessions.
*
* @return the selected IPv6 BGP routes among all BGP sessions
*/
public Collection<BgpRouteEntry> getBgpRoutes6();
}
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
......
......@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
......
......@@ -13,12 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.MessageHeaderError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -117,8 +116,8 @@ final class BgpNotification {
* @return the message to transmit (BGP header included)
*/
static ChannelBuffer prepareBgpNotificationBadMessageLength(int length) {
int errorCode = MessageHeaderError.ERROR_CODE;
int errorSubcode = MessageHeaderError.BAD_MESSAGE_LENGTH;
int errorCode = BgpConstants.Notifications.MessageHeaderError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.MessageHeaderError.BAD_MESSAGE_LENGTH;
ChannelBuffer data = ChannelBuffers.buffer(2);
data.writeShort(length);
......
......@@ -13,18 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.onlab.packet.Ip4Address;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.OpenMessageError;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.MultiprotocolExtensions;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.As4Octet;
import org.onosproject.sdnip.bgp.BgpMessage.BgpParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -86,8 +80,8 @@ final class BgpOpen {
// ERROR: Unsupported Version Number
//
// Send NOTIFICATION and close the connection
int errorCode = OpenMessageError.ERROR_CODE;
int errorSubcode = OpenMessageError.UNSUPPORTED_VERSION_NUMBER;
int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.OpenMessageError.UNSUPPORTED_VERSION_NUMBER;
ChannelBuffer data = ChannelBuffers.buffer(2);
data.writeShort(BgpConstants.BGP_VERSION);
ChannelBuffer txMessage =
......@@ -123,8 +117,8 @@ final class BgpOpen {
// ERROR: Unacceptable Hold Time
//
// Send NOTIFICATION and close the connection
int errorCode = OpenMessageError.ERROR_CODE;
int errorSubcode = OpenMessageError.UNACCEPTABLE_HOLD_TIME;
int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.OpenMessageError.UNACCEPTABLE_HOLD_TIME;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
null);
......@@ -149,7 +143,7 @@ final class BgpOpen {
// Parse the Optional Parameters
try {
parseOptionalParameters(bgpSession, ctx, message);
} catch (BgpParseException e) {
} catch (BgpMessage.BgpParseException e) {
// ERROR: Error parsing optional parameters
log.debug("BGP RX OPEN Error from {}: " +
"Exception parsing Optional Parameters: {}",
......@@ -158,8 +152,8 @@ final class BgpOpen {
// ERROR: Invalid Optional Parameters: Unspecific
//
// Send NOTIFICATION and close the connection
int errorCode = OpenMessageError.ERROR_CODE;
int errorSubcode = Notifications.ERROR_SUBCODE_UNSPECIFIC;
int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
null);
......@@ -202,8 +196,8 @@ final class BgpOpen {
// ERROR: Bad Peer AS
//
// Send NOTIFICATION and close the connection
int errorCode = OpenMessageError.ERROR_CODE;
int errorSubcode = OpenMessageError.BAD_PEER_AS;
int errorCode = BgpConstants.Notifications.OpenMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.OpenMessageError.BAD_PEER_AS;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode,
errorSubcode, null);
......@@ -268,12 +262,12 @@ final class BgpOpen {
* @param bgpSession the BGP Session to use
* @param ctx the Channel Handler Context
* @param message the message to process
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static void parseOptionalParameters(BgpSession bgpSession,
ChannelHandlerContext ctx,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
//
// Get and verify the Optional Parameters Length
......@@ -284,7 +278,7 @@ final class BgpOpen {
String errorMsg = "Invalid Optional Parameter Length field " +
optParamLength + ". Remaining Optional Parameters " +
message.readableBytes();
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
if (optParamLength == 0) {
return; // No Optional Parameters
......@@ -299,25 +293,25 @@ final class BgpOpen {
if (message.readerIndex() >= optParamEnd) {
// ERROR: Malformed Optional Parameters
String errorMsg = "Malformed Optional Parameters";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
int paramLen = message.readUnsignedByte();
if (message.readerIndex() + paramLen > optParamEnd) {
// ERROR: Malformed Optional Parameters
String errorMsg = "Malformed Optional Parameters";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
//
// Extract the Optional Parameter Value based on the Parameter Type
//
switch (paramType) {
case Capabilities.TYPE:
case BgpConstants.Open.Capabilities.TYPE:
// Optional Parameter Type: Capabilities
if (paramLen < Capabilities.MIN_LENGTH) {
if (paramLen < BgpConstants.Open.Capabilities.MIN_LENGTH) {
// ERROR: Malformed Capability
String errorMsg = "Malformed Capability Type " + paramType;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
int capabEnd = message.readerIndex() + paramLen;
int capabCode = message.readUnsignedByte();
......@@ -325,16 +319,16 @@ final class BgpOpen {
if (message.readerIndex() + capabLen > capabEnd) {
// ERROR: Malformed Capability
String errorMsg = "Malformed Capability Type " + paramType;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
switch (capabCode) {
case MultiprotocolExtensions.CODE:
case BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE:
// Multiprotocol Extensions Capabilities (RFC 4760)
if (capabLen != MultiprotocolExtensions.LENGTH) {
if (capabLen != BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH) {
// ERROR: Multiprotocol Extension Length Error
String errorMsg = "Multiprotocol Extension Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// Decode the AFI (2 octets) and SAFI (1 octet)
int afi = message.readUnsignedShort();
......@@ -348,20 +342,20 @@ final class BgpOpen {
// NOTE: For now we just copy the remote AFI/SAFI setting
// to the local configuration.
//
if (afi == MultiprotocolExtensions.AFI_IPV4 &&
safi == MultiprotocolExtensions.SAFI_UNICAST) {
if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4 &&
safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST) {
bgpSession.remoteInfo().setIpv4Unicast();
bgpSession.localInfo().setIpv4Unicast();
} else if (afi == MultiprotocolExtensions.AFI_IPV4 &&
safi == MultiprotocolExtensions.SAFI_MULTICAST) {
} else if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4 &&
safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST) {
bgpSession.remoteInfo().setIpv4Multicast();
bgpSession.localInfo().setIpv4Multicast();
} else if (afi == MultiprotocolExtensions.AFI_IPV6 &&
safi == MultiprotocolExtensions.SAFI_UNICAST) {
} else if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6 &&
safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST) {
bgpSession.remoteInfo().setIpv6Unicast();
bgpSession.localInfo().setIpv6Unicast();
} else if (afi == MultiprotocolExtensions.AFI_IPV6 &&
safi == MultiprotocolExtensions.SAFI_MULTICAST) {
} else if (afi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6 &&
safi == BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST) {
bgpSession.remoteInfo().setIpv6Multicast();
bgpSession.localInfo().setIpv6Multicast();
} else {
......@@ -370,12 +364,12 @@ final class BgpOpen {
}
break;
case Capabilities.As4Octet.CODE:
case BgpConstants.Open.Capabilities.As4Octet.CODE:
// Support for 4-octet AS Number Capabilities (RFC 6793)
if (capabLen != Capabilities.As4Octet.LENGTH) {
if (capabLen != BgpConstants.Open.Capabilities.As4Octet.LENGTH) {
// ERROR: 4-octet AS Number Capability Length Error
String errorMsg = "4-octet AS Number Capability Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
long as4Number = message.readUnsignedInt();
......@@ -430,56 +424,72 @@ final class BgpOpen {
// IPv4 unicast
if (localInfo.ipv4Unicast()) {
message.writeByte(Capabilities.TYPE); // Param type
message.writeByte(Capabilities.MIN_LENGTH +
MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(MultiprotocolExtensions.AFI_IPV4);
message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4);
message.writeByte(0); // Reserved field
message.writeByte(MultiprotocolExtensions.SAFI_UNICAST);
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST);
}
// IPv4 multicast
if (localInfo.ipv4Multicast()) {
message.writeByte(Capabilities.TYPE); // Param type
message.writeByte(Capabilities.MIN_LENGTH +
MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(MultiprotocolExtensions.AFI_IPV4);
message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4);
message.writeByte(0); // Reserved field
message.writeByte(MultiprotocolExtensions.SAFI_MULTICAST);
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST);
}
// IPv6 unicast
if (localInfo.ipv6Unicast()) {
message.writeByte(Capabilities.TYPE); // Param type
message.writeByte(Capabilities.MIN_LENGTH +
MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(MultiprotocolExtensions.AFI_IPV6);
message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6);
message.writeByte(0); // Reserved field
message.writeByte(MultiprotocolExtensions.SAFI_UNICAST);
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST);
}
// IPv6 multicast
if (localInfo.ipv6Multicast()) {
message.writeByte(Capabilities.TYPE); // Param type
message.writeByte(Capabilities.MIN_LENGTH +
MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(MultiprotocolExtensions.AFI_IPV6);
message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Param len
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.CODE); // Capab. code
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.LENGTH); // Capab. len
message.writeShort(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6);
message.writeByte(0); // Reserved field
message.writeByte(MultiprotocolExtensions.SAFI_MULTICAST);
message.writeByte(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_MULTICAST);
}
// 4 octet AS path capability
if (localInfo.as4OctetCapability()) {
message.writeByte(Capabilities.TYPE); // Param type
message.writeByte(Capabilities.MIN_LENGTH +
As4Octet.LENGTH); // Param len
message.writeByte(As4Octet.CODE); // Capab. code
message.writeByte(As4Octet.LENGTH); // Capab. len
message.writeByte(BgpConstants.Open.Capabilities.TYPE); // Param type
message.writeByte(BgpConstants.Open.Capabilities.MIN_LENGTH +
BgpConstants.Open.Capabilities.As4Octet.LENGTH); // Param len
message.writeByte(BgpConstants.Open.Capabilities.As4Octet.CODE); // Capab. code
message.writeByte(BgpConstants.Open.Capabilities.As4Octet.LENGTH); // Capab. len
message.writeInt((int) localInfo.as4Number());
}
return message;
......
......@@ -13,20 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.MoreObjects;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.routingapi.RouteEntry;
import java.util.ArrayList;
import java.util.Objects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.Ip4Address;
import org.onosproject.sdnip.RouteEntry;
import org.onosproject.sdnip.bgp.BgpConstants.Update;
import com.google.common.base.MoreObjects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a route in BGP.
......@@ -37,7 +35,7 @@ public class BgpRouteEntry extends RouteEntry {
private final byte origin; // Route ORIGIN: IGP, EGP, INCOMPLETE
private final AsPath asPath; // The AS Path
private final long localPref; // The local preference for the route
private long multiExitDisc = Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC;
private long multiExitDisc = BgpConstants.Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC;
/**
* Class constructor.
......@@ -129,8 +127,8 @@ public class BgpRouteEntry extends RouteEntry {
// Find the first Path Segment by ignoring the AS_CONFED_* segments
for (PathSegment pathSegment : asPath.getPathSegments()) {
if ((pathSegment.getType() == Update.AsPath.AS_SET) ||
(pathSegment.getType() == Update.AsPath.AS_SEQUENCE)) {
if ((pathSegment.getType() == BgpConstants.Update.AsPath.AS_SET) ||
(pathSegment.getType() == BgpConstants.Update.AsPath.AS_SEQUENCE)) {
firstPathSegment = pathSegment;
break;
}
......@@ -139,7 +137,7 @@ public class BgpRouteEntry extends RouteEntry {
return true; // Local route: no path segments
}
// If the first path segment is AS_SET, the route is considered local
if (firstPathSegment.getType() == Update.AsPath.AS_SET) {
if (firstPathSegment.getType() == BgpConstants.Update.AsPath.AS_SET) {
return true;
}
......@@ -164,8 +162,8 @@ public class BgpRouteEntry extends RouteEntry {
// Find the first Path Segment by ignoring the AS_CONFED_* segments
for (PathSegment pathSegment : asPath.getPathSegments()) {
if ((pathSegment.getType() == Update.AsPath.AS_SET) ||
(pathSegment.getType() == Update.AsPath.AS_SEQUENCE)) {
if ((pathSegment.getType() == BgpConstants.Update.AsPath.AS_SET) ||
(pathSegment.getType() == BgpConstants.Update.AsPath.AS_SEQUENCE)) {
firstPathSegment = pathSegment;
break;
}
......@@ -340,7 +338,7 @@ public class BgpRouteEntry extends RouteEntry {
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("type", Update.AsPath.typeToString(type))
.add("type", BgpConstants.Update.AsPath.typeToString(type))
.add("segmentAsNumbers", this.segmentAsNumbers)
.toString();
}
......@@ -370,16 +368,16 @@ public class BgpRouteEntry extends RouteEntry {
int pl = 0;
for (PathSegment pathSegment : pathSegments) {
switch (pathSegment.getType()) {
case Update.AsPath.AS_SET:
case BgpConstants.Update.AsPath.AS_SET:
pl++; // AS_SET counts as 1
break;
case Update.AsPath.AS_SEQUENCE:
case BgpConstants.Update.AsPath.AS_SEQUENCE:
// Count each AS number
pl += pathSegment.getSegmentAsNumbers().size();
break;
case Update.AsPath.AS_CONFED_SEQUENCE:
case BgpConstants.Update.AsPath.AS_CONFED_SEQUENCE:
break; // Ignore
case Update.AsPath.AS_CONFED_SET:
case BgpConstants.Update.AsPath.AS_CONFED_SET:
break; // Ignore
default:
// NOTE: What to do if the Path Segment type is unknown?
......@@ -487,7 +485,7 @@ public class BgpRouteEntry extends RouteEntry {
.add("prefix", prefix())
.add("nextHop", nextHop())
.add("bgpId", bgpSession.remoteInfo().bgpId())
.add("origin", Update.Origin.typeToString(origin))
.add("origin", BgpConstants.Update.Origin.typeToString(origin))
.add("asPath", asPath)
.add("localPref", localPref)
.add("multiExitDisc", multiExitDisc)
......
......@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
import java.util.Collection;
import java.util.LinkedList;
package org.onosproject.routing.bgp;
import org.onlab.packet.IpPrefix;
import org.onosproject.sdnip.RouteUpdate;
import org.onosproject.routingapi.RouteUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.LinkedList;
/**
* Class to receive and process the BGP routes from each BGP Session/Peer.
*/
......
......@@ -13,15 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
......@@ -32,15 +24,21 @@ import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.Timer;
import org.jboss.netty.util.TimerTask;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Prefix;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.HoldTimerExpired;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/**
* Class for handling the BGP peer sessions.
* There is one instance per each BGP peer session.
......@@ -463,8 +461,8 @@ public class BgpSession extends SimpleChannelHandler {
// ERROR: Invalid Optional Parameter Length field: Unspecific
//
// Send NOTIFICATION and close the connection
int errorCode = HoldTimerExpired.ERROR_CODE;
int errorSubcode = Notifications.ERROR_SUBCODE_UNSPECIFIC;
int errorCode = BgpConstants.Notifications.HoldTimerExpired.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
null);
......
......@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import java.net.SocketAddress;
import org.onlab.packet.Ip4Address;
import java.net.SocketAddress;
/**
* Class for keeping information about a BGP session.
*
......
......@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelException;
......@@ -29,7 +31,8 @@ import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.IpPrefix;
import org.onosproject.sdnip.RouteListener;
import org.onosproject.routingapi.BgpService;
import org.onosproject.routingapi.RouteListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -47,7 +50,9 @@ import static org.onlab.util.Tools.namedThreads;
/**
* BGP Session Manager class.
*/
public class BgpSessionManager {
@Component(immediate = true)
@Service
public class BgpSessionManager implements BgpInfoService, BgpService {
private static final Logger log =
LoggerFactory.getLogger(BgpSessionManager.class);
......@@ -65,16 +70,7 @@ public class BgpSessionManager {
private ConcurrentMap<Ip6Prefix, BgpRouteEntry> bgpRoutes6 =
new ConcurrentHashMap<>();
private final RouteListener routeListener;
/**
* Constructor for given route listener.
*
* @param routeListener the route listener to use
*/
public BgpSessionManager(RouteListener routeListener) {
this.routeListener = checkNotNull(routeListener);
}
private RouteListener routeListener;
/**
* Checks whether the BGP Session Manager is shutdown.
......@@ -248,16 +244,13 @@ public class BgpSessionManager {
return bgpRouteSelector;
}
/**
* Starts up BGP Session Manager operation.
*
* @param listenPortNumber the port number to listen on. By default
* it should be BgpConstants.BGP_PORT (179)
*/
public void start(int listenPortNumber) {
@Override
public void start(RouteListener routeListener, int listenPortNumber) {
log.debug("BGP Session Manager start.");
isShutdown = false;
this.routeListener = checkNotNull(routeListener);
ChannelFactory channelFactory = new NioServerSocketChannelFactory(
newCachedThreadPool(namedThreads("onos-bgp-sm-boss-%d")),
newCachedThreadPool(namedThreads("onos-bgp-sm-worker-%d")));
......@@ -294,9 +287,7 @@ public class BgpSessionManager {
}
}
/**
* Stops the BGP Session Manager operation.
*/
@Override
public void stop() {
isShutdown = true;
allChannels.close().awaitUninterruptibly();
......
......@@ -13,12 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
package org.onosproject.routing.bgp;
import org.apache.commons.lang3.tuple.Pair;
import org.jboss.netty.buffer.ChannelBuffer;
......@@ -28,14 +23,14 @@ import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.Ip6Prefix;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.UpdateMessageError;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.MultiprotocolExtensions;
import org.onosproject.sdnip.bgp.BgpConstants.Update;
import org.onosproject.sdnip.bgp.BgpConstants.Update.AsPath;
import org.onosproject.sdnip.bgp.BgpMessage.BgpParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* A class for handling BGP UPDATE messages.
*/
......@@ -102,7 +97,7 @@ final class BgpUpdate {
try {
withdrawnPrefixes = parsePackedIp4Prefixes(withdrawnRoutesLength,
message);
} catch (BgpParseException e) {
} catch (BgpMessage.BgpParseException e) {
// ERROR: Invalid Network Field
log.debug("Exception parsing Withdrawn Prefixes from BGP peer {}: ",
bgpSession.remoteInfo().bgpId(), e);
......@@ -124,7 +119,7 @@ final class BgpUpdate {
//
try {
parsePathAttributes(bgpSession, ctx, message, decodedBgpRoutes);
} catch (BgpParseException e) {
} catch (BgpMessage.BgpParseException e) {
log.debug("Exception parsing Path Attributes from BGP peer {}: ",
bgpSession.remoteInfo().bgpId(), e);
// NOTE: The session was already closed, so nothing else to do
......@@ -179,7 +174,7 @@ final class BgpUpdate {
* @param decodedBgpRoutes the container to store the decoded BGP Route
* Entries. It might already contain some route entries such as withdrawn
* IPv4 prefixes
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
// CHECKSTYLE IGNORE MethodLength FOR NEXT 300 LINES
private static void parsePathAttributes(
......@@ -187,7 +182,7 @@ final class BgpUpdate {
ChannelHandlerContext ctx,
ChannelBuffer message,
DecodedBgpRoutes decodedBgpRoutes)
throws BgpParseException {
throws BgpMessage.BgpParseException {
//
// Parsed values
......@@ -195,10 +190,11 @@ final class BgpUpdate {
Short origin = -1; // Mandatory
BgpRouteEntry.AsPath asPath = null; // Mandatory
// Legacy NLRI (RFC 4271). Mandatory NEXT_HOP if legacy NLRI is used
MpNlri legacyNlri = new MpNlri(MultiprotocolExtensions.AFI_IPV4,
MultiprotocolExtensions.SAFI_UNICAST);
MpNlri legacyNlri = new MpNlri(
BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4,
BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST);
long multiExitDisc = // Optional
Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC;
BgpConstants.Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC;
Long localPref = null; // Mandatory
Long aggregatorAsNumber = null; // Optional: unused
Ip4Address aggregatorIpAddress = null; // Optional: unused
......@@ -213,7 +209,7 @@ final class BgpUpdate {
// ERROR: Malformed Attribute List
actionsBgpUpdateMalformedAttributeList(bgpSession, ctx);
String errorMsg = "Malformed Attribute List";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
if (pathAttributeLength == 0) {
return;
......@@ -229,7 +225,7 @@ final class BgpUpdate {
// ERROR: Malformed Attribute List
actionsBgpUpdateMalformedAttributeList(bgpSession, ctx);
String errorMsg = "Malformed Attribute List";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
int attrTypeCode = message.readUnsignedByte();
......@@ -249,7 +245,7 @@ final class BgpUpdate {
// ERROR: Malformed Attribute List
actionsBgpUpdateMalformedAttributeList(bgpSession, ctx);
String errorMsg = "Malformed Attribute List";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
if (extendedLengthBit) {
attrLen = message.readUnsignedShort();
......@@ -260,7 +256,7 @@ final class BgpUpdate {
// ERROR: Malformed Attribute List
actionsBgpUpdateMalformedAttributeList(bgpSession, ctx);
String errorMsg = "Malformed Attribute List";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// Verify the Attribute Flags
......@@ -272,21 +268,21 @@ final class BgpUpdate {
//
switch (attrTypeCode) {
case Update.Origin.TYPE:
case BgpConstants.Update.Origin.TYPE:
// Attribute Type Code ORIGIN
origin = parseAttributeTypeOrigin(bgpSession, ctx,
attrTypeCode, attrLen,
attrFlags, message);
break;
case Update.AsPath.TYPE:
case BgpConstants.Update.AsPath.TYPE:
// Attribute Type Code AS_PATH
asPath = parseAttributeTypeAsPath(bgpSession, ctx,
attrTypeCode, attrLen,
attrFlags, message);
break;
case Update.NextHop.TYPE:
case BgpConstants.Update.NextHop.TYPE:
// Attribute Type Code NEXT_HOP
legacyNlri.nextHop4 =
parseAttributeTypeNextHop(bgpSession, ctx,
......@@ -294,7 +290,7 @@ final class BgpUpdate {
attrFlags, message);
break;
case Update.MultiExitDisc.TYPE:
case BgpConstants.Update.MultiExitDisc.TYPE:
// Attribute Type Code MULTI_EXIT_DISC
multiExitDisc =
parseAttributeTypeMultiExitDisc(bgpSession, ctx,
......@@ -302,7 +298,7 @@ final class BgpUpdate {
attrFlags, message);
break;
case Update.LocalPref.TYPE:
case BgpConstants.Update.LocalPref.TYPE:
// Attribute Type Code LOCAL_PREF
localPref =
parseAttributeTypeLocalPref(bgpSession, ctx,
......@@ -310,7 +306,7 @@ final class BgpUpdate {
attrFlags, message);
break;
case Update.AtomicAggregate.TYPE:
case BgpConstants.Update.AtomicAggregate.TYPE:
// Attribute Type Code ATOMIC_AGGREGATE
parseAttributeTypeAtomicAggregate(bgpSession, ctx,
attrTypeCode, attrLen,
......@@ -318,7 +314,7 @@ final class BgpUpdate {
// Nothing to do: this attribute is primarily informational
break;
case Update.Aggregator.TYPE:
case BgpConstants.Update.Aggregator.TYPE:
// Attribute Type Code AGGREGATOR
Pair<Long, Ip4Address> aggregator =
parseAttributeTypeAggregator(bgpSession, ctx,
......@@ -328,7 +324,7 @@ final class BgpUpdate {
aggregatorIpAddress = aggregator.getRight();
break;
case Update.MpReachNlri.TYPE:
case BgpConstants.Update.MpReachNlri.TYPE:
// Attribute Type Code MP_REACH_NLRI
MpNlri mpNlriReach =
parseAttributeTypeMpReachNlri(bgpSession, ctx,
......@@ -340,7 +336,7 @@ final class BgpUpdate {
}
break;
case Update.MpUnreachNlri.TYPE:
case BgpConstants.Update.MpUnreachNlri.TYPE:
// Attribute Type Code MP_UNREACH_NLRI
MpNlri mpNlriUnreach =
parseAttributeTypeMpUnreachNlri(bgpSession, ctx,
......@@ -360,7 +356,7 @@ final class BgpUpdate {
message);
String errorMsg = "Unrecognized Well-known Attribute: " +
attrTypeCode;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// Skip the data from the unrecognized attribute
......@@ -381,7 +377,7 @@ final class BgpUpdate {
parsePackedIp4Prefixes(nlriLength, message);
// Store it inside the legacy NLRI wrapper
legacyNlri.nlri4 = addedPrefixes4;
} catch (BgpParseException e) {
} catch (BgpMessage.BgpParseException e) {
// ERROR: Invalid Network Field
log.debug("Exception parsing NLRI from BGP peer {}: ",
bgpSession.remoteInfo().bgpId(), e);
......@@ -486,7 +482,7 @@ final class BgpUpdate {
* @param legacyNlri the legacy NLRI. Encapsulates the NEXT_HOP well-known
* mandatory attribute (mandatory if legacy NLRI is used).
* @param mpNlriReachList the Multiprotocol NLRI attributes
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static void verifyBgpUpdateWellKnownAttributes(
BgpSession bgpSession,
......@@ -496,7 +492,7 @@ final class BgpUpdate {
Long localPref,
MpNlri legacyNlri,
Collection<MpNlri> mpNlriReachList)
throws BgpParseException {
throws BgpMessage.BgpParseException {
boolean hasNlri = false;
boolean hasLegacyNlri = false;
......@@ -525,32 +521,32 @@ final class BgpUpdate {
//
if (hasNlri && ((origin == null) || (origin == -1))) {
// Missing Attribute Type Code ORIGIN
int type = Update.Origin.TYPE;
int type = BgpConstants.Update.Origin.TYPE;
actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
String errorMsg = "Missing Well-known Attribute: ORIGIN";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
if (hasNlri && (asPath == null)) {
// Missing Attribute Type Code AS_PATH
int type = Update.AsPath.TYPE;
int type = BgpConstants.Update.AsPath.TYPE;
actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
String errorMsg = "Missing Well-known Attribute: AS_PATH";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
if (hasNlri && (localPref == null)) {
// Missing Attribute Type Code LOCAL_PREF
// NOTE: Required for iBGP
int type = Update.LocalPref.TYPE;
int type = BgpConstants.Update.LocalPref.TYPE;
actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
String errorMsg = "Missing Well-known Attribute: LOCAL_PREF";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
if (hasLegacyNlri && (legacyNlri.nextHop4 == null)) {
// Missing Attribute Type Code NEXT_HOP
int type = Update.NextHop.TYPE;
int type = BgpConstants.Update.NextHop.TYPE;
actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
String errorMsg = "Missing Well-known Attribute: NEXT_HOP";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
}
......@@ -563,7 +559,7 @@ final class BgpUpdate {
* @param attrLen the attribute length (in octets)
* @param attrFlags the attribute flags
* @param message the message to parse
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static void verifyBgpUpdateAttributeFlags(
BgpSession bgpSession,
......@@ -572,7 +568,7 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
//
// Assign the Attribute Type Name and the Well-known flag
......@@ -580,39 +576,39 @@ final class BgpUpdate {
String typeName = "UNKNOWN";
boolean isWellKnown = false;
switch (attrTypeCode) {
case Update.Origin.TYPE:
case BgpConstants.Update.Origin.TYPE:
isWellKnown = true;
typeName = "ORIGIN";
break;
case Update.AsPath.TYPE:
case BgpConstants.Update.AsPath.TYPE:
isWellKnown = true;
typeName = "AS_PATH";
break;
case Update.NextHop.TYPE:
case BgpConstants.Update.NextHop.TYPE:
isWellKnown = true;
typeName = "NEXT_HOP";
break;
case Update.MultiExitDisc.TYPE:
case BgpConstants.Update.MultiExitDisc.TYPE:
isWellKnown = false;
typeName = "MULTI_EXIT_DISC";
break;
case Update.LocalPref.TYPE:
case BgpConstants.Update.LocalPref.TYPE:
isWellKnown = true;
typeName = "LOCAL_PREF";
break;
case Update.AtomicAggregate.TYPE:
case BgpConstants.Update.AtomicAggregate.TYPE:
isWellKnown = true;
typeName = "ATOMIC_AGGREGATE";
break;
case Update.Aggregator.TYPE:
case BgpConstants.Update.Aggregator.TYPE:
isWellKnown = false;
typeName = "AGGREGATOR";
break;
case Update.MpReachNlri.TYPE:
case BgpConstants.Update.MpReachNlri.TYPE:
isWellKnown = false;
typeName = "MP_REACH_NLRI";
break;
case Update.MpUnreachNlri.TYPE:
case BgpConstants.Update.MpUnreachNlri.TYPE:
isWellKnown = false;
typeName = "MP_UNREACH_NLRI";
break;
......@@ -643,7 +639,7 @@ final class BgpUpdate {
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Flags Error for " + typeName + ": " +
attrFlags;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
}
......@@ -657,7 +653,7 @@ final class BgpUpdate {
* @param attrFlags the attribute flags
* @param message the message to parse
* @return the parsed ORIGIN value
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static short parseAttributeTypeOrigin(
BgpSession bgpSession,
......@@ -666,25 +662,25 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
// Check the Attribute Length
if (attrLen != Update.Origin.LENGTH) {
if (attrLen != BgpConstants.Update.Origin.LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
message.markReaderIndex();
short origin = message.readUnsignedByte();
switch (origin) {
case Update.Origin.IGP:
case BgpConstants.Update.Origin.IGP:
// FALLTHROUGH
case Update.Origin.EGP:
case BgpConstants.Update.Origin.EGP:
// FALLTHROUGH
case Update.Origin.INCOMPLETE:
case BgpConstants.Update.Origin.INCOMPLETE:
break;
default:
// ERROR: Invalid ORIGIN Attribute
......@@ -693,7 +689,7 @@ final class BgpUpdate {
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message,
origin);
String errorMsg = "Invalid ORIGIN Attribute: " + origin;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
return origin;
......@@ -709,7 +705,7 @@ final class BgpUpdate {
* @param attrFlags the attribute flags
* @param message the message to parse
* @return the parsed AS Path
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static BgpRouteEntry.AsPath parseAttributeTypeAsPath(
BgpSession bgpSession,
......@@ -718,7 +714,7 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
//
......@@ -729,7 +725,7 @@ final class BgpUpdate {
// ERROR: Malformed AS_PATH
actionsBgpUpdateMalformedAsPath(bgpSession, ctx);
String errorMsg = "Malformed AS Path";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// Get the Path Segment Type and Length (in number of ASes)
short pathSegmentType = message.readUnsignedByte();
......@@ -738,13 +734,13 @@ final class BgpUpdate {
// Verify the Path Segment Type
switch (pathSegmentType) {
case Update.AsPath.AS_SET:
case BgpConstants.Update.AsPath.AS_SET:
// FALLTHROUGH
case Update.AsPath.AS_SEQUENCE:
case BgpConstants.Update.AsPath.AS_SEQUENCE:
// FALLTHROUGH
case Update.AsPath.AS_CONFED_SEQUENCE:
case BgpConstants.Update.AsPath.AS_CONFED_SEQUENCE:
// FALLTHROUGH
case Update.AsPath.AS_CONFED_SET:
case BgpConstants.Update.AsPath.AS_CONFED_SET:
break;
default:
// ERROR: Invalid Path Segment Type
......@@ -756,15 +752,15 @@ final class BgpUpdate {
actionsBgpUpdateMalformedAsPath(bgpSession, ctx);
String errorMsg =
"Invalid AS Path Segment Type: " + pathSegmentType;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// 4-octet AS number handling.
int asPathLen;
if (bgpSession.isAs4OctetCapable()) {
asPathLen = AsPath.AS_4OCTET_LENGTH;
asPathLen = BgpConstants.Update.AsPath.AS_4OCTET_LENGTH;
} else {
asPathLen = AsPath.AS_LENGTH;
asPathLen = BgpConstants.Update.AsPath.AS_LENGTH;
}
// Parse the AS numbers
......@@ -772,13 +768,13 @@ final class BgpUpdate {
// ERROR: Malformed AS_PATH
actionsBgpUpdateMalformedAsPath(bgpSession, ctx);
String errorMsg = "Malformed AS Path";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
attrLen -= (asPathLen * pathSegmentLength);
ArrayList<Long> segmentAsNumbers = new ArrayList<>();
while (pathSegmentLength-- > 0) {
long asNumber;
if (asPathLen == AsPath.AS_4OCTET_LENGTH) {
if (asPathLen == BgpConstants.Update.AsPath.AS_4OCTET_LENGTH) {
asNumber = message.readUnsignedInt();
} else {
asNumber = message.readUnsignedShort();
......@@ -805,7 +801,7 @@ final class BgpUpdate {
* @param attrFlags the attribute flags
* @param message the message to parse
* @return the parsed NEXT_HOP value
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static Ip4Address parseAttributeTypeNextHop(
BgpSession bgpSession,
......@@ -814,15 +810,15 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
// Check the Attribute Length
if (attrLen != Update.NextHop.LENGTH) {
if (attrLen != BgpConstants.Update.NextHop.LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
message.markReaderIndex();
......@@ -845,7 +841,7 @@ final class BgpUpdate {
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message,
nextHopAddress);
String errorMsg = "Invalid NEXT_HOP Attribute: " + nextHopAddress;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
return nextHopAddress;
......@@ -861,7 +857,7 @@ final class BgpUpdate {
* @param attrFlags the attribute flags
* @param message the message to parse
* @return the parsed MULTI_EXIT_DISC value
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static long parseAttributeTypeMultiExitDisc(
BgpSession bgpSession,
......@@ -870,15 +866,15 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
// Check the Attribute Length
if (attrLen != Update.MultiExitDisc.LENGTH) {
if (attrLen != BgpConstants.Update.MultiExitDisc.LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
long multiExitDisc = message.readUnsignedInt();
......@@ -895,7 +891,7 @@ final class BgpUpdate {
* @param attrFlags the attribute flags
* @param message the message to parse
* @return the parsed LOCAL_PREF value
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static long parseAttributeTypeLocalPref(
BgpSession bgpSession,
......@@ -904,15 +900,15 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
// Check the Attribute Length
if (attrLen != Update.LocalPref.LENGTH) {
if (attrLen != BgpConstants.Update.LocalPref.LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
long localPref = message.readUnsignedInt();
......@@ -928,7 +924,7 @@ final class BgpUpdate {
* @param attrLen the attribute length (in octets)
* @param attrFlags the attribute flags
* @param message the message to parse
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static void parseAttributeTypeAtomicAggregate(
BgpSession bgpSession,
......@@ -937,15 +933,15 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
// Check the Attribute Length
if (attrLen != Update.AtomicAggregate.LENGTH) {
if (attrLen != BgpConstants.Update.AtomicAggregate.LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// Nothing to do: this attribute is primarily informational
......@@ -961,7 +957,7 @@ final class BgpUpdate {
* @param attrFlags the attribute flags
* @param message the message to parse
* @return the parsed AGGREGATOR value: a tuple of <AS-Number, IP-Address>
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static Pair<Long, Ip4Address> parseAttributeTypeAggregator(
BgpSession bgpSession,
......@@ -970,15 +966,15 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
// Check the Attribute Length
if (attrLen != Update.Aggregator.LENGTH) {
if (attrLen != BgpConstants.Update.Aggregator.LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// The AGGREGATOR AS number
......@@ -1003,7 +999,7 @@ final class BgpUpdate {
* @param message the message to parse
* @return the parsed MP_REACH_NLRI information if recognized, otherwise
* null
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static MpNlri parseAttributeTypeMpReachNlri(
BgpSession bgpSession,
......@@ -1012,16 +1008,16 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
int attributeEnd = message.readerIndex() + attrLen;
// Check the Attribute Length
if (attrLen < Update.MpReachNlri.MIN_LENGTH) {
if (attrLen < BgpConstants.Update.MpReachNlri.MIN_LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
message.markReaderIndex();
......@@ -1033,9 +1029,9 @@ final class BgpUpdate {
// Verify the AFI/SAFI, and skip the attribute if not recognized.
// NOTE: Currently, we support only IPv4/IPv6 UNICAST
//
if (((afi != MultiprotocolExtensions.AFI_IPV4) &&
(afi != MultiprotocolExtensions.AFI_IPV6)) ||
(safi != MultiprotocolExtensions.SAFI_UNICAST)) {
if (((afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4) &&
(afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6)) ||
(safi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST)) {
// Skip the attribute
message.resetReaderIndex();
message.skipBytes(attrLen);
......@@ -1047,10 +1043,10 @@ final class BgpUpdate {
//
int expectedNextHopLen = 0;
switch (afi) {
case MultiprotocolExtensions.AFI_IPV4:
case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4:
expectedNextHopLen = Ip4Address.BYTE_LENGTH;
break;
case MultiprotocolExtensions.AFI_IPV6:
case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6:
expectedNextHopLen = Ip6Address.BYTE_LENGTH;
break;
default:
......@@ -1064,7 +1060,7 @@ final class BgpUpdate {
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Invalid next-hop network address length. " +
"Received " + nextHopLen + " expected " + expectedNextHopLen;
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
// NOTE: We use "+ 1" to take into account the Reserved field (1 octet)
if (message.readerIndex() + nextHopLen + 1 >= attributeEnd) {
......@@ -1073,7 +1069,7 @@ final class BgpUpdate {
actionsBgpUpdateOptionalAttributeError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Malformed next-hop network address";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
//
......@@ -1085,7 +1081,7 @@ final class BgpUpdate {
MpNlri mpNlri = new MpNlri(afi, safi);
try {
switch (afi) {
case MultiprotocolExtensions.AFI_IPV4:
case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4:
// The next-hop address
mpNlri.nextHop4 = Ip4Address.valueOf(nextHopBuffer);
// The NLRI
......@@ -1093,7 +1089,7 @@ final class BgpUpdate {
attributeEnd - message.readerIndex(),
message);
break;
case MultiprotocolExtensions.AFI_IPV6:
case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6:
// The next-hop address
mpNlri.nextHop6 = Ip6Address.valueOf(nextHopBuffer);
// The NLRI
......@@ -1105,13 +1101,13 @@ final class BgpUpdate {
// UNREACHABLE
break;
}
} catch (BgpParseException e) {
} catch (BgpMessage.BgpParseException e) {
// ERROR: Optional Attribute Error
message.resetReaderIndex();
actionsBgpUpdateOptionalAttributeError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Malformed network layer reachability information";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
return mpNlri;
......@@ -1128,7 +1124,7 @@ final class BgpUpdate {
* @param message the message to parse
* @return the parsed MP_UNREACH_NLRI information if recognized, otherwise
* null
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static MpNlri parseAttributeTypeMpUnreachNlri(
BgpSession bgpSession,
......@@ -1137,16 +1133,16 @@ final class BgpUpdate {
int attrLen,
int attrFlags,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
int attributeEnd = message.readerIndex() + attrLen;
// Check the Attribute Length
if (attrLen < Update.MpUnreachNlri.MIN_LENGTH) {
if (attrLen < BgpConstants.Update.MpUnreachNlri.MIN_LENGTH) {
// ERROR: Attribute Length Error
actionsBgpUpdateAttributeLengthError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Attribute Length Error";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
message.markReaderIndex();
......@@ -1157,9 +1153,9 @@ final class BgpUpdate {
// Verify the AFI/SAFI, and skip the attribute if not recognized.
// NOTE: Currently, we support only IPv4/IPv6 UNICAST
//
if (((afi != MultiprotocolExtensions.AFI_IPV4) &&
(afi != MultiprotocolExtensions.AFI_IPV6)) ||
(safi != MultiprotocolExtensions.SAFI_UNICAST)) {
if (((afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4) &&
(afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6)) ||
(safi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST)) {
// Skip the attribute
message.resetReaderIndex();
message.skipBytes(attrLen);
......@@ -1172,13 +1168,13 @@ final class BgpUpdate {
MpNlri mpNlri = new MpNlri(afi, safi);
try {
switch (afi) {
case MultiprotocolExtensions.AFI_IPV4:
case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4:
// The Withdrawn Routes
mpNlri.nlri4 = parsePackedIp4Prefixes(
attributeEnd - message.readerIndex(),
message);
break;
case MultiprotocolExtensions.AFI_IPV6:
case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6:
// The Withdrawn Routes
mpNlri.nlri6 = parsePackedIp6Prefixes(
attributeEnd - message.readerIndex(),
......@@ -1188,13 +1184,13 @@ final class BgpUpdate {
// UNREACHABLE
break;
}
} catch (BgpParseException e) {
} catch (BgpMessage.BgpParseException e) {
// ERROR: Optional Attribute Error
message.resetReaderIndex();
actionsBgpUpdateOptionalAttributeError(
bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
String errorMsg = "Malformed withdrawn routes";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
return mpNlri;
......@@ -1211,12 +1207,12 @@ final class BgpUpdate {
* @param totalLength the total length of the data to parse
* @param message the message with data to parse
* @return a collection of parsed IPv4 network prefixes
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static Collection<Ip4Prefix> parsePackedIp4Prefixes(
int totalLength,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
Collection<Ip4Prefix> result = new ArrayList<>();
if (totalLength == 0) {
......@@ -1231,7 +1227,7 @@ final class BgpUpdate {
int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
if (message.readerIndex() + prefixBytelen > dataEnd) {
String errorMsg = "Malformed Network Prefixes";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
message.readBytes(buffer, 0, prefixBytelen);
......@@ -1254,12 +1250,12 @@ final class BgpUpdate {
* @param totalLength the total length of the data to parse
* @param message the message with data to parse
* @return a collection of parsed IPv6 network prefixes
* @throws BgpParseException
* @throws BgpMessage.BgpParseException
*/
private static Collection<Ip6Prefix> parsePackedIp6Prefixes(
int totalLength,
ChannelBuffer message)
throws BgpParseException {
throws BgpMessage.BgpParseException {
Collection<Ip6Prefix> result = new ArrayList<>();
if (totalLength == 0) {
......@@ -1274,7 +1270,7 @@ final class BgpUpdate {
int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
if (message.readerIndex() + prefixBytelen > dataEnd) {
String errorMsg = "Malformed Network Prefixes";
throw new BgpParseException(errorMsg);
throw new BgpMessage.BgpParseException(errorMsg);
}
message.readBytes(buffer, 0, prefixBytelen);
......@@ -1303,8 +1299,8 @@ final class BgpUpdate {
// ERROR: Invalid Network Field
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.INVALID_NETWORK_FIELD;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.INVALID_NETWORK_FIELD;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
null);
......@@ -1329,8 +1325,8 @@ final class BgpUpdate {
// ERROR: Malformed Attribute List
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.MALFORMED_ATTRIBUTE_LIST;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.MALFORMED_ATTRIBUTE_LIST;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
null);
......@@ -1358,8 +1354,8 @@ final class BgpUpdate {
// ERROR: Missing Well-known Attribute
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.MISSING_WELL_KNOWN_ATTRIBUTE;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.MISSING_WELL_KNOWN_ATTRIBUTE;
ChannelBuffer data = ChannelBuffers.buffer(1);
data.writeByte(missingAttrTypeCode);
ChannelBuffer txMessage =
......@@ -1396,8 +1392,8 @@ final class BgpUpdate {
// ERROR: Invalid ORIGIN Attribute
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.INVALID_ORIGIN_ATTRIBUTE;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.INVALID_ORIGIN_ATTRIBUTE;
ChannelBuffer data =
prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen,
attrFlags, message);
......@@ -1433,8 +1429,8 @@ final class BgpUpdate {
// ERROR: Attribute Flags Error
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.ATTRIBUTE_FLAGS_ERROR;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.ATTRIBUTE_FLAGS_ERROR;
ChannelBuffer data =
prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen,
attrFlags, message);
......@@ -1473,8 +1469,8 @@ final class BgpUpdate {
// ERROR: Invalid NEXT_HOP Attribute
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.INVALID_NEXT_HOP_ATTRIBUTE;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.INVALID_NEXT_HOP_ATTRIBUTE;
ChannelBuffer data =
prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen,
attrFlags, message);
......@@ -1512,9 +1508,9 @@ final class BgpUpdate {
// ERROR: Unrecognized Well-known Attribute
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode =
UpdateMessageError.UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE;
BgpConstants.Notifications.UpdateMessageError.UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE;
ChannelBuffer data =
prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen,
attrFlags, message);
......@@ -1551,9 +1547,9 @@ final class BgpUpdate {
// ERROR: Optional Attribute Error
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode =
UpdateMessageError.OPTIONAL_ATTRIBUTE_ERROR;
BgpConstants.Notifications.UpdateMessageError.OPTIONAL_ATTRIBUTE_ERROR;
ChannelBuffer data =
prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen,
attrFlags, message);
......@@ -1589,8 +1585,8 @@ final class BgpUpdate {
// ERROR: Attribute Length Error
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.ATTRIBUTE_LENGTH_ERROR;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.ATTRIBUTE_LENGTH_ERROR;
ChannelBuffer data =
prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen,
attrFlags, message);
......@@ -1618,8 +1614,8 @@ final class BgpUpdate {
// ERROR: Malformed AS_PATH
//
// Send NOTIFICATION and close the connection
int errorCode = UpdateMessageError.ERROR_CODE;
int errorSubcode = UpdateMessageError.MALFORMED_AS_PATH;
int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE;
int errorSubcode = BgpConstants.Notifications.UpdateMessageError.MALFORMED_AS_PATH;
ChannelBuffer txMessage =
BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
null);
......
......@@ -17,4 +17,4 @@
/**
* Implementation of the BGP protocol.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
......
......@@ -13,9 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.cli;
import java.util.Collection;
package org.onosproject.routing.cli;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -24,8 +22,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.sdnip.SdnIpService;
import org.onosproject.sdnip.bgp.BgpSession;
import org.onosproject.routing.bgp.BgpInfoService;
import org.onosproject.routing.bgp.BgpSession;
import java.util.Collection;
/**
* Command to show the BGP neighbors.
......@@ -53,7 +53,7 @@ public class BgpNeighborsListCommand extends AbstractShellCommand {
@Override
protected void execute() {
SdnIpService service = get(SdnIpService.class);
BgpInfoService service = AbstractShellCommand.get(BgpInfoService.class);
Collection<BgpSession> bgpSessions = service.getBgpSessions();
if (bgpNeighbor != null) {
......
......@@ -13,10 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.cli;
import java.util.ArrayList;
import java.util.Collection;
package org.onosproject.routing.cli;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -25,10 +22,13 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.sdnip.SdnIpService;
import org.onosproject.sdnip.bgp.BgpConstants.Update;
import org.onosproject.sdnip.bgp.BgpRouteEntry;
import org.onosproject.sdnip.bgp.BgpSession;
import org.onosproject.routing.bgp.BgpConstants.Update;
import org.onosproject.routing.bgp.BgpInfoService;
import org.onosproject.routing.bgp.BgpRouteEntry;
import org.onosproject.routing.bgp.BgpSession;
import java.util.ArrayList;
import java.util.Collection;
/**
* Command to show the routes learned through BGP.
......@@ -59,7 +59,7 @@ public class BgpRoutesListCommand extends AbstractShellCommand {
@Override
protected void execute() {
SdnIpService service = get(SdnIpService.class);
BgpInfoService service = AbstractShellCommand.get(BgpInfoService.class);
// Print summary of the routes
if (routesSummary) {
......
......@@ -13,9 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.cli;
import java.util.Collection;
package org.onosproject.routing.cli;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -24,8 +22,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.sdnip.RouteEntry;
import org.onosproject.sdnip.SdnIpService;
import org.onosproject.routingapi.RouteEntry;
import org.onosproject.routingapi.RoutingService;
import java.util.Collection;
/**
* Command to show the list of routes in SDN-IP's routing table.
......@@ -49,7 +49,7 @@ public class RoutesListCommand extends AbstractShellCommand {
@Override
protected void execute() {
SdnIpService service = get(SdnIpService.class);
RoutingService service = AbstractShellCommand.get(RoutingService.class);
// Print summary of the routes
if (routesSummary) {
......
<!--
~ Copyright 2015 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.
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.routing.cli.BgpNeighborsListCommand"/>
</command>
<command>
<action class="org.onosproject.routing.cli.BgpRoutesListCommand"/>
</command>
<command>
<action class="org.onosproject.routing.cli.RoutesListCommand"/>
</command>
</command-bundle>
</blueprint>
/*
* Copyright 2014 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.routing;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.routing.Router.InternalHostListener;
import org.onosproject.routingapi.BgpService;
import org.onosproject.routingapi.FibEntry;
import org.onosproject.routingapi.FibListener;
import org.onosproject.routingapi.FibUpdate;
import org.onosproject.routingapi.RouteEntry;
import org.onosproject.routingapi.RouteListener;
import org.onosproject.routingapi.RouteUpdate;
import java.util.Collections;
import static org.easymock.EasyMock.*;
/**
* This class tests adding a route and updating a route.
* The HostService module answers the MAC address asynchronously.
*/
public class RouterAsyncArpTest {
private HostService hostService;
private FibListener fibListener;
private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000001"),
PortNumber.portNumber(1));
private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000002"),
PortNumber.portNumber(1));
private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000003"),
PortNumber.portNumber(1));
private Router router;
private InternalHostListener internalHostListener;
@Before
public void setUp() throws Exception {
hostService = createMock(HostService.class);
BgpService bgpService = createMock(BgpService.class);
bgpService.start(anyObject(RouteListener.class), anyInt());
bgpService.stop();
replay(bgpService);
fibListener = createMock(FibListener.class);
router = new Router();
router.hostService = hostService;
router.bgpService = bgpService;
router.activate();
router.start(fibListener);
internalHostListener = router.new InternalHostListener();
}
@After
public void tearDown() {
// Called during shutdown
reset(hostService);
hostService.removeListener(anyObject(HostListener.class));
router.stop();
}
/**
* Tests adding a route entry with asynchronous HostService replies.
*/
@Test
public void testRouteAdd() {
// Construct a route entry
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
IpAddress nextHopIp = Ip4Address.valueOf("192.168.10.1");
RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);
// Host service will reply with no hosts when asked
reset(hostService);
expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
Collections.emptySet()).anyTimes();
hostService.startMonitoringIp(IpAddress.valueOf("192.168.10.1"));
replay(hostService);
// Initially when we add the route, no FIB update will be sent
replay(fibListener);
router.processRouteUpdates(Collections.singletonList(
new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));
verify(fibListener);
// Now when we send the event, we expect the FIB update to be sent
reset(fibListener);
FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
MacAddress.valueOf("00:00:00:00:00:01"));
fibListener.update(Collections.singletonList(new FibUpdate(
FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());
replay(fibListener);
Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
new HostLocation(
SW1_ETH1.deviceId(),
SW1_ETH1.port(), 1),
Sets.newHashSet(IpAddress.valueOf("192.168.10.1")));
// Send in the host event
internalHostListener.event(
new HostEvent(HostEvent.Type.HOST_ADDED, host));
verify(fibListener);
}
/**
* Tests updating a route entry with asynchronous HostService replies.
*/
@Test
public void testRouteUpdate() {
// Add a route
testRouteAdd();
// Construct a route entry
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
IpAddress nextHopIp = Ip4Address.valueOf("192.168.20.1");
RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);
// Host service will reply with no hosts when asked
reset(hostService);
expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
Collections.emptySet()).anyTimes();
hostService.startMonitoringIp(IpAddress.valueOf("192.168.20.1"));
replay(hostService);
// Initially when we add the route, the DELETE FIB update will be sent
// but the UPDATE FIB update will come later when the MAC is resolved
reset(fibListener);
fibListener.update(Collections.emptyList(), Collections.singletonList(new FibUpdate(
FibUpdate.Type.DELETE, new FibEntry(prefix, null, null))));
replay(fibListener);
router.processRouteUpdates(Collections.singletonList(
new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));
verify(fibListener);
// Now when we send the event, we expect the FIB update to be sent
reset(fibListener);
FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
MacAddress.valueOf("00:00:00:00:00:02"));
fibListener.update(Collections.singletonList(new FibUpdate(
FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());
replay(fibListener);
Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
new HostLocation(
SW1_ETH1.deviceId(),
SW1_ETH1.port(), 1),
Sets.newHashSet(IpAddress.valueOf("192.168.20.1")));
// Send in the host event
internalHostListener.event(
new HostEvent(HostEvent.Type.HOST_ADDED, host));
verify(fibListener);
}
}
/*
* Copyright 2014 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.routing;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.routingapi.BgpService;
import org.onosproject.routingapi.FibEntry;
import org.onosproject.routingapi.FibListener;
import org.onosproject.routingapi.FibUpdate;
import org.onosproject.routingapi.RouteEntry;
import org.onosproject.routingapi.RouteListener;
import org.onosproject.routingapi.RouteUpdate;
import java.util.Collections;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* This class tests adding a route, updating a route, deleting a route,
* and adding a route whose next hop is the local BGP speaker.
* <p/>
* The HostService answers requests synchronously.
*/
public class RouterTest {
private HostService hostService;
private FibListener fibListener;
private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000001"),
PortNumber.portNumber(1));
private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000002"),
PortNumber.portNumber(1));
private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000003"),
PortNumber.portNumber(1));
private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000004"),
PortNumber.portNumber(1));
private Router router;
@Before
public void setUp() throws Exception {
setUpHostService();
BgpService bgpService = createMock(BgpService.class);
bgpService.start(anyObject(RouteListener.class), anyInt());
bgpService.stop();
replay(bgpService);
fibListener = createMock(FibListener.class);
router = new Router();
router.hostService = hostService;
router.bgpService = bgpService;
router.activate();
router.start(fibListener);
}
@After
public void tearDown() {
router.stop();
}
/**
* Sets up the host service with details of some hosts.
*/
private void setUpHostService() {
hostService = createMock(HostService.class);
hostService.addListener(anyObject(HostListener.class));
expectLastCall().anyTimes();
IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
new HostLocation(SW1_ETH1, 1),
Sets.newHashSet(host1Address));
expect(hostService.getHostsByIp(host1Address))
.andReturn(Sets.newHashSet(host1)).anyTimes();
hostService.startMonitoringIp(host1Address);
expectLastCall().anyTimes();
IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
new HostLocation(SW2_ETH1, 1),
Sets.newHashSet(host2Address));
expect(hostService.getHostsByIp(host2Address))
.andReturn(Sets.newHashSet(host2)).anyTimes();
hostService.startMonitoringIp(host2Address);
expectLastCall().anyTimes();
// Next hop on a VLAN
IpAddress host3Address = IpAddress.valueOf("192.168.40.1");
Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:03"), VlanId.vlanId((short) 1),
new HostLocation(SW4_ETH1, 1),
Sets.newHashSet(host3Address));
expect(hostService.getHostsByIp(host3Address))
.andReturn(Sets.newHashSet(host3)).anyTimes();
hostService.startMonitoringIp(host3Address);
expectLastCall().anyTimes();
// Called during shutdown
hostService.removeListener(anyObject(HostListener.class));
replay(hostService);
}
/**
* Tests adding a route entry.
*/
@Test
public void testRouteAdd() {
// Construct a route entry
IpPrefix prefix = Ip4Prefix.valueOf("1.1.1.0/24");
IpAddress nextHopIp = Ip4Address.valueOf("192.168.10.1");
RouteEntry routeEntry = new RouteEntry(prefix, nextHopIp);
// Expected FIB entry
FibEntry fibEntry = new FibEntry(prefix, nextHopIp,
MacAddress.valueOf("00:00:00:00:00:01"));
fibListener.update(Collections.singletonList(new FibUpdate(
FibUpdate.Type.UPDATE, fibEntry)), Collections.emptyList());
replay(fibListener);
router.processRouteUpdates(Collections.singletonList(
new RouteUpdate(RouteUpdate.Type.UPDATE, routeEntry)));
verify(fibListener);
}
/**
* Tests updating a route entry.
*/
@Test
public void testRouteUpdate() {
// Firstly add a route
testRouteAdd();
// Route entry with updated next hop for the original prefix
RouteEntry routeEntryUpdate = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.20.1"));
// The old FIB entry will be withdrawn
FibEntry withdrawFibEntry = new FibEntry(
Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
// A new FIB entry will be added
FibEntry updateFibEntry = new FibEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.20.1"),
MacAddress.valueOf("00:00:00:00:00:02"));
reset(fibListener);
fibListener.update(Collections.singletonList(new FibUpdate(
FibUpdate.Type.UPDATE, updateFibEntry)),
Collections.singletonList(new FibUpdate(
FibUpdate.Type.DELETE, withdrawFibEntry)));
replay(fibListener);
router.processRouteUpdates(Collections.singletonList(new RouteUpdate(
RouteUpdate.Type.UPDATE, routeEntryUpdate)));
verify(fibListener);
}
/**
* Tests deleting a route entry.
*/
@Test
public void testRouteDelete() {
// Firstly add a route
testRouteAdd();
RouteEntry deleteRouteEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.10.1"));
FibEntry deleteFibEntry = new FibEntry(
Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
reset(fibListener);
fibListener.update(Collections.emptyList(), Collections.singletonList(
new FibUpdate(FibUpdate.Type.DELETE, deleteFibEntry)));
replay(fibListener);
router.processRouteUpdates(Collections.singletonList(
new RouteUpdate(RouteUpdate.Type.DELETE, deleteRouteEntry)));
verify(fibListener);
}
/**
* Tests adding a route whose next hop is the local BGP speaker.
*/
@Test
public void testLocalRouteAdd() {
// Construct a route entry, the next hop is the local BGP speaker
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("0.0.0.0"));
// No methods on the FIB listener should be called
replay(fibListener);
// Call the processRouteUpdates() method in Router class
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
routeEntry);
router.processRouteUpdates(Collections.singletonList(routeUpdate));
// Verify
assertEquals(1, router.getRoutes4().size());
assertTrue(router.getRoutes4().contains(routeEntry));
verify(fibListener);
}
}
......@@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import org.hamcrest.Matchers;
import org.junit.Test;
import java.util.ArrayList;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
/**
* Unit tests for the BgpRouteEntry.AsPath class.
......@@ -211,7 +212,7 @@ public class AsPathTest {
//
BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments);
assertThat(asPath1, is(not(asPath2)));
assertThat(asPath1, Matchers.is(not(asPath2)));
}
/**
......
......@@ -13,22 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
package org.onosproject.routing.bgp;
import org.easymock.EasyMock;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import java.util.ArrayList;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
/**
* Unit tests for the BgpRouteEntry class.
*/
......@@ -63,9 +62,9 @@ public class BgpRouteEntryTest {
@Before
public void setUp() throws Exception {
// Mock objects for testing
bgpSession = createMock(BgpSession.class);
bgpSession2 = createMock(BgpSession.class);
bgpSession3 = createMock(BgpSession.class);
bgpSession = EasyMock.createMock(BgpSession.class);
bgpSession2 = EasyMock.createMock(BgpSession.class);
bgpSession3 = EasyMock.createMock(BgpSession.class);
// Setup the BGP Sessions
remoteInfo.setIp4Address(BGP_SESSION_IP_ADDRESS);
......@@ -75,16 +74,16 @@ public class BgpRouteEntryTest {
remoteInfo2.setBgpId(BGP_SESSION_BGP_ID2);
remoteInfo3.setBgpId(BGP_SESSION_BGP_ID3);
expect(bgpSession.localInfo()).andReturn(localInfo).anyTimes();
expect(bgpSession.remoteInfo()).andReturn(remoteInfo).anyTimes();
expect(bgpSession2.localInfo()).andReturn(localInfo2).anyTimes();
expect(bgpSession2.remoteInfo()).andReturn(remoteInfo2).anyTimes();
expect(bgpSession3.localInfo()).andReturn(localInfo3).anyTimes();
expect(bgpSession3.remoteInfo()).andReturn(remoteInfo3).anyTimes();
EasyMock.expect(bgpSession.localInfo()).andReturn(localInfo).anyTimes();
EasyMock.expect(bgpSession.remoteInfo()).andReturn(remoteInfo).anyTimes();
EasyMock.expect(bgpSession2.localInfo()).andReturn(localInfo2).anyTimes();
EasyMock.expect(bgpSession2.remoteInfo()).andReturn(remoteInfo2).anyTimes();
EasyMock.expect(bgpSession3.localInfo()).andReturn(localInfo3).anyTimes();
EasyMock.expect(bgpSession3.remoteInfo()).andReturn(remoteInfo3).anyTimes();
replay(bgpSession);
replay(bgpSession2);
replay(bgpSession3);
EasyMock.replay(bgpSession);
EasyMock.replay(bgpSession2);
EasyMock.replay(bgpSession3);
}
/**
......@@ -500,7 +499,7 @@ public class BgpRouteEntryTest {
localPref);
bgpRouteEntry2.setMultiExitDisc(multiExitDisc);
assertThat(bgpRouteEntry1, is(not(bgpRouteEntry2)));
assertThat(bgpRouteEntry1, Matchers.is(not(bgpRouteEntry2)));
}
/**
......
......@@ -13,22 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
package org.onosproject.routing.bgp;
import com.google.common.net.InetAddresses;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.jboss.netty.bootstrap.ClientBootstrap;
......@@ -44,12 +31,24 @@ import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.junit.TestUtils.TestUtilsException;
import org.onosproject.sdnip.RouteListener;
import org.onosproject.sdnip.RouteUpdate;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onosproject.routingapi.RouteListener;
import org.onosproject.routingapi.RouteUpdate;
import com.google.common.net.InetAddresses;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* Unit tests for the BgpSessionManager class.
......@@ -251,9 +250,9 @@ public class BgpSessionManagerTest {
// Setup the BGP Session Manager to test, and start listening for BGP
// connections.
//
bgpSessionManager = new BgpSessionManager(dummyRouteListener);
bgpSessionManager = new BgpSessionManager();
// NOTE: We use port 0 to bind on any available port
bgpSessionManager.start(0);
bgpSessionManager.start(dummyRouteListener, 0);
// Get the port number the BGP Session Manager is listening on
Channel serverChannel = TestUtils.getField(bgpSessionManager,
......
......@@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
package org.onosproject.routing.bgp;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import org.hamcrest.Matchers;
import org.junit.Test;
import java.util.ArrayList;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
/**
* Unit tests for the BgpRouteEntry.PathSegment class.
......@@ -113,7 +114,7 @@ public class PathSegmentTest {
BgpRouteEntry.PathSegment pathSegment2 =
new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
assertThat(pathSegment1, is(not(pathSegment2)));
assertThat(pathSegment1, Matchers.is(not(pathSegment2)));
}
/**
......
......@@ -13,9 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
import java.util.Collection;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
......@@ -25,6 +23,8 @@ import org.jboss.netty.channel.SimpleChannelHandler;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import java.util.Collection;
/**
* Class for handling the remote BGP Peer session.
*/
......
......@@ -13,9 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdnip.bgp;
import java.util.concurrent.CountDownLatch;
package org.onosproject.routing.bgp;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
......@@ -23,6 +21,8 @@ import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.onlab.packet.Ip4Address;
import java.util.concurrent.CountDownLatch;
/**
* Class for handling the decoding of the BGP messages at the remote
* BGP peer session.
......
......@@ -61,11 +61,6 @@
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-thirdparty</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
......@@ -85,13 +80,13 @@
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<artifactId>onos-app-routing-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-dist</artifactId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
......@@ -107,11 +102,6 @@
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
......
......@@ -36,6 +36,8 @@ import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.routingapi.FibListener;
import org.onosproject.routingapi.FibUpdate;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
......
......@@ -15,15 +15,11 @@
*/
package org.onosproject.sdnip;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.IpAddress;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
......@@ -32,7 +28,6 @@ import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.sdnip.bgp.BgpConstants;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.BgpSpeaker;
import org.onosproject.sdnip.config.Interface;
......@@ -41,6 +36,10 @@ import org.onosproject.sdnip.config.SdnIpConfigurationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Manages the connectivity requirements between peers.
*/
......@@ -49,6 +48,8 @@ public class PeerConnectivityManager {
private static final Logger log = LoggerFactory.getLogger(
PeerConnectivityManager.class);
private static final short BGP_PORT = 179;
private final IntentSynchronizer intentSynchronizer;
private final SdnIpConfigurationService configService;
private final InterfaceService interfaceService;
......@@ -191,7 +192,7 @@ public class PeerConnectivityManager {
bgpdAddress,
bgpdPeerAddress,
null,
(short) BgpConstants.BGP_PORT);
BGP_PORT);
intents.add(new PointToPointIntent(appId, selector, treatment,
bgpdConnectPoint, bgpdPeerConnectPoint));
......@@ -200,7 +201,7 @@ public class PeerConnectivityManager {
selector = buildSelector(tcpProtocol,
bgpdAddress,
bgpdPeerAddress,
(short) BgpConstants.BGP_PORT,
BGP_PORT,
null);
intents.add(new PointToPointIntent(appId, selector, treatment,
......@@ -211,7 +212,7 @@ public class PeerConnectivityManager {
bgpdPeerAddress,
bgpdAddress,
null,
(short) BgpConstants.BGP_PORT);
BGP_PORT);
intents.add(new PointToPointIntent(appId, selector, treatment,
bgpdPeerConnectPoint, bgpdConnectPoint));
......@@ -220,7 +221,7 @@ public class PeerConnectivityManager {
selector = buildSelector(tcpProtocol,
bgpdPeerAddress,
bgpdAddress,
(short) BgpConstants.BGP_PORT,
BGP_PORT,
null);
intents.add(new PointToPointIntent(appId, selector, treatment,
......
......@@ -32,14 +32,11 @@ import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.IntentService;
import org.onosproject.sdnip.bgp.BgpRouteEntry;
import org.onosproject.sdnip.bgp.BgpSession;
import org.onosproject.sdnip.bgp.BgpSessionManager;
import org.onosproject.routingapi.RoutingService;
import org.onosproject.sdnip.config.SdnIpConfigurationReader;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.Collection;
import java.util.Dictionary;
import static org.slf4j.LoggerFactory.getLogger;
......@@ -69,8 +66,11 @@ public class SdnIp implements SdnIpService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LeadershipService leadershipService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected RoutingService routingService;
//
// NOTE: Unused reference - needed to guarentee that the
// NOTE: Unused reference - needed to guarantee that the
// NetworkConfigReader component is activated and the network configuration
// is read.
//
......@@ -83,8 +83,7 @@ public class SdnIp implements SdnIpService {
private IntentSynchronizer intentSynchronizer;
private SdnIpConfigurationReader config;
private PeerConnectivityManager peerConnectivity;
private Router router;
private BgpSessionManager bgpSessionManager;
private LeadershipEventListener leadershipEventListener =
new InnerLeadershipEventListener();
private ApplicationId appId;
......@@ -114,23 +113,18 @@ public class SdnIp implements SdnIpService {
interfaceService);
peerConnectivity.start();
router = new Router(intentSynchronizer, hostService);
router.start();
routingService.start(intentSynchronizer);
leadershipService.addListener(leadershipEventListener);
leadershipService.runForLeadership(appId.name());
log.info("Starting BGP with port {}", bgpPort);
bgpSessionManager = new BgpSessionManager(router);
bgpSessionManager.start(bgpPort);
// TODO feed port information through to the BgpService
}
@Deactivate
protected void deactivate() {
bgpSessionManager.stop();
router.stop();
routingService.stop();
peerConnectivity.stop();
intentSynchronizer.stop();
......@@ -168,31 +162,6 @@ public class SdnIp implements SdnIpService {
}
@Override
public Collection<BgpSession> getBgpSessions() {
return bgpSessionManager.getBgpSessions();
}
@Override
public Collection<BgpRouteEntry> getBgpRoutes4() {
return bgpSessionManager.getBgpRoutes4();
}
@Override
public Collection<BgpRouteEntry> getBgpRoutes6() {
return bgpSessionManager.getBgpRoutes6();
}
@Override
public Collection<RouteEntry> getRoutes4() {
return router.getRoutes4();
}
@Override
public Collection<RouteEntry> getRoutes6() {
return router.getRoutes6();
}
@Override
public void modifyPrimary(boolean isPrimary) {
intentSynchronizer.leaderChanged(isPrimary);
}
......
......@@ -15,49 +15,10 @@
*/
package org.onosproject.sdnip;
import java.util.Collection;
import org.onosproject.sdnip.bgp.BgpRouteEntry;
import org.onosproject.sdnip.bgp.BgpSession;
/**
* Service interface exported by SDN-IP.
*/
public interface SdnIpService {
/**
* Gets the BGP sessions.
*
* @return the BGP sessions
*/
public Collection<BgpSession> getBgpSessions();
/**
* Gets the selected IPv4 BGP routes among all BGP sessions.
*
* @return the selected IPv4 BGP routes among all BGP sessions
*/
public Collection<BgpRouteEntry> getBgpRoutes4();
/**
* Gets the selected IPv6 BGP routes among all BGP sessions.
*
* @return the selected IPv6 BGP routes among all BGP sessions
*/
public Collection<BgpRouteEntry> getBgpRoutes6();
/**
* Gets all IPv4 routes known to SDN-IP.
*
* @return the SDN-IP IPv4 routes
*/
public Collection<RouteEntry> getRoutes4();
/**
* Gets all IPv6 routes known to SDN-IP.
*
* @return the SDN-IP IPv6 routes
*/
public Collection<RouteEntry> getRoutes6();
/**
* Changes whether this SDN-IP instance is the primary or not based on the
......
......@@ -17,15 +17,6 @@
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.sdnip.cli.BgpNeighborsListCommand"/>
</command>
<command>
<action class="org.onosproject.sdnip.cli.BgpRoutesListCommand"/>
</command>
<command>
<action class="org.onosproject.sdnip.cli.RoutesListCommand"/>
</command>
<command>
<action class="org.onosproject.sdnip.cli.PrimaryChangeCommand"/>
</command>
</command-bundle>
......
......@@ -16,9 +16,8 @@
package org.onosproject.sdnip;
import com.google.common.collect.Sets;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
......@@ -32,18 +31,12 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Intent;
......@@ -51,10 +44,18 @@ import org.onosproject.net.intent.IntentOperations;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.routingapi.FibEntry;
import org.onosproject.routingapi.FibUpdate;
import org.onosproject.routingapi.RouteEntry;
import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
......@@ -71,9 +72,9 @@ import static org.junit.Assert.assertTrue;
*/
public class IntentSyncTest extends AbstractIntentTest {
private SdnIpConfigurationService sdnIpConfigService;
private InterfaceService interfaceService;
private IntentService intentService;
private HostService hostService;
private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000001"),
......@@ -87,8 +88,11 @@ public class IntentSyncTest extends AbstractIntentTest {
DeviceId.deviceId("of:0000000000000003"),
PortNumber.portNumber(1));
private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000004"),
PortNumber.portNumber(1));
private IntentSynchronizer intentSynchronizer;
private Router router;
private static final ApplicationId APPID = new ApplicationId() {
@Override
......@@ -106,12 +110,42 @@ public class IntentSyncTest extends AbstractIntentTest {
public void setUp() throws Exception {
super.setUp();
setUpInterfaceService();
setUpHostService();
setUpBgpPeers();
intentService = createMock(IntentService.class);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
null, interfaceService);
router = new Router(intentSynchronizer, hostService);
sdnIpConfigService, interfaceService);
}
/**
* Sets up BGP peers in external networks.
*/
private void setUpBgpPeers() {
Map<IpAddress, BgpPeer> peers = new HashMap<>();
String peerSw1Eth1 = "192.168.10.1";
peers.put(IpAddress.valueOf(peerSw1Eth1),
new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
// Two BGP peers are connected to switch 2 port 1.
String peer1Sw2Eth1 = "192.168.20.1";
peers.put(IpAddress.valueOf(peer1Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
String peer2Sw2Eth1 = "192.168.20.2";
peers.put(IpAddress.valueOf(peer2Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
String peer1Sw4Eth1 = "192.168.40.1";
peers.put(IpAddress.valueOf(peer1Sw4Eth1),
new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
sdnIpConfigService = createMock(SdnIpConfigurationService.class);
expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
EasyMock.replay(sdnIpConfigService);
}
/**
......@@ -133,80 +167,279 @@ public class IntentSyncTest extends AbstractIntentTest {
interfaces.add(sw1Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
interfaceIpAddresses2.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.20.101"),
IpPrefix.valueOf("192.168.20.0/24")));
interfaceIpAddresses2.add(
new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
IpPrefix.valueOf("192.168.20.0/24")));
Interface sw2Eth1 = new Interface(SW2_ETH1,
interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
VlanId.NONE);
interfaces.add(sw2Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
interfaceIpAddresses3.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.30.101"),
IpPrefix.valueOf("192.168.30.0/24")));
interfaceIpAddresses3.add(
new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
IpPrefix.valueOf("192.168.30.0/24")));
Interface sw3Eth1 = new Interface(SW3_ETH1,
interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
VlanId.NONE);
interfaces.add(sw3Eth1);
InterfaceIpAddress interfaceIpAddress4 =
new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
IpPrefix.valueOf("192.168.40.0/24"));
Interface sw4Eth1 = new Interface(SW4_ETH1,
Sets.newHashSet(interfaceIpAddress4),
MacAddress.valueOf("00:00:00:00:00:04"),
VlanId.vlanId((short) 1));
expect(interfaceService.getInterface(SW4_ETH1)).andReturn(sw4Eth1).anyTimes();
interfaces.add(sw4Eth1);
expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
sw1Eth1).anyTimes();
expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
sw2Eth1).anyTimes();
expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
sw3Eth1).anyTimes();
expect(interfaceService.getInterfaces()).andReturn(
interfaces).anyTimes();
expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
replay(interfaceService);
}
/**
* Sets up the host service with details of hosts.
* Tests adding a FIB entry to the IntentSynchronizer.
*
* We verify that the synchronizer records the correct state and that the
* correct intent is submitted to the IntentService.
*
* @throws TestUtilsException
*/
@Test
public void testFibAdd() throws TestUtilsException {
FibEntry fibEntry = new FibEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.10.1"),
MacAddress.valueOf("00:00:00:00:00:01"));
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
fibEntry.prefix());
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
Set<ConnectPoint> ingressPoints = new HashSet<>();
ingressPoints.add(SW2_ETH1);
ingressPoints.add(SW3_ETH1);
ingressPoints.add(SW4_ETH1);
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(APPID,
selectorBuilder.build(), treatmentBuilder.build(),
ingressPoints, SW1_ETH1);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intent);
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
fibEntry);
intentSynchronizer.update(Collections.singleton(fibUpdate),
Collections.emptyList());
Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentKey = new IntentKey(intent);
assertTrue(firstIntentKey.equals(intentKey));
verify(intentService);
}
/**
* Tests adding a FIB entry with to 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.
*
* @throws TestUtilsException
*/
@Test
public void testFibAddWithVlan() throws TestUtilsException {
FibEntry fibEntry = new FibEntry(
Ip4Prefix.valueOf("3.3.3.0/24"),
Ip4Address.valueOf("192.168.40.1"),
MacAddress.valueOf("00:00:00:00:00:04"));
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(fibEntry.prefix())
.matchVlanId(VlanId.ANY);
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:04"))
.setVlanId(VlanId.vlanId((short) 1));
Set<ConnectPoint> ingressPoints = new HashSet<>();
ingressPoints.add(SW1_ETH1);
ingressPoints.add(SW2_ETH1);
ingressPoints.add(SW3_ETH1);
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(APPID,
selectorBuilder.build(), treatmentBuilder.build(),
ingressPoints, SW4_ETH1);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intent);
intentService.execute(
TestIntentServiceHelper.eqExceptId(builder.build()));
replay(intentService);
// Run the test
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE, fibEntry);
intentSynchronizer.update(Collections.singleton(fibUpdate),
Collections.emptyList());
// Verify
Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentKey = new IntentKey(intent);
assertTrue(firstIntentKey.equals(intentKey));
verify(intentService);
}
/**
* Tests updating a FIB entry.
*
* We verify that the synchronizer records the correct state and that the
* correct intent is submitted to the IntentService.
*
* @throws TestUtilsException
*/
private void setUpHostService() {
hostService = createMock(HostService.class);
@Test
public void testFibUpdate() throws TestUtilsException {
// Firstly add a route
testFibAdd();
hostService.addListener(anyObject(HostListener.class));
expectLastCall().anyTimes();
Intent addedIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
new HostLocation(SW1_ETH1, 1),
Sets.newHashSet(host1Address));
// Start to construct a new route entry and new intent
FibEntry fibEntryUpdate = new FibEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.20.1"),
MacAddress.valueOf("00:00:00:00:00:02"));
expect(hostService.getHostsByIp(host1Address))
.andReturn(Sets.newHashSet(host1)).anyTimes();
hostService.startMonitoringIp(host1Address);
expectLastCall().anyTimes();
// Construct a new MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilderNew =
DefaultTrafficSelector.builder();
selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
fibEntryUpdate.prefix());
TrafficTreatment.Builder treatmentBuilderNew =
DefaultTrafficTreatment.builder();
treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
new HostLocation(SW2_ETH1, 1),
Sets.newHashSet(host2Address));
expect(hostService.getHostsByIp(host2Address))
.andReturn(Sets.newHashSet(host2)).anyTimes();
hostService.startMonitoringIp(host2Address);
expectLastCall().anyTimes();
Set<ConnectPoint> ingressPointsNew = new HashSet<>();
ingressPointsNew.add(SW1_ETH1);
ingressPointsNew.add(SW3_ETH1);
ingressPointsNew.add(SW4_ETH1);
MultiPointToSinglePointIntent intentNew =
new MultiPointToSinglePointIntent(APPID,
selectorBuilderNew.build(),
treatmentBuilderNew.build(),
ingressPointsNew, SW2_ETH1);
IpAddress host3Address = IpAddress.valueOf("192.168.30.1");
Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:03"), VlanId.NONE,
new HostLocation(SW3_ETH1, 1),
Sets.newHashSet(host3Address));
// Set up test expectation
reset(intentService);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addWithdrawOperation(addedIntent.id());
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intentNew);
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the update() method in IntentSynchronizer class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.UPDATE,
fibEntryUpdate);
intentSynchronizer.update(Collections.singletonList(fibUpdate),
Collections.emptyList());
// Verify
Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentNewKey = new IntentKey(intentNew);
assertTrue(firstIntentKey.equals(intentNewKey));
verify(intentService);
}
expect(hostService.getHostsByIp(host3Address))
.andReturn(Sets.newHashSet(host3)).anyTimes();
hostService.startMonitoringIp(host3Address);
expectLastCall().anyTimes();
/**
* Tests deleting a FIB entry.
*
* We verify that the synchronizer records the correct state and that the
* correct intent is withdrawn from the IntentService.
*
* @throws TestUtilsException
*/
@Test
public void testFibDelete() throws TestUtilsException {
// Firstly add a route
testFibAdd();
Intent addedIntent =
intentSynchronizer.getRouteIntents().iterator().next();
replay(hostService);
// Construct the existing route entry
FibEntry fibEntry = new FibEntry(
Ip4Prefix.valueOf("1.1.1.0/24"), null, null);
// Set up expectation
reset(intentService);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addWithdrawOperation(addedIntent.id());
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the update() method in IntentSynchronizer class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
FibUpdate fibUpdate = new FibUpdate(FibUpdate.Type.DELETE, fibEntry);
intentSynchronizer.update(Collections.emptyList(),
Collections.singletonList(fibUpdate));
// Verify
Assert.assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
verify(intentService);
}
/**
......@@ -287,25 +520,7 @@ public class IntentSyncTest extends AbstractIntentTest {
MultiPointToSinglePointIntent intent6 = intentBuilder(
routeEntry6.prefix(), "00:00:00:00:00:01", SW1_ETH1);
// Set up the ribTable field in Router class and routeIntents fields
// in IntentSynchronizer class
InvertedRadixTree<RouteEntry> ribTable =
new ConcurrentInvertedRadixTree<>(
new DefaultByteArrayNodeFactory());
ribTable.put(RouteEntry.createBinaryString(routeEntry1.prefix()),
routeEntry1);
ribTable.put(RouteEntry.createBinaryString(routeEntry3.prefix()),
routeEntry3);
ribTable.put(RouteEntry.createBinaryString(routeEntry4Update.prefix()),
routeEntry4Update);
ribTable.put(RouteEntry.createBinaryString(routeEntry5.prefix()),
routeEntry5);
ribTable.put(RouteEntry.createBinaryString(routeEntry6.prefix()),
routeEntry6);
ribTable.put(RouteEntry.createBinaryString(routeEntry7.prefix()),
routeEntry7);
TestUtils.setField(router, "ribTable4", ribTable);
// Set up the routeIntents field in IntentSynchronizer class
ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
routeIntents = new ConcurrentHashMap<>();
routeIntents.put(routeEntry1.prefix(), intent1);
......@@ -353,20 +568,9 @@ public class IntentSyncTest extends AbstractIntentTest {
// Start the test
intentSynchronizer.leaderChanged(true);
/*
TestUtils.callMethod(intentSynchronizer, "synchronizeIntents",
new Class<?>[] {});
*/
intentSynchronizer.synchronizeIntents();
// Verify
assertEquals(router.getRoutes4().size(), 6);
assertTrue(router.getRoutes4().contains(routeEntry1));
assertTrue(router.getRoutes4().contains(routeEntry3));
assertTrue(router.getRoutes4().contains(routeEntry4Update));
assertTrue(router.getRoutes4().contains(routeEntry5));
assertTrue(router.getRoutes4().contains(routeEntry6));
assertEquals(intentSynchronizer.getRouteIntents().size(), 6);
assertTrue(intentSynchronizer.getRouteIntents().contains(intent1));
assertTrue(intentSynchronizer.getRouteIntents().contains(intent3));
......
......@@ -41,7 +41,6 @@ import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentOperations;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.sdnip.bgp.BgpConstants;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.BgpSpeaker;
import org.onosproject.sdnip.config.Interface;
......@@ -302,7 +301,7 @@ public class PeerConnectivityManagerTest extends AbstractIntentTest {
*/
private void setUpBgpIntents() {
Short bgpPort = Short.valueOf((short) BgpConstants.BGP_PORT);
Short bgpPort = 179;
// Start to build intents between BGP speaker1 and BGP peer1
bgpPathintentConstructor(
......
/*
* Copyright 2014 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.sdnip;
import com.google.common.collect.Sets;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultByteArrayNodeFactory;
import com.googlecode.concurrenttrees.radixinverted.ConcurrentInvertedRadixTree;
import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.junit.TestUtils.TestUtilsException;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentOperations;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
import org.onosproject.sdnip.Router.InternalHostListener;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* This class tests adding a route, updating a route, deleting a route, and
* the ARP module answers the MAC address asynchronously.
*/
public class RouterAsyncArpTest extends AbstractIntentTest {
private SdnIpConfigurationService sdnIpConfigService;
private InterfaceService interfaceService;
private IntentService intentService;
private HostService hostService;
private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000001"),
PortNumber.portNumber(1));
private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000002"),
PortNumber.portNumber(1));
private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000003"),
PortNumber.portNumber(1));
private IntentSynchronizer intentSynchronizer;
private Router router;
private InternalHostListener internalHostListener;
private static final ApplicationId APPID = new ApplicationId() {
@Override
public short id() {
return 1;
}
@Override
public String name() {
return "SDNIP";
}
};
@Before
public void setUp() throws Exception {
super.setUp();
setUpSdnIpConfigService();
setUpInterfaceService();
hostService = createMock(HostService.class);
intentService = createMock(IntentService.class);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
sdnIpConfigService,
interfaceService);
router = new Router(intentSynchronizer, hostService);
internalHostListener = router.new InternalHostListener();
}
/**
* Sets up SdnIpConfigService.
*/
private void setUpSdnIpConfigService() {
sdnIpConfigService = createMock(SdnIpConfigurationService.class);
Map<IpAddress, BgpPeer> peers = new HashMap<>();
String peerSw1Eth1 = "192.168.10.1";
peers.put(IpAddress.valueOf(peerSw1Eth1),
new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
// Two BGP peers are connected to switch 2 port 1.
String peer1Sw2Eth1 = "192.168.20.1";
peers.put(IpAddress.valueOf(peer1Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
String peer2Sw2Eth1 = "192.168.20.2";
peers.put(IpAddress.valueOf(peer2Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
replay(sdnIpConfigService);
}
/**
* Sets up InterfaceService.
*/
private void setUpInterfaceService() {
interfaceService = createMock(InterfaceService.class);
Set<Interface> interfaces = Sets.newHashSet();
Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
interfaceIpAddresses1.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.10.101"),
IpPrefix.valueOf("192.168.10.0/24")));
Interface sw1Eth1 = new Interface(SW1_ETH1,
interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
VlanId.NONE);
interfaces.add(sw1Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
interfaceIpAddresses2.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.20.101"),
IpPrefix.valueOf("192.168.20.0/24")));
Interface sw2Eth1 = new Interface(SW2_ETH1,
interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
VlanId.NONE);
interfaces.add(sw2Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
interfaceIpAddresses3.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.30.101"),
IpPrefix.valueOf("192.168.30.0/24")));
Interface sw3Eth1 = new Interface(SW3_ETH1,
interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
VlanId.NONE);
interfaces.add(sw3Eth1);
expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
replay(interfaceService);
}
/**
* This method tests adding a route entry.
*/
@Test
public void testRouteAdd() throws TestUtilsException {
// Construct a route entry
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.10.1"));
// Construct a route intent
MultiPointToSinglePointIntent intent = staticIntentBuilder();
// Set up test expectation
reset(hostService);
expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
new HashSet<Host>()).anyTimes();
hostService.startMonitoringIp(IpAddress.valueOf("192.168.10.1"));
replay(hostService);
reset(intentService);
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intent);
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
routeEntry);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
new HostLocation(
SW1_ETH1.deviceId(),
SW1_ETH1.port(), 1),
Sets.newHashSet(IpAddress.valueOf("192.168.10.1")));
internalHostListener.event(
new HostEvent(HostEvent.Type.HOST_ADDED, host));
// Verify
assertEquals(router.getRoutes4().size(), 1);
assertTrue(router.getRoutes4().contains(routeEntry));
assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentKey = new IntentKey(intent);
assertTrue(firstIntentKey.equals(intentKey));
verify(intentService);
verify(hostService);
}
/**
* This method tests updating a route entry.
*
* @throws TestUtilsException
*/
@Test
public void testRouteUpdate() throws TestUtilsException {
// Construct the existing route entry
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.10.1"));
// Construct the existing MultiPointToSinglePointIntent intent
MultiPointToSinglePointIntent intent = staticIntentBuilder();
// Set up the ribTable field of Router class with existing route, and
// routeIntents field with the corresponding existing intent
setRibTableField(routeEntry);
setRouteIntentsField(routeEntry, intent);
// Start to construct a new route entry and new intent
RouteEntry routeEntryUpdate = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.20.1"));
// Construct a new MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilderNew =
DefaultTrafficSelector.builder();
selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
routeEntryUpdate.prefix());
TrafficTreatment.Builder treatmentBuilderNew =
DefaultTrafficTreatment.builder();
treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
ingressPointsNew.add(SW1_ETH1);
ingressPointsNew.add(SW3_ETH1);
MultiPointToSinglePointIntent intentNew =
new MultiPointToSinglePointIntent(APPID,
selectorBuilderNew.build(),
treatmentBuilderNew.build(),
ingressPointsNew, SW2_ETH1);
// Set up test expectation
reset(hostService);
expect(hostService.getHostsByIp(anyObject(IpAddress.class))).andReturn(
new HashSet<Host>()).anyTimes();
hostService.startMonitoringIp(IpAddress.valueOf("192.168.20.1"));
replay(hostService);
reset(intentService);
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addWithdrawOperation(intent.id());
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intentNew);
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
routeEntryUpdate);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
new HostLocation(
SW2_ETH1.deviceId(),
SW2_ETH1.port(), 1),
Sets.newHashSet(IpAddress.valueOf("192.168.20.1")));
internalHostListener.event(
new HostEvent(HostEvent.Type.HOST_ADDED, host));
// Verify
assertEquals(router.getRoutes4().size(), 1);
assertTrue(router.getRoutes4().contains(routeEntryUpdate));
assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentNewKey = new IntentKey(intentNew);
assertTrue(firstIntentKey.equals(intentNewKey));
verify(intentService);
verify(hostService);
}
/**
* This method tests deleting a route entry.
*/
@Test
public void testRouteDelete() throws TestUtilsException {
// Construct the existing route entry
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.10.1"));
// Construct the existing MultiPointToSinglePointIntent intent
MultiPointToSinglePointIntent intent = staticIntentBuilder();
// Set up the ribTable field of Router class with existing route, and
// routeIntents field with the corresponding existing intent
setRibTableField(routeEntry);
setRouteIntentsField(routeEntry, intent);
// Set up expectation
reset(intentService);
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addWithdrawOperation(intent.id());
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
routeEntry);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
// Verify
assertEquals(router.getRoutes4().size(), 0);
assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
verify(intentService);
}
/**
* Constructs a static MultiPointToSinglePointIntent.
*/
private MultiPointToSinglePointIntent staticIntentBuilder() {
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
IpPrefix.valueOf("1.1.1.0/24"));
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
ingressPoints.add(SW2_ETH1);
ingressPoints.add(SW3_ETH1);
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(APPID,
selectorBuilder.build(), treatmentBuilder.build(),
ingressPoints, SW1_ETH1);
return intent;
}
/**
* Sets ribTable Field in Router class.
*
* @throws TestUtilsException
*/
private void setRibTableField(RouteEntry routeEntry)
throws TestUtilsException {
InvertedRadixTree<RouteEntry> ribTable =
new ConcurrentInvertedRadixTree<>(
new DefaultByteArrayNodeFactory());
ribTable.put(RouteEntry.createBinaryString(routeEntry.prefix()),
routeEntry);
TestUtils.setField(router, "ribTable4", ribTable);
}
/**
* Sets routeIntentsField in IntentSynchronizer class.
*
* @throws TestUtilsException
*/
private void setRouteIntentsField(RouteEntry routeEntry,
MultiPointToSinglePointIntent intent)
throws TestUtilsException {
ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent>
routeIntents = new ConcurrentHashMap<>();
routeIntents.put(routeEntry.prefix(), intent);
TestUtils.setField(intentSynchronizer, "routeIntents", routeIntents);
}
}
/*
* Copyright 2014 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.sdnip;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.junit.TestUtils.TestUtilsException;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentOperations;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* This class tests adding a route, updating a route, deleting a route,
* and adding a route whose next hop is the local BGP speaker.
* <p/>
* ARP module answers the MAC address synchronously.
*/
public class RouterTest extends AbstractIntentTest {
private SdnIpConfigurationService sdnIpConfigService;
private InterfaceService interfaceService;
private IntentService intentService;
private HostService hostService;
private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000001"),
PortNumber.portNumber(1));
private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000002"),
PortNumber.portNumber(1));
private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000003"),
PortNumber.portNumber(1));
private static final ConnectPoint SW4_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000004"),
PortNumber.portNumber(1));
private static final ApplicationId APPID = new ApplicationId() {
@Override
public short id() {
return 1;
}
@Override
public String name() {
return "SDNIP";
}
};
private IntentSynchronizer intentSynchronizer;
private Router router;
@Before
public void setUp() throws Exception {
super.setUp();
setUpBgpPeers();
setUpInterfaceService();
setUpHostService();
intentService = createMock(IntentService.class);
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
sdnIpConfigService,
interfaceService);
router = new Router(intentSynchronizer, hostService);
}
/**
* Sets up BGP peers in external networks.
*/
private void setUpBgpPeers() {
Map<IpAddress, BgpPeer> peers = new HashMap<>();
String peerSw1Eth1 = "192.168.10.1";
peers.put(IpAddress.valueOf(peerSw1Eth1),
new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
// Two BGP peers are connected to switch 2 port 1.
String peer1Sw2Eth1 = "192.168.20.1";
peers.put(IpAddress.valueOf(peer1Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
String peer2Sw2Eth1 = "192.168.20.2";
peers.put(IpAddress.valueOf(peer2Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
String peer1Sw4Eth1 = "192.168.40.1";
peers.put(IpAddress.valueOf(peer1Sw4Eth1),
new BgpPeer("00:00:00:00:00:00:00:04", 1, peer1Sw4Eth1));
sdnIpConfigService = createMock(SdnIpConfigurationService.class);
expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
replay(sdnIpConfigService);
}
/**
* Sets up logical interfaces, which emulate the configured interfaces
* in SDN-IP application.
*/
private void setUpInterfaceService() {
interfaceService = createMock(InterfaceService.class);
Set<Interface> interfaces = Sets.newHashSet();
InterfaceIpAddress ia1 =
new InterfaceIpAddress(IpAddress.valueOf("192.168.10.101"),
IpPrefix.valueOf("192.168.10.0/24"));
Interface sw1Eth1 = new Interface(SW1_ETH1,
Sets.newHashSet(ia1),
MacAddress.valueOf("00:00:00:00:00:01"),
VlanId.NONE);
expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
interfaces.add(sw1Eth1);
InterfaceIpAddress ia2 =
new InterfaceIpAddress(IpAddress.valueOf("192.168.20.101"),
IpPrefix.valueOf("192.168.20.0/24"));
Interface sw2Eth1 = new Interface(SW2_ETH1,
Sets.newHashSet(ia2),
MacAddress.valueOf("00:00:00:00:00:02"),
VlanId.NONE);
expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
interfaces.add(sw2Eth1);
InterfaceIpAddress ia3 =
new InterfaceIpAddress(IpAddress.valueOf("192.168.30.101"),
IpPrefix.valueOf("192.168.30.0/24"));
Interface sw3Eth1 = new Interface(SW3_ETH1,
Sets.newHashSet(ia3),
MacAddress.valueOf("00:00:00:00:00:03"),
VlanId.NONE);
expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
interfaces.add(sw3Eth1);
InterfaceIpAddress ia4 =
new InterfaceIpAddress(IpAddress.valueOf("192.168.40.101"),
IpPrefix.valueOf("192.168.40.0/24"));
Interface sw4Eth1 = new Interface(SW4_ETH1,
Sets.newHashSet(ia4),
MacAddress.valueOf("00:00:00:00:00:04"),
VlanId.vlanId((short) 1));
expect(interfaceService.getInterface(SW4_ETH1)).andReturn(sw4Eth1).anyTimes();
interfaces.add(sw4Eth1);
expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
replay(interfaceService);
}
/**
* Sets up the host service with details of some hosts.
*/
private void setUpHostService() {
hostService = createMock(HostService.class);
hostService.addListener(anyObject(HostListener.class));
expectLastCall().anyTimes();
IpAddress host1Address = IpAddress.valueOf("192.168.10.1");
Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
new HostLocation(SW1_ETH1, 1),
Sets.newHashSet(host1Address));
expect(hostService.getHostsByIp(host1Address))
.andReturn(Sets.newHashSet(host1)).anyTimes();
hostService.startMonitoringIp(host1Address);
expectLastCall().anyTimes();
IpAddress host2Address = IpAddress.valueOf("192.168.20.1");
Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
new HostLocation(SW2_ETH1, 1),
Sets.newHashSet(host2Address));
expect(hostService.getHostsByIp(host2Address))
.andReturn(Sets.newHashSet(host2)).anyTimes();
hostService.startMonitoringIp(host2Address);
expectLastCall().anyTimes();
// Next hop on a VLAN
IpAddress host3Address = IpAddress.valueOf("192.168.40.1");
Host host3 = new DefaultHost(ProviderId.NONE, HostId.NONE,
MacAddress.valueOf("00:00:00:00:00:03"), VlanId.vlanId((short) 1),
new HostLocation(SW4_ETH1, 1),
Sets.newHashSet(host3Address));
expect(hostService.getHostsByIp(host3Address))
.andReturn(Sets.newHashSet(host3)).anyTimes();
hostService.startMonitoringIp(host3Address);
expectLastCall().anyTimes();
replay(hostService);
}
/**
* This method tests adding a route entry.
*/
@Test
public void testRouteAdd() throws TestUtilsException {
// Construct a route entry
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.10.1"));
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
routeEntry.prefix());
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
ingressPoints.add(SW2_ETH1);
ingressPoints.add(SW3_ETH1);
ingressPoints.add(SW4_ETH1);
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(APPID,
selectorBuilder.build(), treatmentBuilder.build(),
ingressPoints, SW1_ETH1);
// Set up test expectation
reset(intentService);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intent);
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
routeEntry);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
// Verify
assertEquals(router.getRoutes4().size(), 1);
assertTrue(router.getRoutes4().contains(routeEntry));
assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentKey = new IntentKey(intent);
assertTrue(firstIntentKey.equals(intentKey));
verify(intentService);
}
/**
* This method tests adding a route entry.
*/
@Test
public void testRouteAddWithVlan() throws TestUtilsException {
// Construct a route entry
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("3.3.3.0/24"),
Ip4Address.valueOf("192.168.40.1"));
// Construct a MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(routeEntry.prefix())
.matchVlanId(VlanId.ANY);
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
.setVlanId(VlanId.vlanId((short) 1));
Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
ingressPoints.add(SW1_ETH1);
ingressPoints.add(SW2_ETH1);
ingressPoints.add(SW3_ETH1);
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(APPID,
selectorBuilder.build(), treatmentBuilder.build(),
ingressPoints, SW4_ETH1);
// Set up test expectation
reset(intentService);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intent);
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
routeEntry);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
// Verify
assertEquals(router.getRoutes4().size(), 1);
assertTrue(router.getRoutes4().contains(routeEntry));
assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentKey = new IntentKey(intent);
assertTrue(firstIntentKey.equals(intentKey));
verify(intentService);
}
/**
* This method tests updating a route entry.
*
* @throws TestUtilsException
*/
@Test
public void testRouteUpdate() throws TestUtilsException {
// Firstly add a route
testRouteAdd();
Intent addedIntent =
intentSynchronizer.getRouteIntents().iterator().next();
// Start to construct a new route entry and new intent
RouteEntry routeEntryUpdate = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.20.1"));
// Construct a new MultiPointToSinglePointIntent intent
TrafficSelector.Builder selectorBuilderNew =
DefaultTrafficSelector.builder();
selectorBuilderNew.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(
routeEntryUpdate.prefix());
TrafficTreatment.Builder treatmentBuilderNew =
DefaultTrafficTreatment.builder();
treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
ingressPointsNew.add(SW1_ETH1);
ingressPointsNew.add(SW3_ETH1);
ingressPointsNew.add(SW4_ETH1);
MultiPointToSinglePointIntent intentNew =
new MultiPointToSinglePointIntent(APPID,
selectorBuilderNew.build(),
treatmentBuilderNew.build(),
ingressPointsNew, SW2_ETH1);
// Set up test expectation
reset(intentService);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addWithdrawOperation(addedIntent.id());
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
builder = IntentOperations.builder(APPID);
builder.addSubmitOperation(intentNew);
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
routeEntryUpdate);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
// Verify
assertEquals(router.getRoutes4().size(), 1);
assertTrue(router.getRoutes4().contains(routeEntryUpdate));
assertEquals(intentSynchronizer.getRouteIntents().size(), 1);
Intent firstIntent =
intentSynchronizer.getRouteIntents().iterator().next();
IntentKey firstIntentKey = new IntentKey(firstIntent);
IntentKey intentNewKey = new IntentKey(intentNew);
assertTrue(firstIntentKey.equals(intentNewKey));
verify(intentService);
}
/**
* This method tests deleting a route entry.
*/
@Test
public void testRouteDelete() throws TestUtilsException {
// Firstly add a route
testRouteAdd();
Intent addedIntent =
intentSynchronizer.getRouteIntents().iterator().next();
// Construct the existing route entry
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("192.168.10.1"));
// Set up expectation
reset(intentService);
// Setup the expected intents
IntentOperations.Builder builder = IntentOperations.builder(APPID);
builder.addWithdrawOperation(addedIntent.id());
intentService.execute(TestIntentServiceHelper.eqExceptId(
builder.build()));
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
routeEntry);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
// Verify
assertEquals(router.getRoutes4().size(), 0);
assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
verify(intentService);
}
/**
* This method tests when the next hop of a route is the local BGP speaker.
*
* @throws TestUtilsException
*/
@Test
public void testLocalRouteAdd() throws TestUtilsException {
// Construct a route entry, the next hop is the local BGP speaker
RouteEntry routeEntry = new RouteEntry(
Ip4Prefix.valueOf("1.1.1.0/24"),
Ip4Address.valueOf("0.0.0.0"));
// Reset intentService to check whether the submit method is called
reset(intentService);
replay(intentService);
// Call the processRouteUpdates() method in Router class
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
RouteUpdate routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
routeEntry);
router.processRouteUpdates(Collections.<RouteUpdate>singletonList(routeUpdate));
// Verify
assertEquals(router.getRoutes4().size(), 1);
assertTrue(router.getRoutes4().contains(routeEntry));
assertEquals(intentSynchronizer.getRouteIntents().size(), 0);
verify(intentService);
}
}
/*
* Copyright 2014 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.sdnip;
import com.google.common.collect.Sets;
import org.easymock.IAnswer;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.onlab.junit.IntegrationTest;
import org.onlab.junit.TestUtils;
import org.onlab.junit.TestUtils.TestUtilsException;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.sdnip.config.BgpPeer;
import org.onosproject.sdnip.config.Interface;
import org.onosproject.sdnip.config.SdnIpConfigurationService;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Integration tests for the SDN-IP application.
* <p/>
* The tests are very coarse-grained. They feed route updates in to
* {@link Router} (simulating routes learnt from iBGP module inside SDN-IP
* application), then they check that the correct intents are created and
* submitted to the intent service. The entire route processing logic of
* Router class is tested.
*/
@Category(IntegrationTest.class)
public class SdnIpTest extends AbstractIntentTest {
private static final int MAC_ADDRESS_LENGTH = 6;
private static final int MIN_PREFIX_LENGTH = 1;
private static final int MAX_PREFIX_LENGTH = 32;
private IntentSynchronizer intentSynchronizer;
static Router router;
private SdnIpConfigurationService sdnIpConfigService;
private InterfaceService interfaceService;
private HostService hostService;
private IntentService intentService;
private Map<IpAddress, BgpPeer> bgpPeers;
private Random random;
static final ConnectPoint SW1_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000001"),
PortNumber.portNumber(1));
static final ConnectPoint SW2_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000002"),
PortNumber.portNumber(1));
static final ConnectPoint SW3_ETH1 = new ConnectPoint(
DeviceId.deviceId("of:0000000000000003"),
PortNumber.portNumber(1));
private static final ApplicationId APPID = new ApplicationId() {
@Override
public short id() {
return 1;
}
@Override
public String name() {
return "SDNIP";
}
};
@Before
public void setUp() throws Exception {
super.setUp();
setUpInterfaceService();
setUpSdnIpConfigService();
hostService = new TestHostService();
intentService = createMock(IntentService.class);
random = new Random();
intentSynchronizer = new IntentSynchronizer(APPID, intentService,
sdnIpConfigService,
interfaceService);
router = new Router(intentSynchronizer, hostService);
}
/**
* Sets up InterfaceService and virtual {@link Interface}s.
*/
private void setUpInterfaceService() {
interfaceService = createMock(InterfaceService.class);
Set<Interface> interfaces = Sets.newHashSet();
Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
interfaceIpAddresses1.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.10.101"),
IpPrefix.valueOf("192.168.10.0/24")));
Interface sw1Eth1 = new Interface(SW1_ETH1,
interfaceIpAddresses1, MacAddress.valueOf("00:00:00:00:00:01"),
VlanId.NONE);
interfaces.add(sw1Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses2 = Sets.newHashSet();
interfaceIpAddresses2.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.20.101"),
IpPrefix.valueOf("192.168.20.0/24")));
Interface sw2Eth1 = new Interface(SW2_ETH1,
interfaceIpAddresses2, MacAddress.valueOf("00:00:00:00:00:02"),
VlanId.NONE);
interfaces.add(sw2Eth1);
Set<InterfaceIpAddress> interfaceIpAddresses3 = Sets.newHashSet();
interfaceIpAddresses3.add(new InterfaceIpAddress(
IpAddress.valueOf("192.168.30.101"),
IpPrefix.valueOf("192.168.30.0/24")));
Interface sw3Eth1 = new Interface(SW3_ETH1,
interfaceIpAddresses3, MacAddress.valueOf("00:00:00:00:00:03"),
VlanId.NONE);
interfaces.add(sw3Eth1);
expect(interfaceService.getInterface(SW1_ETH1)).andReturn(
sw1Eth1).anyTimes();
expect(interfaceService.getInterface(SW2_ETH1)).andReturn(
sw2Eth1).anyTimes();
expect(interfaceService.getInterface(SW3_ETH1)).andReturn(
sw3Eth1).anyTimes();
expect(interfaceService.getInterfaces()).andReturn(
interfaces).anyTimes();
replay(interfaceService);
}
/**
* Sets up SdnIpConfigService and BGP peers in external networks.
*/
private void setUpSdnIpConfigService() {
sdnIpConfigService = createMock(SdnIpConfigurationService.class);
bgpPeers = new HashMap<>();
String peerSw1Eth1 = "192.168.10.1";
bgpPeers.put(IpAddress.valueOf(peerSw1Eth1),
new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
String peer1Sw2Eth1 = "192.168.20.1";
bgpPeers.put(IpAddress.valueOf(peer1Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
String peer2Sw2Eth1 = "192.168.30.1";
bgpPeers.put(IpAddress.valueOf(peer2Sw2Eth1),
new BgpPeer("00:00:00:00:00:00:00:03", 1, peer2Sw2Eth1));
expect(sdnIpConfigService.getBgpPeers()).andReturn(bgpPeers).anyTimes();
replay(sdnIpConfigService);
}
/**
* Tests adding a set of routes into {@link Router}.
* <p/>
* Random routes are generated and fed in to the route processing
* logic (via processRouteAdd in Router class). We check that the correct
* intents are generated and submitted to our mock intent service.
*
* @throws InterruptedException if interrupted while waiting on a latch
* @throws TestUtilsException if exceptions when using TestUtils
*/
@Test
public void testAddRoutes() throws InterruptedException, TestUtilsException {
int numRoutes = 100;
final CountDownLatch latch = new CountDownLatch(numRoutes);
List<RouteUpdate> routeUpdates = generateRouteUpdates(numRoutes);
// Set up expectation
reset(intentService);
for (RouteUpdate update : routeUpdates) {
IpAddress nextHopAddress = update.routeEntry().nextHop();
// Find out the egress ConnectPoint
ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);
MultiPointToSinglePointIntent intent = getIntentForUpdate(update,
generateMacAddress(nextHopAddress),
egressConnectPoint);
intentService.submit(TestIntentServiceHelper.eqExceptId(intent));
expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
latch.countDown();
return null;
}
}).once();
}
replay(intentService);
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
// Add route updates
router.processRouteUpdates(routeUpdates);
latch.await(5000, TimeUnit.MILLISECONDS);
assertEquals(router.getRoutes4().size(), numRoutes);
assertEquals(intentSynchronizer.getRouteIntents().size(),
numRoutes);
verify(intentService);
}
/**
* Tests adding then deleting a set of routes from {@link Router}.
* <p/>
* Random routes are generated and fed in to the route processing
* logic (via processRouteAdd in Router class), and we check that the
* correct intents are generated. We then delete the entire set of routes
* (by feeding updates to processRouteDelete), and check that the correct
* intents are withdrawn from the intent service.
*
* @throws InterruptedException if interrupted while waiting on a latch
* @throws TestUtilsException exceptions when using TestUtils
*/
@Test
public void testDeleteRoutes() throws InterruptedException, TestUtilsException {
int numRoutes = 100;
List<RouteUpdate> routeUpdates = generateRouteUpdates(numRoutes);
final CountDownLatch installCount = new CountDownLatch(numRoutes);
final CountDownLatch deleteCount = new CountDownLatch(numRoutes);
// Set up expectation
reset(intentService);
for (RouteUpdate update : routeUpdates) {
IpAddress nextHopAddress = update.routeEntry().nextHop();
// Find out the egress ConnectPoint
ConnectPoint egressConnectPoint = getConnectPoint(nextHopAddress);
MultiPointToSinglePointIntent intent = getIntentForUpdate(update,
generateMacAddress(nextHopAddress),
egressConnectPoint);
intentService.submit(TestIntentServiceHelper.eqExceptId(intent));
expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
installCount.countDown();
return null;
}
}).once();
intentService.withdraw(TestIntentServiceHelper.eqExceptId(intent));
expectLastCall().andAnswer(new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
deleteCount.countDown();
return null;
}
}).once();
}
replay(intentService);
intentSynchronizer.leaderChanged(true);
TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
// Send the add updates first
router.processRouteUpdates(routeUpdates);
// Give some time to let the intents be submitted
installCount.await(5000, TimeUnit.MILLISECONDS);
// Send the DELETE updates
List<RouteUpdate> deleteRouteUpdates = new ArrayList<>();
for (RouteUpdate update : routeUpdates) {
RouteUpdate deleteUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
update.routeEntry());
deleteRouteUpdates.add(deleteUpdate);
}
router.processRouteUpdates(deleteRouteUpdates);
deleteCount.await(5000, TimeUnit.MILLISECONDS);
assertEquals(0, router.getRoutes4().size());
assertEquals(0, intentSynchronizer.getRouteIntents().size());
verify(intentService);
}
/**
* This methods generates random route updates.
*
* @param numRoutes the number of route updates to generate
* @return a list of route update
*/
private List<RouteUpdate> generateRouteUpdates(int numRoutes) {
List<RouteUpdate> routeUpdates = new ArrayList<>(numRoutes);
Set<Ip4Prefix> prefixes = new HashSet<>();
for (int i = 0; i < numRoutes; i++) {
Ip4Prefix prefix;
do {
// Generate a random prefix length between MIN_PREFIX_LENGTH
// and MAX_PREFIX_LENGTH
int prefixLength = random.nextInt(
(MAX_PREFIX_LENGTH - MIN_PREFIX_LENGTH) + 1)
+ MIN_PREFIX_LENGTH;
prefix =
Ip4Prefix.valueOf(Ip4Address.valueOf(random.nextInt()),
prefixLength);
// We have to ensure we don't generate the same prefix twice
// (this is quite easy to happen with small prefix lengths).
} while (prefixes.contains(prefix));
prefixes.add(prefix);
// Randomly select a peer to use as the next hop
BgpPeer nextHop = null;
int peerNumber = random.nextInt(sdnIpConfigService.getBgpPeers()
.size());
int j = 0;
for (BgpPeer peer : sdnIpConfigService.getBgpPeers().values()) {
if (j++ == peerNumber) {
nextHop = peer;
break;
}
}
assertNotNull(nextHop);
RouteUpdate update =
new RouteUpdate(RouteUpdate.Type.UPDATE,
new RouteEntry(prefix,
nextHop.ipAddress().getIp4Address()));
routeUpdates.add(update);
}
return routeUpdates;
}
/**
* Generates the MultiPointToSinglePointIntent that should be
* submitted/withdrawn for a particular RouteUpdate.
*
* @param update the RouteUpdate to generate an intent for
* @param nextHopMac a MAC address to use as the dst-mac for the intent
* @param egressConnectPoint the outgoing ConnectPoint for the intent
* @return the generated intent
*/
private MultiPointToSinglePointIntent getIntentForUpdate(RouteUpdate update,
MacAddress nextHopMac, ConnectPoint egressConnectPoint) {
IpPrefix ip4Prefix = update.routeEntry().prefix();
TrafficSelector.Builder selectorBuilder =
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(Ethernet.TYPE_IPV4).matchIPDst(ip4Prefix);
TrafficTreatment.Builder treatmentBuilder =
DefaultTrafficTreatment.builder();
treatmentBuilder.setEthDst(nextHopMac);
Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
for (Interface intf : interfaceService.getInterfaces()) {
if (!intf.connectPoint().equals(egressConnectPoint)) {
ConnectPoint srcPort = intf.connectPoint();
ingressPoints.add(srcPort);
}
}
MultiPointToSinglePointIntent intent =
new MultiPointToSinglePointIntent(APPID,
selectorBuilder.build(), treatmentBuilder.build(),
ingressPoints, egressConnectPoint);
return intent;
}
/**
* Generates a MAC address based on an IP address.
* For the test we need MAC addresses but the actual values don't have any
* meaning, so we'll just generate them based on the IP address. This means
* we have a deterministic mapping from IP address to MAC address.
*
* @param ipAddress IP address used to generate a MAC address
* @return generated MAC address
*/
static MacAddress generateMacAddress(IpAddress ipAddress) {
byte[] macAddress = new byte[MAC_ADDRESS_LENGTH];
ByteBuffer bb = ByteBuffer.wrap(macAddress);
// Put the IP address bytes into the lower four bytes of the MAC
// address. Leave the first two bytes set to 0.
bb.position(2);
bb.put(ipAddress.toOctets());
return MacAddress.valueOf(bb.array());
}
/**
* Finds out the ConnectPoint for a BGP peer address.
*
* @param bgpPeerAddress the BGP peer address.
*/
private ConnectPoint getConnectPoint(IpAddress bgpPeerAddress) {
ConnectPoint connectPoint = null;
for (BgpPeer bgpPeer: bgpPeers.values()) {
if (bgpPeer.ipAddress().equals(bgpPeerAddress)) {
connectPoint = bgpPeer.connectPoint();
break;
}
}
return connectPoint;
}
}
/*
* Copyright 2014 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.sdnip;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.PortAddresses;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.sdnip.Router.InternalHostListener;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import com.google.common.collect.Sets;
/**
* Test version of the HostService which is used to simulate delays in
* receiving ARP replies, as you would see in a real system due to the time
* it takes to proxy ARP packets to/from the host. Requests are asynchronous,
* and replies may come back to the requestor in a different order than the
* requests were sent, which again you would expect to see in a real system.
*/
public class TestHostService implements HostService {
/**
* The maximum possible delay before an ARP reply is received.
*/
private static final int MAX_ARP_REPLY_DELAY = 30; // milliseconds
/**
* The probability that we already have the MAC address cached when the
* caller calls {@link #getHostsByIp(IpAddress ipAddress)}.
*/
private static final float MAC_ALREADY_KNOWN_PROBABILITY = 0.3f;
private final ScheduledExecutorService replyTaskExecutor;
private final Random random;
/**
* Class constructor.
*/
public TestHostService() {
replyTaskExecutor = Executors.newSingleThreadScheduledExecutor();
random = new Random();
}
/**
* Task used to reply to ARP requests from a different thread. Replies
* usually come on a different thread in the real system, so we need to
* ensure we test this behavior.
*/
private class ReplyTask implements Runnable {
private HostListener listener;
private IpAddress ipAddress;
/**
* Class constructor.
*
* @param listener the client who requests and waits the MAC address
* @param ipAddress the target IP address of the request
*/
public ReplyTask(InternalHostListener listener,
IpAddress ipAddress) {
this.listener = listener;
this.ipAddress = ipAddress;
}
@Override
public void run() {
Host host = getHostsByIp(ipAddress).iterator().next();
HostEvent hostevent =
new HostEvent(HostEvent.Type.HOST_ADDED, host);
listener.event(hostevent);
}
}
@Override
public Set<Host> getHostsByIp(IpAddress ipAddress) {
float replyChance = random.nextFloat();
// We don't care what the attachment point is in the test,
// so for all the hosts, we use a same ConnectPoint.
Host host = new DefaultHost(ProviderId.NONE, HostId.NONE,
SdnIpTest.generateMacAddress(ipAddress), VlanId.NONE,
new HostLocation(SdnIpTest.SW1_ETH1, 1),
Sets.newHashSet(ipAddress));
if (replyChance < MAC_ALREADY_KNOWN_PROBABILITY) {
// Some percentage of the time we already know the MAC address, so
// we reply directly when the requestor asks for the MAC address
return Sets.newHashSet(host);
}
return new HashSet<Host>();
}
@Override
public void startMonitoringIp(IpAddress ipAddress) {
// Randomly select an amount of time to delay the reply coming back to
int delay = random.nextInt(MAX_ARP_REPLY_DELAY);
ReplyTask replyTask = new ReplyTask(
(SdnIpTest.router.new InternalHostListener()), ipAddress);
replyTaskExecutor.schedule(replyTask, delay, TimeUnit.MILLISECONDS);
}
@Override
public int getHostCount() {
return 0;
}
@Override
public Iterable<Host> getHosts() {
return null;
}
@Override
public Host getHost(HostId hostId) {
return null;
}
@Override
public Set<Host> getHostsByVlan(VlanId vlanId) {
return null;
}
@Override
public Set<Host> getHostsByMac(MacAddress mac) {
return null;
}
@Override
public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
return null;
}
@Override
public Set<Host> getConnectedHosts(DeviceId deviceId) {
return null;
}
@Override
public void stopMonitoringIp(IpAddress ip) {
}
@Override
public void requestMac(IpAddress ip) {
}
@Override
public Set<PortAddresses> getAddressBindings() {
return null;
}
@Override
public Set<PortAddresses> getAddressBindingsForPort(ConnectPoint connectPoint) {
return null;
}
@Override
public void addListener(HostListener listener) {
}
@Override
public void removeListener(HostListener listener) {
}
}
......@@ -216,6 +216,8 @@
<feature>onos-app-proxyarp</feature>
<feature>onos-app-config</feature>
<bundle>mvn:org.onosproject/onos-app-sdnip/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-app-routing-api/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-app-routing/@ONOS-VERSION</bundle>
</feature>
<feature name="onos-app-calendar" version="@FEATURE-VERSION"
......