alshabib
Committed by Ali Al-Shabibi

removing cord-related applications

Change-Id: Ia232adeecf0f5ea17061b3fb7ca851b6a00e0f99
Showing 96 changed files with 0 additions and 4789 deletions
......@@ -99,7 +99,6 @@ APPS = [
# Apps
'//apps/dhcp:onos-apps-dhcp-oar',
'//apps/fwd:onos-apps-fwd-oar',
'//apps/aaa:onos-apps-aaa-oar',
'//apps/acl:onos-apps-acl-oar',
'//apps/bgprouter:onos-apps-bgprouter-oar',
'//apps/cip:onos-apps-cip-oar',
......@@ -109,10 +108,7 @@ APPS = [
'//apps/segmentrouting:onos-apps-segmentrouting-oar',
'//apps/gangliametrics:onos-apps-gangliametrics-oar',
'//apps/graphitemetrics:onos-apps-graphitemetrics-oar',
'//apps/igmp:onos-apps-igmp-oar',
'//apps/cordmcast:onos-apps-cordmcast-oar',
'//apps/flowanalyzer:onos-apps-flowanalyzer-oar',
'//apps/olt:onos-apps-olt-oar',
'//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar',
'//apps/metrics:onos-apps-metrics-oar',
'//apps/mfwd:onos-apps-mfwd-oar',
......@@ -137,7 +133,6 @@ APPS = [
'//apps/test/loadtest:onos-apps-test-loadtest-oar',
'//apps/test/messaging-perf:onos-apps-test-messaging-perf-oar',
'//apps/virtualbng:onos-apps-virtualbng-oar',
'//apps/cordvtn:onos-apps-cordvtn-oar',
'//apps/vpls:onos-apps-vpls-oar',
'//apps/vrouter:onos-apps-vrouter-oar',
'//apps/vtn:onos-apps-vtn-oar',
......@@ -145,7 +140,6 @@ APPS = [
'//apps/openstacknode:onos-apps-openstacknode-oar',
'//apps/cpman/app:onos-apps-cpman-app-oar',
'//apps/xosclient:onos-apps-xosclient-oar',
'//apps/cordconfig:onos-apps-cordconfig',
]
APP_JARS = [
......@@ -154,7 +148,6 @@ APP_JARS = [
'//apps/dhcp/api:onos-apps-dhcp-api',
'//apps/dhcp/app:onos-apps-dhcp-app',
'//apps/fwd:onos-apps-fwd',
'//apps/olt:onos-apps-olt-api',
'//apps/iptopology-api:onos-apps-iptopology-api',
'//apps/openstacknode:onos-apps-openstacknode',
'//apps/routing:onos-apps-routing',
......
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//lib:org.apache.karaf.shell.console',
'//cli:onos-cli',
]
TEST_DEPS = [
'//lib:TEST_ADAPTERS',
'//core/common:onos-core-common',
]
osgi_jar_with_tests (
deps = COMPILE_DEPS,
test_deps = TEST_DEPS,
)
onos_app (
title = 'Authentication App',
category = 'Security',
url = 'http://onosproject.org',
description = 'ONOS authentication application.',
)
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<app name="org.onosproject.aaa" origin="ATT" version="${project.version}"
category="Security" url="http://onosproject.org" title="Authentication App"
featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
features="${project.artifactId}">
<description>${project.description}</description>
<artifact>mvn:${project.groupId}/${project.artifactId}/${project.version}</artifact>
</app>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<feature>onos-api</feature>
<bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
</feature>
</features>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-aaa</artifactId>
<packaging>bundle</packaging>
<description>ONOS authentication application</description>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.onosproject</groupId>
<artifactId>onos-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.aaa;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.basics.BasicElementConfig;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* Network config for the AAA app.
*/
public class AaaConfig extends Config<ApplicationId> {
private static final String RADIUS_IP = "radiusIp";
private static final String RADIUS_SERVER_PORT = "1812";
private static final String RADIUS_MAC = "radiusMac";
private static final String NAS_IP = "nasIp";
private static final String NAS_MAC = "nasMac";
private static final String RADIUS_SECRET = "radiusSecret";
private static final String RADIUS_SWITCH = "radiusSwitch";
private static final String RADIUS_PORT = "radiusPort";
// RADIUS server IP address
protected static final String DEFAULT_RADIUS_IP = "10.128.10.4";
// RADIUS MAC address
protected static final String DEFAULT_RADIUS_MAC = "00:00:00:00:01:10";
// NAS IP address
protected static final String DEFAULT_NAS_IP = "10.128.9.244";
// NAS MAC address
protected static final String DEFAULT_NAS_MAC = "00:00:00:00:10:01";
// RADIUS server shared secret
protected static final String DEFAULT_RADIUS_SECRET = "ONOSecret";
// Radius Switch Id
protected static final String DEFAULT_RADIUS_SWITCH = "of:90e2ba82f97791e9";
// Radius Port Number
protected static final String DEFAULT_RADIUS_PORT = "129";
// Radius Server UDP Port Number
protected static final String DEFAULT_RADIUS_SERVER_PORT = "1812";
/**
* Gets the value of a string property, protecting for an empty
* JSON object.
*
* @param name name of the property
* @param defaultValue default value if none has been specified
* @return String value if one os found, default value otherwise
*/
private String getStringProperty(String name, String defaultValue) {
if (object == null) {
return defaultValue;
}
return get(name, defaultValue);
}
/**
* Returns the NAS ip.
*
* @return ip address or null if not set
*/
public InetAddress nasIp() {
try {
return InetAddress.getByName(getStringProperty(NAS_IP, DEFAULT_NAS_IP));
} catch (UnknownHostException e) {
return null;
}
}
/**
* Sets the NAS ip.
*
* @param ip new ip address; null to clear
* @return self
*/
public BasicElementConfig nasIp(String ip) {
return (BasicElementConfig) setOrClear(NAS_IP, ip);
}
/**
* Returns the RADIUS server ip.
*
* @return ip address or null if not set
*/
public InetAddress radiusIp() {
try {
return InetAddress.getByName(getStringProperty(RADIUS_IP, DEFAULT_RADIUS_IP));
} catch (UnknownHostException e) {
return null;
}
}
/**
* Sets the RADIUS server ip.
*
* @param ip new ip address; null to clear
* @return self
*/
public BasicElementConfig radiusIp(String ip) {
return (BasicElementConfig) setOrClear(RADIUS_IP, ip);
}
/**
* Returns the RADIUS MAC address.
*
* @return mac address or null if not set
*/
public String radiusMac() {
return getStringProperty(RADIUS_MAC, DEFAULT_RADIUS_MAC);
}
/**
* Sets the RADIUS MAC address.
*
* @param mac new MAC address; null to clear
* @return self
*/
public BasicElementConfig radiusMac(String mac) {
return (BasicElementConfig) setOrClear(RADIUS_MAC, mac);
}
/**
* Returns the RADIUS MAC address.
*
* @return mac address or null if not set
*/
public String nasMac() {
return getStringProperty(NAS_MAC, DEFAULT_NAS_MAC);
}
/**
* Sets the RADIUS MAC address.
*
* @param mac new MAC address; null to clear
* @return self
*/
public BasicElementConfig nasMac(String mac) {
return (BasicElementConfig) setOrClear(NAS_MAC, mac);
}
/**
* Returns the RADIUS secret.
*
* @return radius secret or null if not set
*/
public String radiusSecret() {
return getStringProperty(RADIUS_SECRET, DEFAULT_RADIUS_SECRET);
}
/**
* Sets the RADIUS secret.
*
* @param secret new MAC address; null to clear
* @return self
*/
public BasicElementConfig radiusSecret(String secret) {
return (BasicElementConfig) setOrClear(RADIUS_SECRET, secret);
}
/**
* Returns the ID of the RADIUS switch.
*
* @return radius switch ID or null if not set
*/
public String radiusSwitch() {
return getStringProperty(RADIUS_SWITCH, DEFAULT_RADIUS_SWITCH);
}
/**
* Sets the ID of the RADIUS switch.
*
* @param switchId new RADIUS switch ID; null to clear
* @return self
*/
public BasicElementConfig radiusSwitch(String switchId) {
return (BasicElementConfig) setOrClear(RADIUS_SWITCH, switchId);
}
/**
* Returns the RADIUS port.
*
* @return radius port or null if not set
*/
public long radiusPort() {
return Integer.parseInt(getStringProperty(RADIUS_PORT, DEFAULT_RADIUS_PORT));
}
/**
* Sets the RADIUS port.
*
* @param port new RADIUS port; null to clear
* @return self
*/
public BasicElementConfig radiusPort(long port) {
return (BasicElementConfig) setOrClear(RADIUS_PORT, port);
}
/**
* Returns the RADIUS server UDP port.
*
* @return radius server UDP port.
*/
public short radiusServerUdpPort() {
return Short.parseShort(getStringProperty(RADIUS_SERVER_PORT,
DEFAULT_RADIUS_SERVER_PORT));
}
/**
* Sets the RADIUS port.
*
* @param port new RADIUS UDP port; -1 to clear
* @return self
*/
public BasicElementConfig radiusServerUdpPort(short port) {
return (BasicElementConfig) setOrClear(RADIUS_SERVER_PORT, (long) port);
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.aaa;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
/**
* Shows the users in the aaa.
*/
@Command(scope = "onos", name = "aaa-users",
description = "Shows the aaa users")
public class AaaShowUsersCommand extends AbstractShellCommand {
@Override
protected void execute() {
String[] state = {
"IDLE",
"STARTED",
"PENDING",
"AUTHORIZED",
"UNAUTHORIZED"
};
for (StateMachine stateMachine : StateMachine.sessionIdMap().values()) {
String deviceId = stateMachine.supplicantConnectpoint().deviceId().toString();
String portNum = stateMachine.supplicantConnectpoint().port().toString();
String username = new String(stateMachine.username());
print("UserName=%s,CurrentState=%s,DeviceId=%s,PortNumber=%s",
username, state[stateMachine.state()], deviceId, portNum);
}
}
}
/*
*
* Copyright 2015 AT&T Foundry
*
* 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.aaa;
/**
* Exception for the State Machine.
*/
class StateMachineException extends Exception {
public StateMachineException(String message) {
super(message);
}
}
/*
*
* Copyright 2015 AT&T Foundry
*
* 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.aaa;
/**
* Exception raised when the transition from one state to another is invalid.
*/
class StateMachineInvalidTransitionException extends StateMachineException {
public StateMachineInvalidTransitionException(String message) {
super(message);
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* AAA implmentation.
*/
package org.onosproject.aaa;
<!--
~ Copyright 2016-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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.aaa.AaaShowUsersCommand"/>
</command>
</command-bundle>
</blueprint>
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.aaa;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onlab.packet.EAP;
import org.onlab.packet.EAPOL;
import org.onlab.packet.Ethernet;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* Set of tests of the ONOS application component. These use an existing RADIUS
* server and sends live packets over the network to it.
*/
@Ignore ("This should not be run as part of the standard build")
public class AaaIntegrationTest extends AaaTestBase {
private AaaManager aaa;
/**
* Mocks the network config registry.
*/
@SuppressWarnings("unchecked")
static final class TestNetworkConfigRegistry
extends NetworkConfigRegistryAdapter {
@Override
public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
return (C) new AaaConfig();
}
}
/**
* Sets up the services required by the AAA application.
*/
@Before
public void setUp() {
aaa = new AaaManager();
aaa.netCfgService = new TestNetworkConfigRegistry();
aaa.coreService = new CoreServiceAdapter();
aaa.packetService = new MockPacketService();
aaa.activate();
}
/**
* Fetches the sent packet at the given index. The requested packet
* must be the last packet on the list.
*
* @param index index into sent packets array
* @return packet
*/
private Ethernet fetchPacket(int index) {
for (int iteration = 0; iteration < 20; iteration++) {
if (savedPackets.size() > index) {
return (Ethernet) savedPackets.get(index);
} else {
try {
Thread.sleep(250);
} catch (Exception ex) {
return null;
}
}
}
return null;
}
/**
* Tests the authentication path through the AAA application by sending
* packets to the RADIUS server and checking the state machine
* transitions.
*
* @throws Exception when an unhandled error occurs
*/
@Test
public void testAuthentication() throws Exception {
// (1) Supplicant start up
Ethernet startPacket = constructSupplicantStartPacket();
sendPacket(startPacket);
Ethernet responsePacket = fetchPacket(0);
assertThat(responsePacket, notNullValue());
checkRadiusPacket(aaa, responsePacket, EAP.REQUEST);
// (2) Supplicant identify
Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
sendPacket(identifyPacket);
// State machine should have been created by now
StateMachine stateMachine =
StateMachine.lookupStateMachineBySessionId(SESSION_ID);
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
// (3) RADIUS MD5 challenge
Ethernet radiusChallengeMD5Packet = fetchPacket(1);
assertThat(radiusChallengeMD5Packet, notNullValue());
checkRadiusPacket(aaa, radiusChallengeMD5Packet, EAP.REQUEST);
// (4) Supplicant MD5 response
Ethernet md5RadiusPacket =
constructSupplicantIdentifyPacket(stateMachine,
EAP.ATTR_MD5,
stateMachine.challengeIdentifier(),
radiusChallengeMD5Packet);
sendPacket(md5RadiusPacket);
// (5) RADIUS Success
Ethernet successRadiusPacket = fetchPacket(2);
assertThat(successRadiusPacket, notNullValue());
EAPOL successEapol = (EAPOL) successRadiusPacket.getPayload();
EAP successEap = (EAP) successEapol.getPayload();
assertThat(successEap.getCode(), is(EAP.SUCCESS));
// State machine should be in authorized state
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.aaa;
import com.google.common.base.Charsets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.BasePacket;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.EAP;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.RADIUS;
import org.onlab.packet.RADIUSAttribute;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigRegistryAdapter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* Set of tests of the ONOS application component.
*/
public class AaaManagerTest extends AaaTestBase {
static final String BAD_IP_ADDRESS = "198.51.100.0";
private AaaManager aaaManager;
class AaaManagerWithoutRadiusServer extends AaaManager {
protected void sendRadiusPacket(RADIUS radiusPacket) {
savePacket(radiusPacket);
}
}
/**
* Mocks the AAAConfig class to force usage of an unroutable address for the
* RADIUS server.
*/
static class MockAaaConfig extends AaaConfig {
@Override
public InetAddress radiusIp() {
try {
return InetAddress.getByName(BAD_IP_ADDRESS);
} catch (UnknownHostException ex) {
// can't happen
throw new IllegalStateException(ex);
}
}
}
/**
* Mocks the network config registry.
*/
@SuppressWarnings("unchecked")
private static final class TestNetworkConfigRegistry
extends NetworkConfigRegistryAdapter {
@Override
public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
AaaConfig aaaConfig = new MockAaaConfig();
return (C) aaaConfig;
}
}
/**
* Constructs an Ethernet packet containing a RADIUS challenge
* packet.
*
* @param challengeCode code to use in challenge packet
* @param challengeType type to use in challenge packet
* @return Ethernet packet
*/
private RADIUS constructRadiusCodeAccessChallengePacket(byte challengeCode, byte challengeType) {
String challenge = "12345678901234567";
EAP eap = new EAP(challengeType, (byte) 1, challengeType,
challenge.getBytes(Charsets.US_ASCII));
eap.setIdentifier((byte) 1);
RADIUS radius = new RADIUS();
radius.setCode(challengeCode);
radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
challenge.getBytes(Charsets.US_ASCII));
radius.setPayload(eap);
radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
eap.serialize());
return radius;
}
/**
* Sets up the services required by the AAA application.
*/
@Before
public void setUp() {
aaaManager = new AaaManagerWithoutRadiusServer();
aaaManager.netCfgService = new TestNetworkConfigRegistry();
aaaManager.coreService = new CoreServiceAdapter();
aaaManager.packetService = new MockPacketService();
aaaManager.activate();
}
/**
* Tears down the AAA application.
*/
@After
public void tearDown() {
aaaManager.deactivate();
}
/**
* Extracts the RADIUS packet from a packet sent by the supplicant.
*
* @param radius RADIUS packet sent by the supplicant
* @throws DeserializationException if deserialization of the packet contents
* fails.
*/
private void checkRadiusPacketFromSupplicant(RADIUS radius)
throws DeserializationException {
assertThat(radius, notNullValue());
EAP eap = radius.decapsulateMessage();
assertThat(eap, notNullValue());
}
/**
* Fetches the sent packet at the given index. The requested packet
* must be the last packet on the list.
*
* @param index index into sent packets array
* @return packet
*/
private BasePacket fetchPacket(int index) {
BasePacket packet = savedPackets.get(index);
assertThat(packet, notNullValue());
return packet;
}
/**
* Tests the authentication path through the AAA application.
*
* @throws DeserializationException if packed deserialization fails.
*/
@Test
public void testAuthentication() throws Exception {
// (1) Supplicant start up
Ethernet startPacket = constructSupplicantStartPacket();
sendPacket(startPacket);
Ethernet responsePacket = (Ethernet) fetchPacket(0);
checkRadiusPacket(aaaManager, responsePacket, EAP.ATTR_IDENTITY);
// (2) Supplicant identify
Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
sendPacket(identifyPacket);
RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
checkRadiusPacketFromSupplicant(radiusIdentifyPacket);
assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
is("testuser"));
IpAddress nasIp =
IpAddress.valueOf(IpAddress.Version.INET,
radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
.getValue());
assertThat(nasIp.toString(), is(aaaManager.nasIpAddress.getHostAddress()));
// State machine should have been created by now
StateMachine stateMachine =
StateMachine.lookupStateMachineBySessionId(SESSION_ID);
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
// (3) RADIUS MD5 challenge
RADIUS radiusCodeAccessChallengePacket =
constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5);
aaaManager.radiusListener.handleRadiusPacket(radiusCodeAccessChallengePacket);
Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
checkRadiusPacket(aaaManager, radiusChallengeMD5Packet, EAP.ATTR_MD5);
// (4) Supplicant MD5 response
Ethernet md5RadiusPacket =
constructSupplicantIdentifyPacket(stateMachine,
EAP.ATTR_MD5,
stateMachine.challengeIdentifier(),
radiusChallengeMD5Packet);
sendPacket(md5RadiusPacket);
RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 0));
assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
// State machine should be in pending state
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
// (5) RADIUS Success
RADIUS successPacket =
constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT, EAP.SUCCESS);
aaaManager.radiusListener.handleRadiusPacket((successPacket));
Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);
checkRadiusPacket(aaaManager, supplicantSuccessPacket, EAP.SUCCESS);
// State machine should be in authorized state
assertThat(stateMachine, notNullValue());
assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
}
/**
* Tests the default configuration.
*/
@Test
public void testConfig() {
assertThat(aaaManager.nasIpAddress.getHostAddress(), is(AaaConfig.DEFAULT_NAS_IP));
assertThat(aaaManager.nasMacAddress, is(AaaConfig.DEFAULT_NAS_MAC));
assertThat(aaaManager.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
assertThat(aaaManager.radiusMacAddress, is(AaaConfig.DEFAULT_RADIUS_MAC));
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.aaa;
import org.onlab.packet.BasePacket;
import org.onlab.packet.EAP;
import org.onlab.packet.EAPOL;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.DefaultPacketContext;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketServiceAdapter;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.LinkedList;
import java.util.List;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.onosproject.net.NetTestTools.connectPoint;
/**
* Common methods for AAA app testing.
*/
public class AaaTestBase {
MacAddress clientMac = MacAddress.valueOf("1a:1a:1a:1a:1a:1a");
MacAddress serverMac = MacAddress.valueOf("2a:2a:2a:2a:2a:2a");
// Our session id will be the device ID ("of:1") with the port ("1") concatenated
static final String SESSION_ID = "of:11";
List<BasePacket> savedPackets = new LinkedList<>();
PacketProcessor packetProcessor;
/**
* Saves the given packet onto the saved packets list.
*
* @param packet packet to save
*/
void savePacket(BasePacket packet) {
savedPackets.add(packet);
}
/**
* Keeps a reference to the PacketProcessor and saves the OutboundPackets.
*/
class MockPacketService extends PacketServiceAdapter {
@Override
public void addProcessor(PacketProcessor processor, int priority) {
packetProcessor = processor;
}
@Override
public void emit(OutboundPacket packet) {
try {
Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
0, packet.data().array().length);
savePacket(eth);
} catch (Exception e) {
fail(e.getMessage());
}
}
}
/**
* Mocks the DefaultPacketContext.
*/
final class TestPacketContext extends DefaultPacketContext {
private TestPacketContext(long time, InboundPacket inPkt,
OutboundPacket outPkt, boolean block) {
super(time, inPkt, outPkt, block);
}
@Override
public void send() {
// We don't send anything out.
}
}
/**
* Sends an Ethernet packet to the process method of the Packet Processor.
*
* @param reply Ethernet packet
*/
void sendPacket(Ethernet reply) {
final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());
InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1),
reply,
byteBuffer);
PacketContext context = new TestPacketContext(127L, inPacket, null, false);
packetProcessor.process(context);
}
/**
* Constructs an Ethernet packet containing identification payload.
*
* @return Ethernet packet
*/
Ethernet constructSupplicantIdentifyPacket(StateMachine stateMachine,
byte type,
byte id,
Ethernet radiusChallenge)
throws Exception {
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(clientMac.toBytes());
eth.setSourceMACAddress(serverMac.toBytes());
eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
eth.setVlanID((short) 2);
String username = "testuser";
byte[] data = username.getBytes();
if (type == EAP.ATTR_MD5) {
String password = "testpassword";
EAPOL eapol = (EAPOL) radiusChallenge.getPayload();
EAP eap = (EAP) eapol.getPayload();
byte[] identifier = new byte[password.length() + eap.getData().length];
identifier[0] = stateMachine.challengeIdentifier();
System.arraycopy(password.getBytes(), 0, identifier, 1, password.length());
System.arraycopy(eap.getData(), 1, identifier, 1 + password.length(), 16);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(identifier);
data = new byte[17];
data[0] = (byte) 16;
System.arraycopy(hash, 0, data, 1, 16);
}
EAP eap = new EAP(EAP.RESPONSE, (byte) 1, type,
data);
eap.setIdentifier(id);
// eapol header
EAPOL eapol = new EAPOL();
eapol.setEapolType(EAPOL.EAPOL_PACKET);
eapol.setPacketLength(eap.getLength());
// eap part
eapol.setPayload(eap);
eth.setPayload(eapol);
eth.setPad(true);
return eth;
}
/**
* Constructs an Ethernet packet containing a EAPOL_START Payload.
*
* @return Ethernet packet
*/
Ethernet constructSupplicantStartPacket() {
Ethernet eth = new Ethernet();
eth.setDestinationMACAddress(clientMac.toBytes());
eth.setSourceMACAddress(serverMac.toBytes());
eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
eth.setVlanID((short) 2);
EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 2, EAPOL.EAPOL_START, null);
// eapol header
EAPOL eapol = new EAPOL();
eapol.setEapolType(EAPOL.EAPOL_START);
eapol.setPacketLength(eap.getLength());
// eap part
eapol.setPayload(eap);
eth.setPayload(eapol);
eth.setPad(true);
return eth;
}
/**
* Checks the contents of a RADIUS packet being sent to the RADIUS server.
*
* @param radiusPacket packet to check
* @param code expected code
*/
void checkRadiusPacket(AaaManager aaaManager, Ethernet radiusPacket, byte code) {
assertThat(radiusPacket.getSourceMAC(),
is(MacAddress.valueOf(aaaManager.nasMacAddress)));
assertThat(radiusPacket.getDestinationMAC(), is(serverMac));
assertThat(radiusPacket.getPayload(), instanceOf(EAPOL.class));
EAPOL eapol = (EAPOL) radiusPacket.getPayload();
assertThat(eapol, notNullValue());
assertThat(eapol.getEapolType(), is(EAPOL.EAPOL_PACKET));
assertThat(eapol.getPayload(), instanceOf(EAP.class));
EAP eap = (EAP) eapol.getPayload();
assertThat(eap, notNullValue());
assertThat(eap.getCode(), is(code));
}
}
COMPILE_DEPS = [
'//lib:CORE_DEPS',
]
osgi_jar_with_tests (
deps = COMPILE_DEPS,
)
onos_app (
title = 'CORD Configuration',
category = 'Utility',
url = 'http://onosproject.org',
description = 'CORD configuration meta application.',
)
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-cord-config</artifactId>
<packaging>bundle</packaging>
<description>Cord configuration meta applications </description>
<properties>
<onos.app.name>org.onosproject.cord-config</onos.app.name>
<onos.app.title>Cord Configuratuon Meta Application</onos.app.title>
<onos.app.category>Utility</onos.app.category>
<onos.app.url>http://opencord.org</onos.app.url>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
</dependency>
</dependencies>
</project>
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordconfig.access;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.onlab.packet.MacAddress;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.Config;
import java.util.Map;
import java.util.Optional;
import static org.onosproject.net.config.Config.FieldPresence.MANDATORY;
import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
/**
* Represents configuration for an OLT agent.
*/
public class AccessAgentConfig extends Config<DeviceId> {
private static final String OLTS = "olts";
private static final String AGENT_MAC = "mac";
// TODO: Remove this, it is only useful as long as XOS doesn't manage this.
private static final String VTN_LOCATION = "vtn-location";
@Override
public boolean isValid() {
return hasOnlyFields(OLTS, AGENT_MAC, VTN_LOCATION) &&
isMacAddress(AGENT_MAC, MANDATORY) &&
isConnectPoint(VTN_LOCATION, OPTIONAL) &&
isValidOlts();
}
/**
* Gets the access agent configuration for this device.
*
* @return access agent configuration
*/
public AccessAgentData getAgent() {
JsonNode olts = node.get(OLTS);
Map<ConnectPoint, MacAddress> oltMacInfo = Maps.newHashMap();
olts.fields().forEachRemaining(item -> oltMacInfo.put(
new ConnectPoint(subject(), PortNumber.fromString(item.getKey())),
MacAddress.valueOf(item.getValue().asText())));
MacAddress agentMac = MacAddress.valueOf(node.path(AGENT_MAC).asText());
JsonNode vtn = node.path(VTN_LOCATION);
Optional<ConnectPoint> vtnLocation;
if (vtn.isMissingNode()) {
vtnLocation = Optional.empty();
} else {
vtnLocation = Optional.of(ConnectPoint.deviceConnectPoint(vtn.asText()));
}
return new AccessAgentData(subject(), oltMacInfo, agentMac, vtnLocation);
}
private boolean isValidOlts() {
JsonNode olts = node.get(OLTS);
if (!olts.isObject()) {
return false;
}
return !Iterators.any(olts.fields(), item -> !StringUtils.isNumeric(item.getKey()) ||
!isMacAddress((ObjectNode) olts, item.getKey(), MANDATORY));
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordconfig.access;
import com.google.common.collect.ImmutableMap;
import org.onlab.packet.MacAddress;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import java.util.Map;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Information about an access agent.
*/
public class AccessAgentData {
private static final String DEVICE_ID_MISSING = "Device ID cannot be null";
private static final String OLT_INFO_MISSING = "OLT information cannot be null";
private static final String AGENT_MAC_MISSING = "Agent mac cannot be null";
private static final String VTN_MISSING = "VTN location cannot be null";
private final Map<ConnectPoint, MacAddress> oltMacInfo;
private final MacAddress agentMac;
private final Optional<ConnectPoint> vtnLocation;
private final DeviceId deviceId;
/**
* Constucts an agent configuration for a given device.
*
* @param deviceId access device id
* @param oltMacInfo a map of olt chips and their mac address
* @param agentMac the mac address of the agent
* @param vtnLocation the location of the agent
*/
public AccessAgentData(DeviceId deviceId, Map<ConnectPoint, MacAddress> oltMacInfo,
MacAddress agentMac, Optional<ConnectPoint> vtnLocation) {
this.deviceId = checkNotNull(deviceId, DEVICE_ID_MISSING);
this.oltMacInfo = checkNotNull(oltMacInfo, OLT_INFO_MISSING);
this.agentMac = checkNotNull(agentMac, AGENT_MAC_MISSING);
this.vtnLocation = checkNotNull(vtnLocation, VTN_MISSING);
}
/**
* Retrieves the access device ID.
*
* @return device ID
*/
public DeviceId deviceId() {
return deviceId;
}
/**
* Returns the mapping of olt chips to mac addresses. Each chip is
* symbolized by a connect point.
*
* @return a mapping of chips (as connect points) to mac addresses
*/
public Map<ConnectPoint, MacAddress> getOltMacInfo() {
return ImmutableMap.copyOf(oltMacInfo);
}
/**
* Reuturns the agents mac address.
*
* @return a mac address
*/
public MacAddress getAgentMac() {
return agentMac;
}
/**
* Returns the location of the agent.
*
* @return a connection point
*/
public Optional<ConnectPoint> getVtnLocation() {
return vtnLocation;
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordconfig.access;
import org.onosproject.net.DeviceId;
import com.fasterxml.jackson.databind.JsonNode;
import org.onlab.packet.VlanId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.Config;
import java.util.Optional;
/**
* Config object for access device data.
*/
public class AccessDeviceConfig extends Config<DeviceId> {
private static final String UPLINK = "uplink";
private static final String VLAN = "vlan";
private static final String DEFAULT_VLAN = "defaultVlan";
/**
* Gets the access device configuration for this device.
*
* @return access device configuration
*/
public AccessDeviceData getOlt() {
PortNumber uplink = PortNumber.portNumber(node.path(UPLINK).asText());
VlanId vlan = VlanId.vlanId(Short.parseShort(node.path(VLAN).asText()));
JsonNode defaultVlanNode = node.path(DEFAULT_VLAN);
Optional<VlanId> defaultVlan;
if (defaultVlanNode.isMissingNode()) {
defaultVlan = Optional.empty();
} else {
defaultVlan = Optional.of(VlanId.vlanId(Short.parseShort(defaultVlanNode.asText())));
}
return new AccessDeviceData(subject(), uplink, vlan, defaultVlan);
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordconfig.access;
import org.onlab.packet.VlanId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Information about an access device.
*/
public class AccessDeviceData {
private static final String DEVICE_ID_MISSING = "Device ID cannot be null";
private static final String UPLINK_MISSING = "Uplink cannot be null";
private static final String VLAN_MISSING = "VLAN ID cannot be null";
private final DeviceId deviceId;
private final PortNumber uplink;
private final VlanId vlan;
private final Optional<VlanId> defaultVlan;
/**
* Class constructor.
*
* @param deviceId access device ID
* @param uplink uplink port number
* @param vlan device VLAN ID
* @param defaultVlan default device VLAN ID
*/
public AccessDeviceData(DeviceId deviceId, PortNumber uplink, VlanId vlan,
Optional<VlanId> defaultVlan) {
this.deviceId = checkNotNull(deviceId, DEVICE_ID_MISSING);
this.uplink = checkNotNull(uplink, UPLINK_MISSING);
this.vlan = checkNotNull(vlan, VLAN_MISSING);
this.defaultVlan = checkNotNull(defaultVlan);
}
/**
* Retrieves the access device ID.
*
* @return device ID
*/
public DeviceId deviceId() {
return deviceId;
}
/**
* Retrieves the uplink port number.
*
* @return port number
*/
public PortNumber uplink() {
return uplink;
}
/**
* Retrieves the VLAN ID assigned to the device.
*
* @return VLAN ID
*/
public VlanId vlan() {
return vlan;
}
/**
* Retrieves the default VLAN ID that will be used for this device.
*
* @return default VLAN ID
*/
public Optional<VlanId> defaultVlan() {
return defaultVlan;
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Meta Application for hosting common cord configuration classes.
*/
package org.onosproject.cordconfig.access;
\ No newline at end of file
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//lib:javax.ws.rs-api',
'//lib:jersey-client',
'//lib:jersey-common',
'//utils/rest:onlab-rest',
'//apps/olt:onos-apps-olt-api',
'//apps/cordconfig:onos-apps-cordconfig',
]
BUNDLES = [
'//apps/olt:onos-apps-olt-api',
'//apps/cordmcast:onos-apps-cordmcast',
]
osgi_jar_with_tests (
deps = COMPILE_DEPS,
)
onos_app (
title = 'CORD Multicast App',
category = 'Traffic Steering',
url = 'http://onosproject.org',
description = 'CORD Multicast application',
included_bundles = BUNDLES,
)
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-cord-mcast</artifactId>
<packaging>bundle</packaging>
<description>CORD Multicast application</description>
<properties>
<onos.app.name>org.onosproject.cordmcast</onos.app.name>
<onos.app.category>Traffic Steering</onos.app.category>
<onos.app.title>CORD Multicast App</onos.app.title>
<onos.app.url>http://opencord.org</onos.app.url>
<onos.app.requires>org.onosproject.cord-config</onos.app.requires>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cord-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-app-olt-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Application for provisioning multicast streams in the context of cord.
*/
package org.onosproject.cordmcast;
\ No newline at end of file
# app builds but is currently non functional. It needs transitive runtime
# dependencies.
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//lib:org.apache.karaf.shell.console',
'//lib:javax.ws.rs-api',
'//lib:jsch',
'//utils/rest:onlab-rest',
'//cli:onos-cli',
'//core/store/serializers:onos-core-serializers',
'//apps/dhcp/api:onos-apps-dhcp-api',
'//apps/xosclient:onos-apps-xosclient',
'//apps/cordconfig:onos-apps-cordconfig',
'//protocols/ovsdb/api:onos-protocols-ovsdb-api',
'//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc',
]
BUNDLES = [
'//apps/cordvtn:onos-apps-cordvtn',
]
EXCLUDED_BUNDLES = [
'//lib:jsch',
]
osgi_jar_with_tests (
deps = COMPILE_DEPS,
web_context = '/onos/cordvtn',
)
onos_app (
title = 'CORD VTN REST API',
category = 'Traffic Steering',
url = 'http://onosproject.org',
included_bundles = BUNDLES,
excluded_bundles = EXCLUDED_BUNDLES,
description = 'APIs for interacting with the CORD VTN application.',
required_apps = [ 'org.onosproject.cord-config', 'org.onosproject.xosclient', 'org.onosproject.dhcp', 'org.onosproject.ovsdb' ],
)
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<app name="org.onosproject.cordvtn" origin="ON.Lab" version="${project.version}"
category="Traffic Steering" url="http://onosproject.org" title="CORD Virtual Tenant Network"
featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
features="${project.artifactId}"
apps="org.onosproject.ovsdb-base,org.onosproject.dhcp,org.onosproject.xosclient,org.onosproject.cord-config">
<description>${project.description}</description>
<artifact>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</artifact>
</app>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ Copyright 2016-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
<feature name="${project.artifactId}" version="${project.version}" description="${project.description}">
<feature>onos-api</feature>
<bundle>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</bundle>
<bundle>wrap:mvn:com.jcraft/jsch/0.1.53$Bundle-SymbolicName=jsch&amp;Bundle-Version=0.1.53</bundle>
</feature>
</features>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-cordvtn</artifactId>
<packaging>bundle</packaging>
<description>Virtual tenant network service for CORD</description>
<properties>
<web.context>/onos/cordvtn</web.context>
<api.version>1.0.0</api.version>
<api.title>CORD VTN REST API</api.title>
<api.description>
APIs for interacting with the CORD VTN application.
</api.description>
<api.package>org.onosproject.cordvtn.rest</api.package>
</properties>
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-serializers</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-ovsdb-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-app-dhcp-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-app-xos-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cord-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.53</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>
<Include-Resource>
WEB-INF/classes/apidoc/swagger.json=target/swagger.json,
{maven-resources}
</Include-Resource>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
*,org.glassfish.jersey.servlet
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
/**
* Entity capable of handling a subject connected and disconnected situation.
*/
public interface ConnectionHandler<T> {
/**
* Processes the connected subject.
*
* @param subject subject
*/
void connected(T subject);
/**
* Processes the disconnected subject.
*
* @param subject subject.
*/
void disconnected(T subject);
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.Config;
import org.onosproject.xosclient.api.OpenStackAccess;
import org.onosproject.xosclient.api.XosAccess;
import org.slf4j.Logger;
import java.util.Map;
import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Configuration object for CordVtn service.
*/
public class CordVtnConfig extends Config<ApplicationId> {
protected final Logger log = getLogger(getClass());
public static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
public static final String PUBLIC_GATEWAYS = "publicGateways";
public static final String GATEWAY_IP = "gatewayIp";
public static final String GATEWAY_MAC = "gatewayMac";
public static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
public static final String MANAGEMENT_IP = "managementIpRange";
public static final String OVSDB_PORT = "ovsdbPort";
public static final String CORDVTN_NODES = "nodes";
public static final String HOSTNAME = "hostname";
public static final String HOST_MANAGEMENT_IP = "hostManagementIp";
public static final String DATA_PLANE_IP = "dataPlaneIp";
public static final String DATA_PLANE_INTF = "dataPlaneIntf";
public static final String BRIDGE_ID = "bridgeId";
public static final String SSH = "ssh";
public static final String SSH_PORT = "sshPort";
public static final String SSH_USER = "sshUser";
public static final String SSH_KEY_FILE = "sshKeyFile";
public static final String OPENSTACK = "openstack";
public static final String XOS = "xos";
public static final String ENDPOINT = "endpoint";
public static final String TENANT = "tenant";
public static final String USER = "user";
public static final String PASSWORD = "password";
/**
* Returns the set of nodes read from network config.
*
* @return set of CordVtnNodeConfig or empty set
*/
public Set<CordVtnNode> cordVtnNodes() {
Set<CordVtnNode> nodes = Sets.newHashSet();
JsonNode cordvtnNodes = object.get(CORDVTN_NODES);
if (cordvtnNodes == null) {
log.debug("No CORD VTN nodes found");
return nodes;
}
JsonNode sshNode = object.get(SSH);
if (sshNode == null) {
log.warn("SSH information not found");
return nodes;
}
for (JsonNode cordvtnNode : cordvtnNodes) {
try {
NetworkAddress hostMgmt = NetworkAddress.valueOf(getConfig(cordvtnNode, HOST_MANAGEMENT_IP));
NetworkAddress localMgmt = NetworkAddress.valueOf(getConfig(object, LOCAL_MANAGEMENT_IP));
if (hostMgmt.prefix().contains(localMgmt.prefix()) ||
localMgmt.prefix().contains(hostMgmt.prefix())) {
log.error("hostMamt and localMgmt cannot be overlapped, skip this node");
continue;
}
Ip4Address hostMgmtIp = hostMgmt.ip().getIp4Address();
SshAccessInfo sshInfo = new SshAccessInfo(
hostMgmtIp,
TpPort.tpPort(Integer.parseInt(getConfig(sshNode, SSH_PORT))),
getConfig(sshNode, SSH_USER), getConfig(sshNode, SSH_KEY_FILE));
String hostname = getConfig(cordvtnNode, HOSTNAME);
CordVtnNode newNode = new CordVtnNode(
hostname, hostMgmt, localMgmt,
NetworkAddress.valueOf(getConfig(cordvtnNode, DATA_PLANE_IP)),
TpPort.tpPort(Integer.parseInt(getConfig(object, OVSDB_PORT))),
sshInfo,
DeviceId.deviceId(getConfig(cordvtnNode, BRIDGE_ID)),
getConfig(cordvtnNode, DATA_PLANE_INTF),
CordVtnNodeState.noState());
nodes.add(newNode);
} catch (IllegalArgumentException | NullPointerException e) {
log.error("{}", e);
}
}
return nodes;
}
/**
* Returns value of a given path. If the path is missing, show log and return
* null.
*
* @param path path
* @return value or null
*/
private String getConfig(JsonNode jsonNode, String path) {
jsonNode = jsonNode.path(path);
if (jsonNode.isMissingNode()) {
log.error("{} is not configured", path);
return null;
} else {
return jsonNode.asText();
}
}
/**
* Returns private network gateway MAC address.
*
* @return mac address, or null
*/
public MacAddress privateGatewayMac() {
JsonNode jsonNode = object.get(PRIVATE_GATEWAY_MAC);
if (jsonNode == null) {
return null;
}
try {
return MacAddress.valueOf(jsonNode.asText());
} catch (IllegalArgumentException e) {
log.error("Wrong MAC address format {}", jsonNode.asText());
return null;
}
}
/**
* Returns public network gateway IP and MAC address pairs.
*
* @return map of ip and mac address
*/
public Map<IpAddress, MacAddress> publicGateways() {
JsonNode jsonNodes = object.get(PUBLIC_GATEWAYS);
if (jsonNodes == null) {
return Maps.newHashMap();
}
Map<IpAddress, MacAddress> publicGateways = Maps.newHashMap();
jsonNodes.forEach(jsonNode -> {
try {
publicGateways.put(
IpAddress.valueOf(jsonNode.path(GATEWAY_IP).asText()),
MacAddress.valueOf(jsonNode.path(GATEWAY_MAC).asText()));
} catch (IllegalArgumentException | NullPointerException e) {
log.error("Wrong address format {}", e.toString());
}
});
return publicGateways;
}
/**
* Returns management IP address range.
*
* @return management network ip prefix, or null
*/
public IpPrefix managementIpRange() {
JsonNode jsonNode = object.get(MANAGEMENT_IP);
if (jsonNode == null) {
return null;
}
try {
return IpPrefix.valueOf(jsonNode.asText());
} catch (IllegalArgumentException e) {
log.error("{}:{} wrong address format", MANAGEMENT_IP, jsonNode);
return null;
}
}
/**
* Returns XOS access information.
*
* @return XOS access, or null
*/
public XosAccess xosAccess() {
JsonNode jsonNode = object.get(XOS);
if (jsonNode == null) {
return null;
}
try {
return new XosAccess(getConfig(jsonNode, ENDPOINT),
getConfig(jsonNode, USER),
getConfig(jsonNode, PASSWORD));
} catch (NullPointerException e) {
log.error("Failed to get XOS access");
return null;
}
}
/**
* Returns OpenStack API access information.
*
* @return openstack access
*/
public OpenStackAccess openstackAccess() {
JsonNode jsonNode = object.get(OPENSTACK);
if (jsonNode == null) {
log.error("Failed to get OpenStack configurations");
return null;
}
try {
return new OpenStackAccess(
jsonNode.path(ENDPOINT).asText(),
jsonNode.path(TENANT).asText(),
jsonNode.path(USER).asText(),
jsonNode.path(PASSWORD).asText());
} catch (IllegalArgumentException | NullPointerException e) {
log.error("Failed to get OpenStack configurations");
return null;
}
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
import com.google.common.base.MoreObjects;
import org.onlab.packet.TpPort;
import org.onosproject.net.DeviceId;
import java.util.Comparator;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Representation of a compute infrastructure node for CORD VTN service.
*/
public final class CordVtnNode {
private final String hostname;
private final NetworkAddress hostMgmtIp;
private final NetworkAddress localMgmtIp;
private final NetworkAddress dpIp;
private final TpPort ovsdbPort;
private final SshAccessInfo sshInfo;
private final DeviceId bridgeId;
private final String dpIntf;
private final CordVtnNodeState state;
public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR =
(node1, node2) -> node1.hostname().compareTo(node2.hostname());
/**
* Creates a new node.
*
* @param hostname hostname
* @param hostMgmtIp host management network address
* @param localMgmtIp local management network address
* @param dpIp data plane network address
* @param ovsdbPort port number for OVSDB connection
* @param sshInfo SSH access information
* @param bridgeId integration bridge identifier
* @param dpIntf data plane interface name
* @param state cordvtn node state
*/
public CordVtnNode(String hostname, NetworkAddress hostMgmtIp, NetworkAddress localMgmtIp,
NetworkAddress dpIp, TpPort ovsdbPort, SshAccessInfo sshInfo,
DeviceId bridgeId, String dpIntf, CordVtnNodeState state) {
this.hostname = checkNotNull(hostname, "hostname cannot be null");
this.hostMgmtIp = checkNotNull(hostMgmtIp, "hostMgmtIp cannot be null");
this.localMgmtIp = checkNotNull(localMgmtIp, "localMgmtIp cannot be null");
this.dpIp = checkNotNull(dpIp, "dpIp cannot be null");
this.ovsdbPort = checkNotNull(ovsdbPort, "ovsdbPort cannot be null");
this.sshInfo = checkNotNull(sshInfo, "sshInfo cannot be null");
this.bridgeId = checkNotNull(bridgeId, "bridgeId cannot be null");
this.dpIntf = checkNotNull(dpIntf, "dpIntf cannot be null");
this.state = state;
}
/**
* Returns cordvtn node with new state.
*
* @param node cordvtn node
* @param state cordvtn node init state
* @return cordvtn node
*/
public static CordVtnNode getUpdatedNode(CordVtnNode node, CordVtnNodeState state) {
return new CordVtnNode(node.hostname,
node.hostMgmtIp, node.localMgmtIp, node.dpIp,
node.ovsdbPort,
node.sshInfo,
node.bridgeId,
node.dpIntf, state);
}
/**
* Returns the hostname.
*
* @return hostname
*/
public String hostname() {
return this.hostname;
}
/**
* Returns the host management network address.
*
* @return network address
*/
public NetworkAddress hostMgmtIp() {
return this.hostMgmtIp;
}
/**
* Returns the local management network address.
*
* @return network address
*/
public NetworkAddress localMgmtIp() {
return this.localMgmtIp;
}
/**
* Returns the data plane network address.
*
* @return network address
*/
public NetworkAddress dpIp() {
return this.dpIp;
}
/**
* Returns the port number used for OVSDB connection.
*
* @return port number
*/
public TpPort ovsdbPort() {
return this.ovsdbPort;
}
/**
* Returns the SSH access information.
*
* @return ssh access information
*/
public SshAccessInfo sshInfo() {
return this.sshInfo;
}
/**
* Returns the identifier of the integration bridge.
*
* @return device id
*/
public DeviceId intBrId() {
return this.bridgeId;
}
/**
* Returns the identifier of the OVSDB device.
*
* @return device id
*/
public DeviceId ovsdbId() {
return DeviceId.deviceId("ovsdb:" + this.hostMgmtIp.ip().toString());
}
/**
* Returns data plane interface name.
*
* @return data plane interface name
*/
public String dpIntf() {
return this.dpIntf;
}
/**
* Returns the state of the node.
*
* @return state
*/
public CordVtnNodeState state() {
return this.state;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof CordVtnNode) {
CordVtnNode that = (CordVtnNode) obj;
if (Objects.equals(hostname, that.hostname) &&
Objects.equals(hostMgmtIp, that.hostMgmtIp) &&
Objects.equals(localMgmtIp, that.localMgmtIp) &&
Objects.equals(dpIp, that.dpIp) &&
Objects.equals(ovsdbPort, that.ovsdbPort) &&
Objects.equals(sshInfo, that.sshInfo) &&
Objects.equals(bridgeId, that.bridgeId) &&
Objects.equals(dpIntf, that.dpIntf)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(hostname, hostMgmtIp, localMgmtIp, dpIp,
ovsdbPort, sshInfo, bridgeId, dpIntf);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("hostname", hostname)
.add("hostMgmtIp", hostMgmtIp)
.add("localMgmtIp", localMgmtIp)
.add("dpIp", dpIp)
.add("port", ovsdbPort)
.add("sshInfo", sshInfo)
.add("bridgeId", bridgeId)
.add("dpIntf", dpIntf)
.add("state", state)
.toString();
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
/**
* Entity that defines possible init state of the cordvtn node.
*/
public interface CordVtnNodeState {
/**
* Returns null for no state.
*
* @return null
*/
static CordVtnNodeState noState() {
return null;
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
import org.onosproject.xosclient.api.VtnServiceId;
/**
* Service for provisioning overlay virtual networks on compute nodes.
*/
public interface CordVtnService {
String CORDVTN_APP_ID = "org.onosproject.cordvtn";
/**
* Creates dependencies for a given tenant service.
*
* @param tServiceId id of the service which has a dependency
* @param pServiceId id of the service which provide dependency
* @param isBidirectional true to enable bidirectional connectivity between two services
*/
void createServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
boolean isBidirectional);
/**
* Removes all dependencies from a given tenant service.
*
* @param tServiceId id of the service which has a dependency
* @param pServiceId id of the service which provide dependency
*/
void removeServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId);
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
import com.google.common.base.Strings;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.PortNumber;
import org.onosproject.xosclient.api.VtnPortId;
import org.onosproject.xosclient.api.VtnService;
import org.onosproject.xosclient.api.VtnServiceId;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Provides methods to help to handle network service instance.
*/
public final class Instance {
public static final String SERVICE_ID = "serviceId";
public static final String SERVICE_TYPE = "serviceType";
public static final String PORT_ID = "vtnPortId";
public static final String CREATE_TIME = "createTime";
public static final String NESTED_INSTANCE = "nestedInstance";
public static final String TRUE = "true";
private final Host host;
/**
* Default constructor.
*
* @param instance host object of this instance
*/
private Instance(Host instance) {
this.host = instance;
}
/**
* Returns host object of this instance.
*
* @return host
*/
public Host host() {
return this.host;
}
/**
* Returns new instance.
*
* @param host host object of this instance
* @return instance
*/
public static Instance of(Host host) {
checkNotNull(host);
checkArgument(!Strings.isNullOrEmpty(host.annotations().value(SERVICE_ID)));
checkArgument(!Strings.isNullOrEmpty(host.annotations().value(SERVICE_TYPE)));
checkArgument(!Strings.isNullOrEmpty(host.annotations().value(PORT_ID)));
checkArgument(!Strings.isNullOrEmpty(host.annotations().value(CREATE_TIME)));
return new Instance(host);
}
/**
* Returns service ID of a given host.
*
* @return vtn service id
*/
public VtnServiceId serviceId() {
String serviceId = host.annotations().value(SERVICE_ID);
return VtnServiceId.of(serviceId);
}
/**
* Returns service type of a given host.
*
* @return vtn service type
*/
public VtnService.ServiceType serviceType() {
String serviceType = host.annotations().value(SERVICE_TYPE);
return VtnService.ServiceType.valueOf(serviceType);
}
/**
* Returns port ID of a given host.
*
* @return vtn port id
*/
public VtnPortId portId() {
String portId = host.annotations().value(PORT_ID);
return VtnPortId.of(portId);
}
/**
* Returns if the instance is nested container or not.
*
* @return true if it's nested container; false otherwise
*/
public boolean isNestedInstance() {
return host.annotations().value(NESTED_INSTANCE) != null;
}
/**
* Returns MAC address of this instance.
*
* @return mac address
*/
public MacAddress mac() {
return host.mac();
}
/**
* Returns IP address of this instance.
*
* @return ip address
*/
public Ip4Address ipAddress() {
// assume all instance has only one IP address, and only IP4 is supported now
return host.ipAddresses().stream().findFirst().get().getIp4Address();
}
/**
* Returns device ID of this host.
*
* @return device id
*/
public DeviceId deviceId() {
return host.location().deviceId();
}
/**
* Returns the port number where this host is.
*
* @return port number
*/
public PortNumber portNumber() {
return host.location().port();
}
/**
* Returns annotation value with a given key.
*
* @param annotationKey annotation key
* @return annotation value
*/
public String getAnnotation(String annotationKey) {
return host.annotations().value(annotationKey);
}
@Override
public String toString() {
return host.toString();
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
/**
* Handles service instance detection and removal.
*/
public interface InstanceHandler {
/**
* Handles newly detected instance.
*
* @param instance instance
*/
void instanceDetected(Instance instance);
/**
* Handles removed instance.
*
* @param instance instance
*/
void instanceRemoved(Instance instance);
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
import com.google.common.base.MoreObjects;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Representation of a network address, which consists of IP address and prefix.
*/
public final class NetworkAddress {
private final IpAddress ip;
private final IpPrefix prefix;
/**
* Constructor for a given IP address and prefix.
*
* @param ip ip address
* @param prefix ip prefix
*/
public NetworkAddress(IpAddress ip, IpPrefix prefix) {
this.ip = ip;
this.prefix = prefix;
}
/**
* Converts a CIDR notation string into a network address.
*
* @param cidr cidr
* @return network address
* @throws IllegalArgumentException if the cidr is not valid
*/
public static NetworkAddress valueOf(String cidr) {
checkArgument(cidr.contains("/"));
IpAddress ipAddress = IpAddress.valueOf(cidr.split("/")[0]);
IpPrefix ipPrefix = IpPrefix.valueOf(cidr);
return new NetworkAddress(ipAddress, ipPrefix);
}
/**
* Returns the IP address value of the network address.
*
* @return ip address
*/
public IpAddress ip() {
return this.ip;
}
/**
* Returns the IP prefix value of the network address.
*
* @return ip prefix
*/
public IpPrefix prefix() {
return this.prefix;
}
/**
* Converts a network address to a CIDR notation.
*
* @return cidr notation string
*/
public String cidr() {
return ip.toString() + "/" + prefix.prefixLength();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof NetworkAddress) {
NetworkAddress that = (NetworkAddress) obj;
if (Objects.equals(ip, that.ip) && Objects.equals(prefix, that.prefix)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(ip, prefix);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("IpAddress", ip)
.add("IpPrefix", prefix)
.toString();
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.api;
import com.google.common.base.MoreObjects;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.TpPort;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Representation of SSH access information.
*/
public final class SshAccessInfo {
private final Ip4Address remoteIp;
private final TpPort port;
private final String user;
private final String privateKey;
/**
* Creates a new SSH access information.
*
* @param remoteIp ssh remote ip address
* @param port ssh port number
* @param user user name
* @param privateKey path of ssh private key
*/
public SshAccessInfo(Ip4Address remoteIp, TpPort port, String user, String privateKey) {
this.remoteIp = checkNotNull(remoteIp);
this.port = checkNotNull(port);
this.user = checkNotNull(user);
this.privateKey = checkNotNull(privateKey);
}
/**
* Returns the remote IP address.
*
* @return ip address
*/
public Ip4Address remoteIp() {
return this.remoteIp;
}
/**
* Returns the port number.
*
* @return ssh port
*/
public TpPort port() {
return this.port;
}
/**
* Returns the user name.
*
* @return user name
*/
public String user() {
return this.user;
}
/**
* Returns the private key path.
*
* @return privateKey
*/
public String privateKey() {
return privateKey;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof SshAccessInfo) {
SshAccessInfo that = (SshAccessInfo) obj;
if (Objects.equals(remoteIp, that.remoteIp) &&
Objects.equals(port, that.port) &&
Objects.equals(user, that.user) &&
Objects.equals(privateKey, that.privateKey)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(remoteIp, port, user, privateKey);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("remoteIp", remoteIp)
.add("port", port)
.add("user", user)
.add("privateKey", privateKey)
.toString();
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* API for CORD VTN application.
*/
package org.onosproject.cordvtn.api;
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.cli;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cordvtn.impl.CordVtnPipeline;
/**
* Deletes nodes from the service.
*/
@Command(scope = "onos", name = "cordvtn-flush-rules",
description = "Flush flow rules installed by CORD VTN")
public class CordVtnFlushRules extends AbstractShellCommand {
@Override
protected void execute() {
CordVtnPipeline pipeline = AbstractShellCommand.get(CordVtnPipeline.class);
pipeline.flushRules();
print("Successfully flushed");
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cordvtn.api.CordVtnNode;
import org.onosproject.cordvtn.impl.CordVtnNodeManager;
import org.onosproject.net.Device;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
/**
* Checks detailed node init state.
*/
@Command(scope = "onos", name = "cordvtn-node-check",
description = "Shows detailed node init state")
public class CordVtnNodeCheckCommand extends AbstractShellCommand {
@Argument(index = 0, name = "hostname", description = "Hostname",
required = true, multiValued = false)
private String hostname = null;
@Override
protected void execute() {
CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
DeviceService deviceService = AbstractShellCommand.get(DeviceService.class);
CordVtnNode node = nodeManager.getNodes()
.stream()
.filter(n -> n.hostname().equals(hostname))
.findFirst()
.orElse(null);
if (node == null) {
print("Cannot find %s from registered nodes", hostname);
return;
}
print(nodeManager.checkNodeInitState(node));
print("%n[DEBUG]");
Device device = deviceService.getDevice(node.intBrId());
String driver = get(DriverService.class).getDriver(device.id()).name();
print("%s available=%s driver=%s %s",
device.id(),
deviceService.isAvailable(device.id()),
driver,
device.annotations());
deviceService.getPorts(node.intBrId()).forEach(port -> {
Object portIsEnabled = port.isEnabled() ? "enabled" : "disabled";
print("port=%s state=%s %s",
port.number(),
portIsEnabled,
port.annotations());
});
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cordvtn.impl.CordVtnNodeManager;
import org.onosproject.cordvtn.api.CordVtnNode;
import java.util.NoSuchElementException;
/**
* Deletes nodes from the service.
*/
@Command(scope = "onos", name = "cordvtn-node-delete",
description = "Deletes nodes from CORD VTN service")
public class CordVtnNodeDeleteCommand extends AbstractShellCommand {
@Argument(index = 0, name = "hostnames", description = "Hostname(s)",
required = true, multiValued = true)
private String[] hostnames = null;
@Override
protected void execute() {
CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
for (String hostname : hostnames) {
CordVtnNode node;
try {
node = nodeManager.getNodes()
.stream()
.filter(n -> n.hostname().equals(hostname))
.findFirst().get();
} catch (NoSuchElementException e) {
print("Unable to find %s", hostname);
continue;
}
nodeManager.deleteNode(node);
}
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cordvtn.impl.CordVtnNodeManager;
import org.onosproject.cordvtn.api.CordVtnNode;
import java.util.NoSuchElementException;
/**
* Initializes nodes for CordVtn service.
*/
@Command(scope = "onos", name = "cordvtn-node-init",
description = "Initializes nodes for CORD VTN service")
public class CordVtnNodeInitCommand extends AbstractShellCommand {
@Argument(index = 0, name = "hostnames", description = "Hostname(s)",
required = true, multiValued = true)
private String[] hostnames = null;
@Override
protected void execute() {
CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
for (String hostname : hostnames) {
CordVtnNode node;
try {
node = nodeManager.getNodes()
.stream()
.filter(n -> n.hostname().equals(hostname))
.findFirst().get();
} catch (NoSuchElementException e) {
print("Unable to find %s", hostname);
continue;
}
nodeManager.addOrUpdateNode(node);
}
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.cli;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cordvtn.impl.CordVtnNodeManager;
import org.onosproject.cordvtn.api.CordVtnNode;
import java.util.Collections;
import java.util.List;
/**
* Lists all nodes registered to the service.
*/
@Command(scope = "onos", name = "cordvtn-nodes",
description = "Lists all nodes registered in CORD VTN service")
public class CordVtnNodeListCommand extends AbstractShellCommand {
private static final String COMPLETE = "COMPLETE";
private static final String INCOMPLETE = "INCOMPLETE";
@Override
protected void execute() {
CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
List<CordVtnNode> nodes = nodeManager.getNodes();
Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR);
if (outputJson()) {
print("%s", json(nodeManager, nodes));
} else {
for (CordVtnNode node : nodes) {
print("hostname=%s, hostMgmtIp=%s, dpIp=%s, br-int=%s, dpIntf=%s, init=%s",
node.hostname(),
node.hostMgmtIp().cidr(),
node.dpIp().cidr(),
node.intBrId().toString(),
node.dpIntf(),
getState(nodeManager, node));
}
print("Total %s nodes", nodeManager.getNodeCount());
}
}
private JsonNode json(CordVtnNodeManager nodeManager, List<CordVtnNode> nodes) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (CordVtnNode node : nodes) {
result.add(mapper.createObjectNode()
.put("hostname", node.hostname())
.put("hostManagementIp", node.hostMgmtIp().cidr())
.put("dataPlaneIp", node.dpIp().cidr())
.put("bridgeId", node.intBrId().toString())
.put("dataPlaneInterface", node.dpIntf())
.put("init", getState(nodeManager, node)));
}
return result;
}
private String getState(CordVtnNodeManager nodeManager, CordVtnNode node) {
return nodeManager.isNodeInitComplete(node) ? COMPLETE : INCOMPLETE;
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Console commands to manage OVSDB nodes for cordvtn.
*/
package org.onosproject.cordvtn.cli;
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.impl;
import com.google.common.collect.Maps;
import org.onlab.packet.ARP;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.cordvtn.api.Instance;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.Host;
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.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Handles ARP requests for virtual network service IPs.
*/
public class CordVtnArpProxy {
protected final Logger log = getLogger(getClass());
private final ApplicationId appId;
private final PacketService packetService;
private final HostService hostService;
private final Map<Ip4Address, MacAddress> gateways = Maps.newConcurrentMap();
/**
* Default constructor.
*
* @param appId application id
* @param packetService packet service
* @param hostService host service reference
*/
public CordVtnArpProxy(ApplicationId appId, PacketService packetService, HostService hostService) {
this.appId = appId;
this.packetService = packetService;
this.hostService = hostService;
}
/**
* Requests ARP packet.
*/
public void requestPacket() {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
.build();
packetService.requestPackets(selector,
PacketPriority.CONTROL,
appId,
Optional.empty());
}
/**
* Cancels ARP packet.
*/
public void cancelPacket() {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
.build();
packetService.cancelPackets(selector,
PacketPriority.CONTROL,
appId,
Optional.empty());
}
/**
* Adds a given gateway IP and MAC address to this ARP proxy.
*
* @param gatewayIp gateway ip address
* @param gatewayMac gateway mac address
*/
public void addGateway(IpAddress gatewayIp, MacAddress gatewayMac) {
checkNotNull(gatewayIp);
checkNotNull(gatewayMac);
gateways.put(gatewayIp.getIp4Address(), gatewayMac);
}
/**
* Removes a given service IP address from this ARP proxy.
*
* @param gatewayIp gateway ip address
*/
public void removeGateway(IpAddress gatewayIp) {
checkNotNull(gatewayIp);
gateways.remove(gatewayIp.getIp4Address());
}
/**
* Emits ARP reply with fake MAC address for a given ARP request.
* It only handles requests for the registered service IPs, and the other
* requests can be handled by other ARP handlers like openstackSwitching or
* proxyArp, for example.
*
* @param context packet context
* @param ethPacket ethernet packet
*/
public void processArpPacket(PacketContext context, Ethernet ethPacket) {
ARP arpPacket = (ARP) ethPacket.getPayload();
if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
return;
}
Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
MacAddress gatewayMac = gateways.get(targetIp);
MacAddress replyMac = gatewayMac != null ? gatewayMac : getMacFromHostService(targetIp);
if (replyMac.equals(MacAddress.NONE)) {
log.debug("Failed to find MAC for {}", targetIp.toString());
context.block();
return;
}
log.trace("Send ARP reply for {} with {}", targetIp.toString(), replyMac.toString());
Ethernet ethReply = ARP.buildArpReply(
targetIp,
replyMac,
ethPacket);
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(context.inPacket().receivedFrom().port())
.build();
packetService.emit(new DefaultOutboundPacket(
context.inPacket().receivedFrom().deviceId(),
treatment,
ByteBuffer.wrap(ethReply.serialize())));
context.block();
}
/**
* Emits gratuitous ARP when a gateway mac address has been changed.
*
* @param gatewayIp gateway ip address to update MAC
* @param instances set of instances to send gratuitous ARP packet
*/
public void sendGratuitousArpForGateway(IpAddress gatewayIp, Set<Instance> instances) {
MacAddress gatewayMac = gateways.get(gatewayIp.getIp4Address());
if (gatewayMac == null) {
log.debug("Gateway {} is not registered to ARP proxy", gatewayIp.toString());
return;
}
Ethernet ethArp = buildGratuitousArp(gatewayIp.getIp4Address(), gatewayMac);
instances.stream().forEach(instance -> {
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(instance.portNumber())
.build();
packetService.emit(new DefaultOutboundPacket(
instance.deviceId(),
treatment,
ByteBuffer.wrap(ethArp.serialize())));
});
}
/**
* Builds gratuitous ARP packet with a given IP and MAC address.
*
* @param ip ip address for TPA and SPA
* @param mac new mac address
* @return ethernet packet
*/
private Ethernet buildGratuitousArp(IpAddress ip, MacAddress mac) {
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_ARP);
eth.setSourceMACAddress(mac);
eth.setDestinationMACAddress(MacAddress.BROADCAST);
ARP arp = new ARP();
arp.setOpCode(ARP.OP_REQUEST);
arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
arp.setProtocolType(ARP.PROTO_TYPE_IP);
arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
arp.setSenderHardwareAddress(mac.toBytes());
arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
arp.setSenderProtocolAddress(ip.getIp4Address().toOctets());
arp.setTargetProtocolAddress(ip.getIp4Address().toOctets());
eth.setPayload(arp);
return eth;
}
/**
* Returns MAC address of a host with a given target IP address by asking to
* host service. It does not support overlapping IP.
*
* @param targetIp target ip
* @return mac address, or NONE mac address if it fails to find the mac
*/
private MacAddress getMacFromHostService(IpAddress targetIp) {
checkNotNull(targetIp);
Host host = hostService.getHostsByIp(targetIp)
.stream()
.findFirst()
.orElse(null);
if (host != null) {
log.trace("Found MAC from host service for {}", targetIp.toString());
return host.mac();
} else {
return MacAddress.NONE;
}
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.impl;
import com.google.common.collect.Sets;
import com.google.common.io.CharStreams;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.onlab.packet.IpAddress;
import org.onosproject.cordvtn.api.NetworkAddress;
import org.onosproject.cordvtn.api.SshAccessInfo;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.slf4j.LoggerFactory.getLogger;
/**
* {@code RemoteIpCommandUtil} provides methods to help execute Linux IP commands to a remote server.
* It opens individual exec channels for each command. User can create a session with {@code connect}
* method and then execute a series commands. After done with all commands, the session must be closed
* explicitly by calling {@code disconnect}.
*/
public final class RemoteIpCommandUtil {
protected static final Logger log = getLogger(RemoteIpCommandUtil.class);
private static final String STRICT_HOST_CHECKING = "StrictHostKeyChecking";
private static final String DEFAULT_STRICT_HOST_CHECKING = "no";
private static final int DEFAULT_SESSION_TIMEOUT = 60000; // milliseconds
private static final String IP_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
private static final String IP_ADDR_SHOW = "sudo ip addr show %s";
private static final String IP_ADDR_FLUSH = "sudo ip addr flush %s";
private static final String IP_ADDR_ADD = "sudo ip addr add %s dev %s";
private static final String IP_ADDR_DELETE = "sudo ip addr delete %s dev %s";
private static final String IP_LINK_SHOW = "sudo ip link show %s";
private static final String IP_LINK_UP = "sudo ip link set %s up";
/**
* Default constructor.
*/
private RemoteIpCommandUtil() {
}
/**
* Adds a given IP address to a given device.
*
* @param session ssh connection
* @param ip network address
* @param device device name to assign the ip address
* @return true if the command succeeds, or false
*/
public static boolean addIp(Session session, NetworkAddress ip, String device) {
if (session == null || !session.isConnected()) {
return false;
}
executeCommand(session, String.format(IP_ADDR_ADD, ip.cidr(), device));
Set<IpAddress> result = getCurrentIps(session, device);
return result.contains(ip.ip());
}
/**
* Removes the IP address from a given device.
*
* @param session ssh connection
* @param ip ip address
* @param device device name
* @return true if the command succeeds, or false
*/
public static boolean deleteIp(Session session, IpAddress ip, String device) {
if (session == null || !session.isConnected()) {
return false;
}
executeCommand(session, String.format(IP_ADDR_DELETE, ip, device));
Set<IpAddress> result = getCurrentIps(session, device);
return !result.contains(ip);
}
/**
* Removes all IP address on a given device.
*
* @param session ssh connection
* @param device device name
* @return true if the command succeeds, or false
*/
public static boolean flushIp(Session session, String device) {
if (session == null || !session.isConnected()) {
return false;
}
executeCommand(session, String.format(IP_ADDR_FLUSH, device));
return getCurrentIps(session, device).isEmpty();
}
/**
* Returns a set of IP address that a given device has.
*
* @param session ssh connection
* @param device device name
* @return set of IP prefix or empty set
*/
public static Set<IpAddress> getCurrentIps(Session session, String device) {
if (session == null || !session.isConnected()) {
return Sets.newHashSet();
}
String output = executeCommand(session, String.format(IP_ADDR_SHOW, device));
Set<IpAddress> result = Pattern.compile(" |/")
.splitAsStream(output)
.filter(s -> s.matches(IP_PATTERN))
.map(IpAddress::valueOf)
.collect(Collectors.toSet());
return result;
}
/**
* Sets link state up for a given device.
*
* @param session ssh connection
* @param device device name
* @return true if the command succeeds, or false
*/
public static boolean setInterfaceUp(Session session, String device) {
if (session == null || !session.isConnected()) {
return false;
}
executeCommand(session, String.format(IP_LINK_UP, device));
return isInterfaceUp(session, device);
}
/**
* Checks if a given interface is up or not.
*
* @param session ssh connection
* @param device device name
* @return true if the interface is up, or false
*/
public static boolean isInterfaceUp(Session session, String device) {
if (session == null || !session.isConnected()) {
return false;
}
String output = executeCommand(session, String.format(IP_LINK_SHOW, device));
return output != null && output.contains("UP");
}
/**
* Creates a new session with a given access information.
*
* @param sshInfo information to ssh to the remove server
* @return ssh session, or null
*/
public static Session connect(SshAccessInfo sshInfo) {
try {
JSch jsch = new JSch();
jsch.addIdentity(sshInfo.privateKey());
Session session = jsch.getSession(sshInfo.user(),
sshInfo.remoteIp().toString(),
sshInfo.port().toInt());
session.setConfig(STRICT_HOST_CHECKING, DEFAULT_STRICT_HOST_CHECKING);
session.connect(DEFAULT_SESSION_TIMEOUT);
return session;
} catch (JSchException e) {
log.debug("Failed to connect to {} due to {}", sshInfo.toString(), e.toString());
return null;
}
}
/**
* Closes a connection.
*
* @param session session
*/
public static void disconnect(Session session) {
if (session.isConnected()) {
session.disconnect();
}
}
/**
* Executes a given command. It opens exec channel for the command and closes
* the channel when it's done.
*
* @param session ssh connection to a remote server
* @param command command to execute
* @return command output string if the command succeeds, or null
*/
private static String executeCommand(Session session, String command) {
if (session == null || !session.isConnected()) {
return null;
}
log.trace("Execute command {} to {}", command, session.getHost());
try {
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
InputStream output = channel.getInputStream();
channel.connect();
String result = CharStreams.toString(new InputStreamReader(output));
channel.disconnect();
return result;
} catch (JSchException | IOException e) {
log.debug("Failed to execute command {} due to {}", command, e.toString());
return null;
}
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Implementation for CORD VTN application.
*/
package org.onosproject.cordvtn.impl;
\ No newline at end of file
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.impl.service;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.onosproject.cordvtn.api.Instance;
import org.onosproject.cordvtn.api.InstanceHandler;
import org.onosproject.cordvtn.impl.CordVtnInstanceHandler;
import org.onosproject.xosclient.api.VtnService;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
/**
* Provides network connectivity for dummy service instances.
*/
@Component(immediate = true)
public class DummyInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
@Activate
protected void activate() {
serviceType = VtnService.ServiceType.DUMMY;
eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-dummy", "event-handler"));
super.activate();
}
@Deactivate
protected void deactivate() {
super.deactivate();
}
@Override
public void instanceDetected(Instance instance) {
super.instanceDetected(instance);
}
@Override
public void instanceRemoved(Instance instance) {
super.instanceRemoved(instance);
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.impl.service;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpPrefix;
import org.onosproject.cordconfig.access.AccessAgentConfig;
import org.onosproject.cordconfig.access.AccessAgentData;
import org.onosproject.cordvtn.api.CordVtnConfig;
import org.onosproject.cordvtn.api.Instance;
import org.onosproject.cordvtn.api.InstanceHandler;
import org.onosproject.cordvtn.impl.CordVtnInstanceHandler;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.xosclient.api.VtnService;
import java.util.Map;
import java.util.Set;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.cordvtn.impl.CordVtnPipeline.PRIORITY_MANAGEMENT;
import static org.onosproject.cordvtn.impl.CordVtnPipeline.TABLE_ACCESS_TYPE;
/**
* Provides network connectivity for OLT agent instances.
*/
@Component(immediate = true)
public class OltAgentInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
private static final Class<AccessAgentConfig> CONFIG_CLASS = AccessAgentConfig.class;
private ConfigFactory<DeviceId, AccessAgentConfig> configFactory =
new ConfigFactory<DeviceId, AccessAgentConfig>(
SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessAgent") {
@Override
public AccessAgentConfig createConfig() {
return new AccessAgentConfig();
}
};
private Map<DeviceId, AccessAgentData> oltAgentData = Maps.newConcurrentMap();
private IpPrefix mgmtIpRange = null;
@Activate
protected void activate() {
eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-olt", "event-handler"));
serviceType = VtnService.ServiceType.OLT_AGENT;
configRegistry.registerConfigFactory(configFactory);
configListener = new InternalConfigListener();
super.activate();
}
@Deactivate
protected void deactivate() {
super.deactivate();
}
@Override
public void instanceDetected(Instance instance) {
log.info("OLT agent instance detected {}", instance);
managementAccessRule(instance.deviceId(), true);
// TODO implement
}
@Override
public void instanceRemoved(Instance instance) {
log.info("OLT agent instance removed {}", instance);
if (getInstances(instance.serviceId()).isEmpty()) {
nodeManager.completeNodes().stream().forEach(node ->
managementAccessRule(node.intBrId(), false));
}
// TODO implement
}
private void managementAccessRule(DeviceId deviceId, boolean install) {
// TODO remove this rule after long term management network is done
if (mgmtIpRange != null) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV4)
.matchIPDst(mgmtIpRange)
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(PortNumber.LOCAL)
.build();
FlowRule flowRule = DefaultFlowRule.builder()
.fromApp(appId)
.withSelector(selector)
.withTreatment(treatment)
.withPriority(PRIORITY_MANAGEMENT)
.forDevice(deviceId)
.forTable(TABLE_ACCESS_TYPE)
.makePermanent()
.build();
pipeline.processFlowRule(install, flowRule);
}
}
private void readAccessAgentConfig() {
Set<DeviceId> deviceSubjects = configRegistry.getSubjects(DeviceId.class, CONFIG_CLASS);
deviceSubjects.stream().forEach(subject -> {
AccessAgentConfig config = configRegistry.getConfig(subject, CONFIG_CLASS);
if (config != null) {
oltAgentData.put(subject, config.getAgent());
}
});
}
@Override
protected void readConfiguration() {
CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
if (config == null) {
log.debug("No configuration found");
return;
}
osAccess = config.openstackAccess();
xosAccess = config.xosAccess();
mgmtIpRange = config.managementIpRange();
}
public class InternalConfigListener implements NetworkConfigListener {
@Override
public void event(NetworkConfigEvent event) {
switch (event.type()) {
case CONFIG_UPDATED:
case CONFIG_ADDED:
if (event.configClass().equals(CordVtnConfig.class)) {
readConfiguration();
} else if (event.configClass().equals(CONFIG_CLASS)) {
readAccessAgentConfig();
}
break;
default:
break;
}
}
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Implementation of instance handlers for various network services.
*/
package org.onosproject.cordvtn.impl.service;
\ No newline at end of file
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.rest;
import org.onlab.rest.AbstractWebApplication;
import java.util.Set;
/**
* CORD VTN Web application.
*/
public class CordVtnWebApplication extends AbstractWebApplication {
@Override
public Set<Class<?>> getClasses() {
return getClasses(ServiceDependencyWebResource.class,
NeutronMl2NetworksWebResource.class,
NeutronMl2SubnetsWebResource.class,
NeutronMl2PortsWebResource.class);
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.rest;
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
/**
* Dummy Neutron ML2 mechanism driver.
* It just returns OK for networks resource requests.
*/
@Path("networks")
public class NeutronMl2NetworksWebResource extends AbstractWebResource {
protected final Logger log = LoggerFactory.getLogger(getClass());
private static final String NETWORKS_MESSAGE = "Received networks %s";
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createNetwork(InputStream input) {
log.trace(String.format(NETWORKS_MESSAGE, "create"));
return Response.status(Response.Status.OK).build();
}
@PUT
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updateNetwork(@PathParam("id") String id, InputStream input) {
log.trace(String.format(NETWORKS_MESSAGE, "update"));
return Response.status(Response.Status.OK).build();
}
@DELETE
@Path("{id}")
public Response deleteNetwork(@PathParam("id") String id) {
log.trace(String.format(NETWORKS_MESSAGE, "delete"));
return Response.noContent().build();
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.rest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import org.onlab.osgi.DefaultServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.cordvtn.impl.service.VsgInstanceHandler;
import org.onosproject.net.HostId;
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.util.Map;
/**
* Dummy Neutron ML2 mechanism driver.
* It just returns OK for ports resource requests except for the port update.
*/
@Path("ports")
public class NeutronMl2PortsWebResource extends AbstractWebResource {
protected final Logger log = LoggerFactory.getLogger(getClass());
private static final String PORTS_MESSAGE = "Received ports %s";
private static final String PORT = "port";
private static final String DEVICE_ID = "device_id";
private static final String NAME = "name";
private static final String MAC_ADDRESS = "mac_address";
private static final String ADDRESS_PAIRS = "allowed_address_pairs";
private static final String IP_ADDERSS = "ip_address";
private static final String STAG_PREFIX = "stag-";
private static final int STAG_BEGIN_INDEX = 5;
private final VsgInstanceHandler service = DefaultServiceDirectory.getService(VsgInstanceHandler.class);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createPorts(InputStream input) {
log.trace(String.format(PORTS_MESSAGE, "create"));
return Response.status(Response.Status.OK).build();
}
@PUT
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updatePorts(@PathParam("id") String id, InputStream input) {
log.debug(String.format(PORTS_MESSAGE, "update"));
// TODO get vSG updates from XOS to CORD VTN service directly
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(input).get(PORT);
log.trace("{}", jsonNode.toString());
String deviceId = jsonNode.path(DEVICE_ID).asText();
String name = jsonNode.path(NAME).asText();
if (deviceId.isEmpty() || name.isEmpty() || !name.startsWith(STAG_PREFIX)) {
// ignore all updates other than allowed address pairs
return Response.status(Response.Status.OK).build();
}
// this is allowed address pairs updates
MacAddress mac = MacAddress.valueOf(jsonNode.path(MAC_ADDRESS).asText());
Map<IpAddress, MacAddress> vsgInstances = Maps.newHashMap();
jsonNode.path(ADDRESS_PAIRS).forEach(addrPair -> {
IpAddress pairIp = IpAddress.valueOf(addrPair.path(IP_ADDERSS).asText());
MacAddress pairMac = MacAddress.valueOf(addrPair.path(MAC_ADDRESS).asText());
vsgInstances.put(pairIp, pairMac);
});
service.updateVsgInstances(HostId.hostId(mac),
name.substring(STAG_BEGIN_INDEX),
vsgInstances);
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Response.Status.OK).build();
}
@Path("{id}")
@DELETE
public Response deletePorts(@PathParam("id") String id) {
log.trace(String.format(PORTS_MESSAGE, "delete"));
return Response.noContent().build();
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.rest;
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
/**
* Dummy Neutron ML2 mechanism driver.
* It just returns OK for subnets resource requests.
*/
@Path("subnets")
public class NeutronMl2SubnetsWebResource extends AbstractWebResource {
protected final Logger log = LoggerFactory.getLogger(getClass());
private static final String SUBNETS_MESSAGE = "Received subnets %s";
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createSubnet(InputStream input) {
log.trace(String.format(SUBNETS_MESSAGE, "create"));
return Response.status(Response.Status.OK).build();
}
@PUT
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response updateSubnet(@PathParam("id") String id, InputStream input) {
log.trace(String.format(SUBNETS_MESSAGE, "update"));
return Response.status(Response.Status.OK).build();
}
@DELETE
@Path("{id}")
public Response deleteSubnet(@PathParam("id") String id) {
log.trace(String.format(SUBNETS_MESSAGE, "delete"));
return Response.noContent().build();
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cordvtn.rest;
import org.onosproject.cordvtn.api.CordVtnService;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.xosclient.api.VtnServiceId;
import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* Manages service dependency.
*/
@Path("service-dependency")
public class ServiceDependencyWebResource extends AbstractWebResource {
private final CordVtnService service = get(CordVtnService.class);
private static final String BIDIRECTION = "b";
/**
* Creates service dependencies with unidirectional access between the services.
*
* @param tServiceId tenant service id
* @param pServiceId provider service id
* @return 200 OK
*/
@POST
@Path("{tenantServiceId}/{providerServiceId}")
@Produces(MediaType.APPLICATION_JSON)
public Response createServiceDependency(@PathParam("tenantServiceId") String tServiceId,
@PathParam("providerServiceId") String pServiceId) {
service.createServiceDependency(VtnServiceId.of(tServiceId),
VtnServiceId.of(pServiceId),
false);
return Response.status(Response.Status.OK).build();
}
/**
* Creates service dependencies with an access type extension between the services.
*
* @param tServiceId tenant service id
* @param pServiceId provider service id
* @param direction b for bidirectional access, otherwise unidirectional access
* @return 200 OK
*/
@POST
@Path("{tenantServiceId}/{providerServiceId}/{direction}")
@Produces(MediaType.APPLICATION_JSON)
public Response createServiceDependency(@PathParam("tenantServiceId") String tServiceId,
@PathParam("providerServiceId") String pServiceId,
@PathParam("direction") String direction) {
service.createServiceDependency(VtnServiceId.of(tServiceId),
VtnServiceId.of(pServiceId),
direction.equals(BIDIRECTION));
return Response.status(Response.Status.OK).build();
}
/**
* Removes service dependencies.
*
* @param tServiceId tenant service id
* @param pServiceId provider service id
* @return 204 NO CONTENT
*/
@DELETE
@Path("{tenantServiceId}/{providerServiceId}")
public Response removeServiceDependency(@PathParam("tenantServiceId") String tServiceId,
@PathParam("providerServiceId") String pServiceId) {
service.removeServiceDependency(VtnServiceId.of(tServiceId), VtnServiceId.of(pServiceId));
return Response.noContent().build();
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* REST APIs for CORD VTN.
*/
package org.onosproject.cordvtn.rest;
\ No newline at end of file
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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.cordvtn.cli.CordVtnNodeListCommand"/>
</command>
<command>
<action class="org.onosproject.cordvtn.cli.CordVtnNodeDeleteCommand"/>
</command>
<command>
<action class="org.onosproject.cordvtn.cli.CordVtnNodeInitCommand"/>
</command>
<command>
<action class="org.onosproject.cordvtn.cli.CordVtnNodeCheckCommand"/>
</command>
<command>
<action class="org.onosproject.cordvtn.cli.CordVtnFlushRules"/>
</command>
</command-bundle>
</blueprint>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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>CORD VTN REST API v1.0</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>Secured</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>admin</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>karaf</realm-name>
</login-config>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.onosproject.cordvtn.rest.CordVtnWebApplication</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>
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//lib:org.apache.karaf.shell.console',
'//cli:onos-cli',
'//apps/olt:onos-apps-olt-api',
'//apps/cordconfig:onos-apps-cordconfig',
]
BUNDLES = [
'//apps/olt:onos-apps-olt-api',
'//apps/igmp:onos-apps-igmp',
]
osgi_jar_with_tests (
deps = COMPILE_DEPS,
)
onos_app (
title = 'IGMP App',
category = 'Traffic Steering',
url = 'http://onosproject.org',
description = 'Internet Group Message Protocol',
included_bundles = BUNDLES,
)
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2015-present Open Networking Laboratory
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onosproject</groupId>
<artifactId>onos-apps</artifactId>
<version>1.6.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-igmp</artifactId>
<packaging>bundle</packaging>
<description>Internet Group Message Protocol</description>
<properties>
<onos.app.name>org.onosproject.igmp</onos.app.name>
<onos.app.title>IGMP App</onos.app.title>
<onos.app.category>Traffic Steering</onos.app.category>
<onos.app.url>http://onosproject.org</onos.app.url>
<onos.app.readme>IGMP implementation.</onos.app.readme>
<onos.app.requires>org.onosproject.cord-config</onos.app.requires>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-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>onos-app-olt-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-cord-config</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-junit</artifactId>
<scope>test</scope>
</dependency>
<!-- This is needed by ComponentContext, used for tunable configuration -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
/*
* Copyright 2016-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.igmp;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onlab.packet.IpAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.Config;
import org.onosproject.net.mcast.McastRoute;
import java.util.ArrayList;
import java.util.List;
/**
* IGMP SSM translate configuration.
*/
public class IgmpSsmTranslateConfig extends Config<ApplicationId> {
private static final String SOURCE = "source";
private static final String GROUP = "group";
@Override
public boolean isValid() {
for (JsonNode node : array) {
if (!hasOnlyFields((ObjectNode) node, SOURCE, GROUP)) {
return false;
}
if (!(isIpAddress((ObjectNode) node, SOURCE, FieldPresence.MANDATORY) &&
isIpAddress((ObjectNode) node, GROUP, FieldPresence.MANDATORY))) {
return false;
}
}
return true;
}
/**
* Gets the list of SSM translations.
*
* @return SSM translations
*/
public List<McastRoute> getSsmTranslations() {
List<McastRoute> translations = new ArrayList();
for (JsonNode node : array) {
translations.add(
new McastRoute(
IpAddress.valueOf(node.path(SOURCE).asText().trim()),
IpAddress.valueOf(node.path(GROUP).asText().trim()),
McastRoute.Type.STATIC));
}
return translations;
}
}
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* IGMP implementation.
*/
package org.onosproject.igmp;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.