Pingping Lin
Committed by Gerrit Code Review

add a vBNG application

This is a virtual Broadband Network Gateway (BNG) application.
It mainly has 3 functions:
(1) assigns and replies a public IP address to a REST request
    with a private IP address
(2) maintains the mapping from the private IP address to the
    public IP address
(3) installs point to point intents for the host configured
    with private IP address to access Internet

Change-Id: Ie78614a1703422a57f3c325540b927cc4ae603f4
......@@ -43,6 +43,7 @@
<module>routing</module>
<module>routing-api</module>
<module>reactive-routing</module>
<module>virtualbng</module>
<module>bgprouter</module>
<module>test</module>
<module>segmentrouting</module>
......
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ 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.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
<repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<bundle>mvn:${project.groupId}/onos-app-virtualbng/${project.version}</bundle>
<feature>onos-thirdparty-web</feature>
</feature>
</features>
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-virtualbng</artifactId>
<packaging>bundle</packaging>
<description>A virtual Broadband Network Gateway(BNG) application</description>
<properties>
<onos.app.name>org.onosproject.virtualbng</onos.app.name>
<web.context>/onos/virtualbng</web.context>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<_wab>src/main/webapp/</_wab>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.slf4j,
javax.ws.rs,
com.sun.jersey.api.core,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
com.fasterxml.jackson.databind,
com.google.common.*,
org.onlab.packet.*,
org.onlab.rest.*,
org.onosproject.*
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
/*
* 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.virtualbng;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Collections;
import java.util.List;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
/**
* Contains the configuration data for virtual BNG that has been read from a
* JSON-formatted configuration file.
*/
public final class VbngConfiguration {
private final List<IpPrefix> localPublicIpPrefixes;
private final IpAddress nextHopIpAddress;
/**
* Default constructor.
*/
private VbngConfiguration() {
localPublicIpPrefixes = null;
nextHopIpAddress = null;
}
/**
* Constructor.
*
* @param nextHopIpAddress the IP address of the next hop
* @param prefixes the public IP prefix list for local SDN network
*/
@JsonCreator
public VbngConfiguration(@JsonProperty("localPublicIpPrefixes")
List<IpPrefix> prefixes,
@JsonProperty("nextHopIpAddress")
IpAddress nextHopIpAddress) {
localPublicIpPrefixes = prefixes;
this.nextHopIpAddress = nextHopIpAddress;
}
/**
* Gets a list of public IP prefixes configured for local SDN network.
*
* @return the list of public IP prefixes
*/
public List<IpPrefix> getLocalPublicIpPrefixes() {
return Collections.unmodifiableList(localPublicIpPrefixes);
}
/**
* Gets the IP address configured for the next hop (upstream gateway).
*
* @return the IP address of the next hop
*/
public IpAddress getNextHopIpAddress() {
return nextHopIpAddress;
}
}
/*
* 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.virtualbng;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
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.Service;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Implementation of ConfigurationService which reads virtual BNG
* configuration from a file.
*/
@Component(immediate = true)
@Service
public class VbngConfigurationManager implements VbngConfigurationService {
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String CONFIG_DIR = "../config";
private static final String DEFAULT_CONFIG_FILE = "virtualbng.json";
private String configFileName = DEFAULT_CONFIG_FILE;
// If all the IP addresses of one IP prefix are assigned, then we
// mark the value of this IP prefix as false, otherwise as true.
private Map<IpPrefix, Boolean> localPublicIpPrefixes =
new ConcurrentHashMap<>();
// Map from private IP address to public IP address
private Map<IpAddress, IpAddress> ipAddressMap =
new ConcurrentHashMap<>();
private IpAddress nextHopIpAddress;
@Activate
public void activate() {
readConfiguration();
log.info("vBNG configuration service started");
}
@Deactivate
public void deactivate() {
log.info("vBNG configuration service stopped");
}
/**
* Instructs the configuration reader to read the configuration from the
* file.
*/
public void readConfiguration() {
readConfiguration(configFileName);
}
/**
* Reads virtual BNG information contained in configuration file.
*
* @param configFilename the name of the configuration file for the virtual
* BNG application
*/
private void readConfiguration(String configFilename) {
File configFile = new File(CONFIG_DIR, configFilename);
ObjectMapper mapper = new ObjectMapper();
try {
log.info("Loading config: {}", configFile.getAbsolutePath());
VbngConfiguration config = mapper.readValue(configFile,
VbngConfiguration.class);
for (IpPrefix prefix : config.getLocalPublicIpPrefixes()) {
localPublicIpPrefixes.put(prefix, true);
}
nextHopIpAddress = config.getNextHopIpAddress();
} catch (FileNotFoundException e) {
log.warn("Configuration file not found: {}", configFileName);
} catch (IOException e) {
log.error("Error loading configuration", e);
}
}
@Override
public IpAddress getNextHopIpAddress() {
return nextHopIpAddress;
}
// TODO handle the case: the number of public IP addresses is not enough
// for 1:1 mapping from public IP to private IP.
@Override
public IpAddress getAvailablePublicIpAddress(IpAddress privateIpAddress) {
// If there is already a mapping entry for the private IP address,
// then fetch the public IP address in the mapping entry and return it.
IpAddress publicIpAddress = ipAddressMap.get(privateIpAddress);
if (publicIpAddress != null) {
return publicIpAddress;
}
// There is no mapping for the private IP address.
Iterator<Entry<IpPrefix, Boolean>> prefixes =
localPublicIpPrefixes.entrySet().iterator();
while (prefixes.hasNext()) {
Entry<IpPrefix, Boolean> prefix = prefixes.next();
if (!prefix.getValue()) {
continue;
}
if (prefix.getKey().prefixLength() == 32) {
updateIpPrefixStatus(prefix.getKey(), false);
publicIpAddress = prefix.getKey().address();
ipAddressMap.put(privateIpAddress, publicIpAddress);
return publicIpAddress;
}
int prefixLen = prefix.getKey().prefixLength();
int availableIpNum = (int) Math.pow(2,
IpPrefix.MAX_INET_MASK_LENGTH - prefixLen) - 1;
for (int i = 1; i <= availableIpNum; i++) {
publicIpAddress =
increaseIpAddress(prefix.getKey().address(), i);
if (publicIpAddress == null) {
return null;
}
if (ipAddressMap.values().contains(publicIpAddress)) {
continue;
} else if (i == availableIpNum) {
// All the IP addresses are assigned out
// Update this IP prefix status to false
// Note: in this version we do not consider the
// IP recycling issue.
updateIpPrefixStatus(prefix.getKey(), false);
ipAddressMap.put(privateIpAddress, publicIpAddress);
return publicIpAddress;
} else {
ipAddressMap.put(privateIpAddress, publicIpAddress);
return publicIpAddress;
}
}
}
return null;
}
/**
* Generates a new IP address base on a given IP address plus a number to
* increase.
*
* @param ipAddress the IP address to increase
* @param num the number for ipAddress to add
* @return the new IP address after increase
*/
private IpAddress increaseIpAddress(IpAddress ipAddress, int num) {
if (ipAddress.isIp6()) {
log.info("vBNG currently does not handle IPv6");
return null;
}
return IpAddress.valueOf(ipAddress.getIp4Address().toInt() + num);
}
/**
* Updates the IP prefix status in the local public IP prefix table.
*
* @param ipPprefix the IP prefix to update
* @param b the new value for the IP prefix
*/
private void updateIpPrefixStatus(IpPrefix ipPprefix, boolean b) {
localPublicIpPrefixes.replace(ipPprefix, b);
}
}
/*
* 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.virtualbng;
import org.onlab.packet.IpAddress;
/**
* Provides information about the virtual BNG configuration.
*/
public interface VbngConfigurationService {
/**
* Gets the IP address configured for the next hop.
*
* @return the IP address of next hop
*/
public IpAddress getNextHopIpAddress();
/**
* Gets an available public IP address from local public IP prefixes.
*
* @param privateIpAddress a private IP address
* @return an available public IP address if it exists, otherwise null
*/
public IpAddress getAvailablePublicIpAddress(IpAddress privateIpAddress);
}
/*
* 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.virtualbng;
import static org.slf4j.LoggerFactory.getLogger;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.onlab.packet.IpAddress;
import org.onlab.rest.BaseResource;
import org.slf4j.Logger;
/**
* This class provides REST services to virtual BNG.
*/
@Path("privateip")
public class VbngResource extends BaseResource {
private final Logger log = getLogger(getClass());
@POST
@Path("{privateip}")
public String privateIpNotification(@PathParam("privateip")
String privateIp) {
if (privateIp == null) {
log.info("Private IP address is null");
return "0";
}
log.info("Received a private IP address : {}", privateIp);
IpAddress privateIpAddress = IpAddress.valueOf(privateIp);
VbngService vbngService = get(VbngService.class);
IpAddress publicIpAddress = null;
synchronized (this) {
// Create a virtual BNG
publicIpAddress = vbngService.createVbng(privateIpAddress);
}
if (publicIpAddress != null) {
return publicIpAddress.toString();
} else {
return "0";
}
}
}
\ No newline at end of file
/*
* 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.virtualbng;
import org.onlab.packet.IpAddress;
/**
* Provides service of the virtual BNG.
*/
public interface VbngService {
/**
* Creates a virtual BNG.
* <p>
* It firstly finds out an available local public IP address. Then, it
* sets up paths between the host configured with private IP and
* next hop. Finally it returns the public IP address.
* </p>
*
* @param privateIpAddress the private IP address
* @return the public address if a virtual BGN is successfully created,
* otherwise return null
*/
public IpAddress createVbng(IpAddress privateIpAddress);
}
/*
* 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.
*/
/**
* A virtual Broadband Network Gateway (BNG) application.
*/
package org.onosproject.virtualbng;
<?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.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>ONOS Virual BNG APP REST API</display-name>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.classnames</param-name>
<param-value>
org.onosproject.virtualbng.VbngResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>