Praseed Balakrishnan

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

......@@ -50,7 +50,10 @@ public class NetworkConfigReader {
private final Logger log = getLogger(getClass());
private static final String DEFAULT_CONFIG_FILE = "config/addresses.json";
// Current working dir seems to be /opt/onos/apache-karaf-3.0.2
// TODO: Set the path to /opt/onos/config
private static final String CONFIG_DIR = "../config";
private static final String DEFAULT_CONFIG_FILE = "addresses.json";
private String configFileName = DEFAULT_CONFIG_FILE;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......@@ -60,52 +63,9 @@ public class NetworkConfigReader {
protected void activate() {
log.info("Started network config reader");
log.info("Config file set to {}", configFileName);
AddressConfiguration config = readNetworkConfig();
if (config != null) {
for (AddressEntry entry : config.getAddresses()) {
ConnectPoint cp = new ConnectPoint(
DeviceId.deviceId(dpidToUri(entry.getDpid())),
PortNumber.portNumber(entry.getPortNumber()));
Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>();
for (String strIp : entry.getIpAddresses()) {
// Get the IP address and the subnet mask length
try {
String[] splits = strIp.split("/");
if (splits.length != 2) {
throw new IllegalArgumentException("Invalid IP address and prefix length format");
}
// NOTE: IpPrefix will mask-out the bits after the prefix length.
IpPrefix subnet = IpPrefix.valueOf(strIp);
IpAddress addr = IpAddress.valueOf(splits[0]);
InterfaceIpAddress ia =
new InterfaceIpAddress(addr, subnet);
interfaceIpAddresses.add(ia);
} catch (IllegalArgumentException e) {
log.warn("Bad format for IP address in config: {}", strIp);
}
}
MacAddress macAddress = null;
if (entry.getMacAddress() != null) {
try {
macAddress = MacAddress.valueOf(entry.getMacAddress());
} catch (IllegalArgumentException e) {
log.warn("Bad format for MAC address in config: {}",
entry.getMacAddress());
}
}
PortAddresses addresses = new PortAddresses(cp,
interfaceIpAddresses, macAddress);
hostAdminService.bindAddressesToPort(addresses);
}
applyNetworkConfig(config);
}
}
......@@ -114,12 +74,17 @@ public class NetworkConfigReader {
log.info("Stopped");
}
/**
* Reads the network configuration.
*
* @return the network configuration on success, otherwise null
*/
private AddressConfiguration readNetworkConfig() {
File configFile = new File(configFileName);
File configFile = new File(CONFIG_DIR, configFileName);
ObjectMapper mapper = new ObjectMapper();
try {
log.info("Loading config: {}", configFile.getAbsolutePath());
AddressConfiguration config =
mapper.readValue(configFile, AddressConfiguration.class);
......@@ -127,12 +92,58 @@ public class NetworkConfigReader {
} catch (FileNotFoundException e) {
log.warn("Configuration file not found: {}", configFileName);
} catch (IOException e) {
log.error("Unable to read config from file:", e);
log.error("Error loading configuration", e);
}
return null;
}
/**
* Applies the network configuration.
*
* @param config the network configuration to apply
*/
private void applyNetworkConfig(AddressConfiguration config) {
for (AddressEntry entry : config.getAddresses()) {
ConnectPoint cp = new ConnectPoint(
DeviceId.deviceId(dpidToUri(entry.getDpid())),
PortNumber.portNumber(entry.getPortNumber()));
Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>();
for (String strIp : entry.getIpAddresses()) {
// Get the IP address and the subnet mask length
try {
String[] splits = strIp.split("/");
if (splits.length != 2) {
throw new IllegalArgumentException("Invalid IP address and prefix length format");
}
// NOTE: IpPrefix will mask-out the bits after the prefix length.
IpPrefix subnet = IpPrefix.valueOf(strIp);
IpAddress addr = IpAddress.valueOf(splits[0]);
InterfaceIpAddress ia =
new InterfaceIpAddress(addr, subnet);
interfaceIpAddresses.add(ia);
} catch (IllegalArgumentException e) {
log.warn("Bad format for IP address in config: {}", strIp);
}
}
MacAddress macAddress = null;
if (entry.getMacAddress() != null) {
try {
macAddress = MacAddress.valueOf(entry.getMacAddress());
} catch (IllegalArgumentException e) {
log.warn("Bad format for MAC address in config: {}",
entry.getMacAddress());
}
}
PortAddresses addresses = new PortAddresses(cp,
interfaceIpAddresses, macAddress);
hostAdminService.bindAddressesToPort(addresses);
}
}
private static String dpidToUri(String dpid) {
return "of:" + dpid.replace(":", "");
}
......
{
"interfaces" : [
{
"dpid" : "00:00:00:00:00:00:01",
"port" : "1",
"ips" : ["192.168.10.101/24"],
"mac" : "00:00:00:11:22:33"
},
{
"dpid" : "00:00:00:00:00:00:02",
"port" : "1",
"ips" : ["192.168.20.101/24", "192.168.30.101/24"]
},
{
"dpid" : "00:00:00:00:00:00:03",
"port" : "1",
"ips" : ["10.1.0.1/16"],
"mac" : "00:00:00:00:00:01"
}
]
}
......@@ -37,24 +37,31 @@ import com.fasterxml.jackson.databind.ObjectMapper;
*/
public class SdnIpConfigReader implements SdnIpConfigService {
private static final Logger log = LoggerFactory.getLogger(SdnIpConfigReader.class);
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String DEFAULT_CONFIG_FILE = "config/sdnip.json";
// Current working dir seems to be /opt/onos/apache-karaf-3.0.2
// TODO: Set the path to /opt/onos/config
private static final String CONFIG_DIR = "../config";
private static final String DEFAULT_CONFIG_FILE = "sdnip.json";
private String configFileName = DEFAULT_CONFIG_FILE;
private Map<String, BgpSpeaker> bgpSpeakers = new ConcurrentHashMap<>();
private Map<IpAddress, BgpPeer> bgpPeers = new ConcurrentHashMap<>();
/**
* Reads the info contained in the configuration file.
* Reads SDN-IP related information contained in the configuration file.
*
* @param configFilename The name of configuration file for SDN-IP application.
* @param configFilename the name of the configuration file for the SDN-IP
* application
*/
private void readConfiguration(String configFilename) {
File gatewaysFile = new File(configFilename);
File configFile = new File(CONFIG_DIR, configFilename);
ObjectMapper mapper = new ObjectMapper();
try {
Configuration config = mapper.readValue(gatewaysFile, Configuration.class);
log.info("Loading config: {}", configFile.getAbsolutePath());
Configuration config = mapper.readValue(configFile,
Configuration.class);
for (BgpSpeaker speaker : config.getBgpSpeakers()) {
bgpSpeakers.put(speaker.name(), speaker);
}
......@@ -64,13 +71,11 @@ public class SdnIpConfigReader implements SdnIpConfigService {
} catch (FileNotFoundException e) {
log.warn("Configuration file not found: {}", configFileName);
} catch (IOException e) {
log.error("Error reading JSON file", e);
log.error("Error loading configuration", e);
}
}
public void init() {
log.debug("Config file set to {}", configFileName);
readConfiguration(configFileName);
}
......
ONOS looks for these config files by default in $KARAF_HOME/config/
\ No newline at end of file
The SDN-IP configuration files should be copied to directory
$ONOS_HOME/tools/package/config
After deployment and starting up the ONOS cluster, ONOS looks for these
configuration files in /opt/onos/config on each cluster member.
......
......@@ -28,4 +28,23 @@ public final class AnnotationKeys {
* Annotation key for latency.
*/
public static final String LATENCY = "latency";
/**
* Returns the value annotated object for the specified annotation key.
* The annotated value is expected to be String that can be parsed as double.
* If parsing fails, the returned value will be 1.0.
*
* @param annotated annotated object whose annotated value is obtained
* @param key key of annotation
* @return double value of annotated object for the specified key
*/
public static double getAnnotatedValue(Annotated annotated, String key) {
double value;
try {
value = Double.parseDouble(annotated.annotations().value(key));
} catch (NumberFormatException e) {
value = 1.0;
}
return value;
}
}
......
......@@ -80,6 +80,7 @@ public class DefaultFlowEntry extends DefaultFlowRule
this.state = FlowEntryState.FAILED;
this.errType = errType;
this.errCode = errCode;
this.lastSeen = System.currentTimeMillis();
}
@Override
......
......@@ -21,6 +21,8 @@ import org.onlab.onos.net.resource.LinkResourceService;
import java.util.Objects;
import static org.onlab.onos.net.AnnotationKeys.getAnnotatedValue;
/**
* Constraint that evaluates an arbitrary link annotated value is under the specified threshold.
*/
......@@ -65,25 +67,6 @@ public class AnnotationConstraint extends BooleanConstraint {
return value <= threshold;
}
/**
* Returns the annotated value of the specified link. The annotated value
* is expected to be String that can be parsed as double. If parsing fails,
* the returned value will be 1.0.
*
* @param link link whose annotated value is obtained
* @param key key of link annotation
* @return double value of link annotation for the specified key
*/
private double getAnnotatedValue(Link link, String key) {
double value;
try {
value = Double.parseDouble(link.annotations().value(key));
} catch (NumberFormatException e) {
value = 1.0;
}
return value;
}
@Override
public double cost(Link link, LinkResourceService resourceService) {
if (isValid(link, resourceService)) {
......
......@@ -26,6 +26,7 @@ import java.time.temporal.ChronoUnit;
import java.util.Objects;
import static org.onlab.onos.net.AnnotationKeys.LATENCY;
import static org.onlab.onos.net.AnnotationKeys.getAnnotatedValue;
/**
* Constraint that evaluates the latency through a path.
......@@ -48,16 +49,7 @@ public class LatencyConstraint implements Constraint {
@Override
public double cost(Link link, LinkResourceService resourceService) {
String value = link.annotations().value(LATENCY);
double latencyInMicroSec;
try {
latencyInMicroSec = Double.parseDouble(value);
} catch (NumberFormatException e) {
latencyInMicroSec = 1.0;
}
return latencyInMicroSec;
return getAnnotatedValue(link, LATENCY);
}
@Override
......
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onlab.onos.net.flow;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.onlab.onos.net.intent.IntentTestsMocks;
import com.google.common.testing.EqualsTester;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.onlab.onos.net.NetTestTools.did;
/**
* Unit tests for the DefaultFlowEntry class.
*/
public class DefaultFlowEntryTest {
private static final IntentTestsMocks.MockSelector SELECTOR =
new IntentTestsMocks.MockSelector();
private static final IntentTestsMocks.MockTreatment TREATMENT =
new IntentTestsMocks.MockTreatment();
private static DefaultFlowEntry makeFlowEntry(int uniqueValue) {
return new DefaultFlowEntry(did("id" + Integer.toString(uniqueValue)),
SELECTOR,
TREATMENT,
uniqueValue,
FlowEntry.FlowEntryState.ADDED,
uniqueValue,
uniqueValue,
uniqueValue,
uniqueValue,
uniqueValue);
}
final DefaultFlowEntry defaultFlowEntry1 = makeFlowEntry(1);
final DefaultFlowEntry sameAsDefaultFlowEntry1 = makeFlowEntry(1);
final DefaultFlowEntry defaultFlowEntry2 = makeFlowEntry(2);
/**
* Tests the equals, hashCode and toString methods using Guava EqualsTester.
*/
@Test
public void testEquals() {
new EqualsTester()
.addEqualityGroup(defaultFlowEntry1, sameAsDefaultFlowEntry1)
.addEqualityGroup(defaultFlowEntry2)
.testEquals();
}
/**
* Tests the construction of a default flow entry from a device id.
*/
@Test
public void testDeviceBasedObject() {
assertThat(defaultFlowEntry1.deviceId(), is(did("id1")));
assertThat(defaultFlowEntry1.selector(), is(SELECTOR));
assertThat(defaultFlowEntry1.treatment(), is(TREATMENT));
assertThat(defaultFlowEntry1.timeout(), is(1));
assertThat(defaultFlowEntry1.life(), is(1L));
assertThat(defaultFlowEntry1.packets(), is(1L));
assertThat(defaultFlowEntry1.bytes(), is(1L));
assertThat(defaultFlowEntry1.state(), is(FlowEntry.FlowEntryState.ADDED));
assertThat(defaultFlowEntry1.lastSeen(),
greaterThan(System.currentTimeMillis() -
TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
}
/**
* Tests the setters on a default flow entry object.
*/
@Test
public void testSetters() {
final DefaultFlowEntry entry = makeFlowEntry(1);
entry.setLastSeen();
entry.setState(FlowEntry.FlowEntryState.PENDING_REMOVE);
entry.setPackets(11);
entry.setBytes(22);
entry.setLife(33);
assertThat(entry.deviceId(), is(did("id1")));
assertThat(entry.selector(), is(SELECTOR));
assertThat(entry.treatment(), is(TREATMENT));
assertThat(entry.timeout(), is(1));
assertThat(entry.life(), is(33L));
assertThat(entry.packets(), is(11L));
assertThat(entry.bytes(), is(22L));
assertThat(entry.state(), is(FlowEntry.FlowEntryState.PENDING_REMOVE));
assertThat(entry.lastSeen(),
greaterThan(System.currentTimeMillis() -
TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
}
/**
* Tests a default flow rule built for an error.
*/
@Test
public void testErrorObject() {
final DefaultFlowEntry errorEntry =
new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(1),
111,
222);
assertThat(errorEntry.errType(), is(111));
assertThat(errorEntry.errCode(), is(222));
assertThat(errorEntry.state(), is(FlowEntry.FlowEntryState.FAILED));
assertThat(errorEntry.lastSeen(),
greaterThan(System.currentTimeMillis() -
TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
}
/**
* Tests a default flow entry constructed from a flow rule.
*/
@Test
public void testFlowBasedObject() {
final DefaultFlowEntry entry =
new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(1));
assertThat(entry.priority(), is(1));
assertThat(entry.appId(), is((short) 0));
assertThat(entry.lastSeen(),
greaterThan(System.currentTimeMillis() -
TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
}
/**
* Tests a default flow entry constructed from a flow rule plus extra
* parameters.
*/
@Test
public void testFlowBasedObjectWithParameters() {
final DefaultFlowEntry entry =
new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(33),
FlowEntry.FlowEntryState.REMOVED,
101, 102, 103);
assertThat(entry.state(), is(FlowEntry.FlowEntryState.REMOVED));
assertThat(entry.life(), is(101L));
assertThat(entry.packets(), is(102L));
assertThat(entry.bytes(), is(103L));
assertThat(entry.lastSeen(),
greaterThan(System.currentTimeMillis() -
TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS)));
}
}
......@@ -17,7 +17,6 @@
package org.onlab.onos.net.flow;
import org.junit.Test;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.intent.IntentTestsMocks;
import com.google.common.testing.EqualsTester;
......@@ -25,8 +24,8 @@ import com.google.common.testing.EqualsTester;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBaseClass;
import static org.onlab.onos.net.NetTestTools.did;
import static org.onlab.onos.net.NetTestTools.APP_ID;
import static org.onlab.onos.net.NetTestTools.did;
/**
* Unit tests for the default flow rule class.
......@@ -37,63 +36,13 @@ public class DefaultFlowRuleTest {
private static final IntentTestsMocks.MockTreatment TREATMENT =
new IntentTestsMocks.MockTreatment();
final FlowRule flowRule1 = new MockFlowRule(1);
final FlowRule sameAsFlowRule1 = new MockFlowRule(1);
final FlowRule flowRule2 = new MockFlowRule(2);
final FlowRule flowRule1 = new IntentTestsMocks.MockFlowRule(1);
final FlowRule sameAsFlowRule1 = new IntentTestsMocks.MockFlowRule(1);
final FlowRule flowRule2 = new IntentTestsMocks.MockFlowRule(2);
final DefaultFlowRule defaultFlowRule1 = new DefaultFlowRule(flowRule1);
final DefaultFlowRule sameAsDefaultFlowRule1 = new DefaultFlowRule(sameAsFlowRule1);
final DefaultFlowRule defaultFlowRule2 = new DefaultFlowRule(flowRule2);
private static class MockFlowRule implements FlowRule {
int priority;
MockFlowRule(int priority) {
this.priority = priority;
}
@Override
public FlowId id() {
return FlowId.valueOf(1);
}
@Override
public short appId() {
return 0;
}
@Override
public int priority() {
return priority;
}
@Override
public DeviceId deviceId() {
return did("1");
}
@Override
public TrafficSelector selector() {
return SELECTOR;
}
@Override
public TrafficTreatment treatment() {
return TREATMENT;
}
@Override
public int timeout() {
return 0;
}
@Override
public boolean isPermanent() {
return false;
}
}
/**
* Checks that the DefaultFlowRule class is immutable but can be inherited
* from.
......
......@@ -16,6 +16,7 @@
package org.onlab.onos.net.intent;
import static org.onlab.onos.net.NetTestTools.createPath;
import static org.onlab.onos.net.NetTestTools.did;
import static org.onlab.onos.net.NetTestTools.link;
import java.util.ArrayList;
......@@ -31,6 +32,8 @@ import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.ElementId;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.FlowId;
import org.onlab.onos.net.flow.FlowRule;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.flow.criteria.Criterion;
......@@ -271,4 +274,60 @@ public class IntentTestsMocks {
}
}
private static final IntentTestsMocks.MockSelector SELECTOR =
new IntentTestsMocks.MockSelector();
private static final IntentTestsMocks.MockTreatment TREATMENT =
new IntentTestsMocks.MockTreatment();
public static class MockFlowRule implements FlowRule {
int priority;
public MockFlowRule(int priority) {
this.priority = priority;
}
@Override
public FlowId id() {
return FlowId.valueOf(1);
}
@Override
public short appId() {
return 0;
}
@Override
public int priority() {
return priority;
}
@Override
public DeviceId deviceId() {
return did("1");
}
@Override
public TrafficSelector selector() {
return SELECTOR;
}
@Override
public TrafficTreatment treatment() {
return TREATMENT;
}
@Override
public int timeout() {
return 0;
}
@Override
public boolean isPermanent() {
return false;
}
}
}
......
......@@ -72,7 +72,7 @@ public class DatabaseManager implements DatabaseService, DatabaseAdminService {
public static final String LOG_FILE_PREFIX = "/tmp/onos-copy-cat-log_";
// Current working dir seems to be /opt/onos/apache-karaf-3.0.2
// TODO: Get the path to /opt/onos/config
// TODO: Set the path to /opt/onos/config
private static final String CONFIG_DIR = "../config";
private static final String DEFAULT_MEMBER_FILE = "tablets.json";
......
......@@ -197,6 +197,8 @@
<feature name="onos-app-sdnip" version="1.0.0"
description="SDN-IP peering application">
<feature>onos-api</feature>
<feature>onos-app-proxyarp</feature>
<feature>onos-app-config</feature>
<bundle>mvn:org.onlab.onos/onos-app-sdnip/1.0.0-SNAPSHOT</bundle>
</feature>
......
onos-config command will copy files contained in this directory to ONOS instances according to cell definition
The onos-config command will copy files contained in this directory to ONOS
instances according to cell definition.
......