refactor code and service separation for MOAS support
Change-Id: Id00a59a46a30d3a8c976611e637c28fe609c9842
diff --git a/apps/artemis/BUCK b/apps/artemis/BUCK
old mode 100644
new mode 100755
index 82c703a..e06097d
--- a/apps/artemis/BUCK
+++ b/apps/artemis/BUCK
@@ -1,24 +1,36 @@
COMPILE_DEPS = [
'//lib:CORE_DEPS',
- '//lib:NETTY',
'//lib:JACKSON',
+ '//lib:NETTY',
+ '//lib:netty',
+ '//lib:netty-transport',
'//lib:org.apache.karaf.shell.console',
'//cli:onos-cli',
'//apps/routing-api:onos-apps-routing-api',
'//apps/routing/common:onos-apps-routing-common',
+ '//protocols/ovsdb/api:onos-protocols-ovsdb-api',
+ '//apps/intentsync:onos-apps-intentsync',
+ '//apps/route-service/api:onos-apps-route-service-api',
+ '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc',
'//lib:okhttp',
'//lib:okio',
':commons-net',
':io.socket-client',
':json',
- ':engine.io-client',
- '//lib:netty',
+ ':engine.io-client'
]
BUNDLES = [
'//apps/artemis:onos-apps-artemis',
'//apps/routing-api:onos-apps-routing-api',
'//apps/routing/common:onos-apps-routing-common',
+ '//protocols/ovsdb/api:onos-protocols-ovsdb-api',
+ '//apps/route-service/api:onos-apps-route-service-api',
+ '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc'
+]
+
+TEST_DEPS = [
+ '//lib:TEST_ADAPTERS'
]
EXCLUDED_BUNDLES = [
@@ -30,8 +42,9 @@
':engine.io-client'
]
-osgi_jar (
+osgi_jar_with_tests (
deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
)
onos_app (
@@ -42,7 +55,12 @@
description = 'Artemis',
included_bundles = BUNDLES,
excluded_bundles = EXCLUDED_BUNDLES,
- required_apps = [ 'org.onosproject.sdnip' ],
+ required_apps = [
+ 'org.onosproject.sdnip',
+ 'org.onosproject.openflow',
+ 'org.onosproject.ovsdb',
+ 'org.onosproject.drivers.ovsdb'
+ ],
)
remote_jar (
@@ -79,4 +97,4 @@
sha1 = '854b49396e1e9f9bb0ab025062ddb49c4ed65ca1',
maven_coords = 'io.socket:engine.io-client:jar:NON-OSGI:0.8.3',
visibility = [ 'PUBLIC' ],
-)
+)
\ No newline at end of file
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisDeaggregator.java b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisDeaggregator.java
new file mode 100644
index 0000000..227f68d3
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisDeaggregator.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis;
+
+/**
+ * Interface for Deaggregator Service of Artemis.
+ *
+ * When a prefix hijacking is detected, ARTEMIS automatically launches its mitigation service (deaggregator).
+ * Since in Internet routing the most specific prefix is always preferred, ARTEMIS modifies the BGP configuration of
+ * the routers so that they announce deaggregated sub-prefixes of the hijacked prefix (that are most preferred from any
+ * AS). After BGP converges, the hijacking attack is mitigated and traffic flows normally back to the ARTEMIS-protected
+ * AS (the one that runs ARTEMIS). Therefore, ARTEMIS assumes write permissions to the routers of the network, in order
+ * to be able to modify their BGP configuration and mitigate the attack. The purpose of this service is to receive all
+ * hijack events from the detector service and proceed on writing all the new prefixes to be announced by the BGP
+ * Speakers.
+ */
+public interface ArtemisDeaggregator {
+ //TODO: give the ability of other services to announce prefixes to BGP Speakers through this interface
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisDetector.java b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisDetector.java
new file mode 100644
index 0000000..650d32d
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisDetector.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis;
+
+/**
+ * Interface for Detector Service of Artemis.
+ *
+ * The detection service combines the information received through the events generated from the monitor service and
+ * the configuration file that includes all the legit BGP paths. The purpose of this interface is to identify given
+ * a BGP update message if there is a BGP hijack or not.
+ */
+public interface ArtemisDetector {
+ //TODO: give the ability to other services to check the legitimacy of a BGP Update message
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisService.java b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisEventListener.java
similarity index 64%
rename from apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisService.java
rename to apps/artemis/src/main/java/org/onosproject/artemis/ArtemisEventListener.java
index 910906c..ced3d56 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisService.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisEventListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,18 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.artemis.impl;
+package org.onosproject.artemis;
+
+import org.onosproject.artemis.impl.ArtemisEvent;
+import org.onosproject.event.EventListener;
/**
- * Artemis Service.
+ * Entity capable of receiving artemis-related events.
*/
-public interface ArtemisService {
-
- /**
- * Set logger to print incoming packets or not.
- *
- * @param value true to print incoming BGP messages
- */
- void setLogger(boolean value);
-
+public interface ArtemisEventListener extends EventListener<ArtemisEvent> {
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisMoasAgent.java b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisMoasAgent.java
new file mode 100644
index 0000000..b25c714
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisMoasAgent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis;
+
+import io.netty.channel.ChannelHandlerContext;
+import org.onlab.packet.IpAddress;
+
+/**
+ * MOAS agent that handles remote connections.
+ */
+public interface ArtemisMoasAgent {
+
+ /**
+ * Keep a connection active if MOAS client is legit.
+ *
+ * @param ipAddress remote IP address
+ * @param ctx channel context
+ */
+ void addMoas(IpAddress ipAddress, ChannelHandlerContext ctx);
+
+ /**
+ * Remove MOAS.
+ *
+ * @param ipAddress remote IP address
+ */
+ void removeMoas(IpAddress ipAddress);
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisMonitor.java b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisMonitor.java
new file mode 100755
index 0000000..2d82145
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisMonitor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis;
+
+/**
+ * Interface for Monitor Service of Artemis.
+ *
+ * The monitoring service runs continuously and provides control plane information from the AS itself, the streaming
+ * services can be RIPE RIS, BGPstream, BGPmon and Periscope, which return almost real-time BGP updates for a given
+ * list of prefixes and ASNs. The purpose of this interface is to provide store and provide this BGO information to the
+ * consumers (e.g. Artemis Detector Service).
+ */
+public interface ArtemisMonitor {
+ //TODO: give access to BGP Update messages to other services through this service
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisPacketProcessor.java b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisPacketProcessor.java
new file mode 100644
index 0000000..d4cae92
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisPacketProcessor.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis;
+
+import io.netty.channel.ChannelHandlerContext;
+import org.json.JSONObject;
+import org.onosproject.artemis.impl.objects.ArtemisMessage;
+
+/**
+ * Packet processor for artemis messages.
+ */
+public interface ArtemisPacketProcessor {
+
+ /**
+ * Process a packet received from a MOAS client/server.
+ *
+ * @param msg artemis message
+ * @param ctx channel context
+ */
+ void processMoasPacket(ArtemisMessage msg, ChannelHandlerContext ctx);
+
+ /**
+ * Process a BGP Update packet received from a monitor.
+ *
+ * @param msg BGP Update message
+ */
+ void processMonitorPacket(JSONObject msg);
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisService.java b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisService.java
new file mode 100644
index 0000000..37206b0
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/ArtemisService.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis;
+
+import org.onosproject.artemis.impl.ArtemisConfig;
+import org.onosproject.artemis.impl.ArtemisEvent;
+import org.onosproject.event.ListenerService;
+
+import java.util.Optional;
+
+/**
+ * The main service/orchestrator of Artemis.
+ */
+public interface ArtemisService extends ListenerService<ArtemisEvent, ArtemisEventListener> {
+
+ /**
+ * Get the current configuration.
+ *
+ * @return config
+ */
+ Optional<ArtemisConfig> getConfig();
+
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisService.java b/apps/artemis/src/main/java/org/onosproject/artemis/BgpSpeakers.java
similarity index 64%
copy from apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisService.java
copy to apps/artemis/src/main/java/org/onosproject/artemis/BgpSpeakers.java
index 910906c..9b333bc 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisService.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/BgpSpeakers.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,18 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.artemis.impl;
+package org.onosproject.artemis;
/**
- * Artemis Service.
+ * Interface for all the types of BGP Speakers.
*/
-public interface ArtemisService {
+public interface BgpSpeakers {
/**
- * Set logger to print incoming packets or not.
+ * Announces the two new subprefixes on the BGP Speaker.
*
- * @param value true to print incoming BGP messages
+ * @param prefixes list of two prefixes
*/
- void setLogger(boolean value);
-
+ void announceSubPrefixes(String[] prefixes);
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/Monitor.java b/apps/artemis/src/main/java/org/onosproject/artemis/Monitors.java
similarity index 62%
rename from apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/Monitor.java
rename to apps/artemis/src/main/java/org/onosproject/artemis/Monitors.java
index 853f1a0..3a5bf22 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/Monitor.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/Monitors.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,90 +13,91 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.artemis.impl.monitors;
+package org.onosproject.artemis;
import org.onlab.packet.IpPrefix;
+import java.util.Arrays;
+import java.util.Optional;
+
/**
- * Abstract class for Monitors.
+ * Interface for Monitors.
*/
-public abstract class Monitor {
- /**
- * Match enum type with monitor type inside configuration to map them.
- */
- public enum Types {
- RIPE {
- @Override
- public String toString() {
- return "ripe";
- }
- },
- EXABGP {
- @Override
- public String toString() {
- return "exabgp";
- }
- }
- }
-
- IpPrefix prefix;
- Monitor(IpPrefix prefix) {
- this.prefix = prefix;
- }
-
+public interface Monitors {
/**
* Get prefix of the specific monitor.
*
* @return prefix
*/
- public IpPrefix getPrefix() {
- return prefix;
- }
+ IpPrefix getPrefix();
/**
* Set prefix for monitor.
*
* @param prefix prefix
*/
- public void setPrefix(IpPrefix prefix) {
- this.prefix = prefix;
- }
+ void setPrefix(IpPrefix prefix);
/**
* Start monitor to begin capturing incoming BGP packets.
*/
- public abstract void startMonitor();
+ void startMonitor();
/**
* Stop monitor from capturing incoming BGP packets.
*/
- public abstract void stopMonitor();
-
- /**
- * Get type of monitor.
- *
- * @return enum type
- */
- public abstract Types getType();
+ void stopMonitor();
/**
* Check if monitor is running.
*
* @return true if running
*/
- public abstract boolean isRunning();
+ boolean isRunning();
/**
* Get host alias e.g. IP address, name.
*
* @return host alias
*/
- public abstract String getHost();
+ String getHost();
/**
* Set alias of host.
*
* @param host alias
*/
- public abstract void setHost(String host);
+ void setHost(String host);
+
+ /**
+ * Match enum type with monitor type inside configuration to map them.
+ */
+ enum Types {
+ RIPE("ripe") {
+ @Override
+ public String toString() {
+ return "ripe";
+ }
+ },
+ EXABGP("exabgp") {
+ @Override
+ public String toString() {
+ return "exabgp";
+ }
+ };
+
+ private String name;
+
+ Types(String name) {
+ this.name = name;
+ }
+
+ public static Types getEnum(String name) {
+ Optional<Types> any = Arrays.stream(Types.values()).filter(typeStr -> typeStr.name.equals(name)).findAny();
+ if (any.isPresent()) {
+ return any.get();
+ }
+ throw new IllegalArgumentException("No enum defined for string: " + name);
+ }
+ }
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/cli/LogOptionsCommand.java b/apps/artemis/src/main/java/org/onosproject/artemis/cli/LogOptionsCommand.java
deleted file mode 100644
index 334b4ab..0000000
--- a/apps/artemis/src/main/java/org/onosproject/artemis/cli/LogOptionsCommand.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2015 Open Networking Foundation
- *
- * 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.artemis.cli;
-
-import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.Option;
-import org.onosproject.artemis.impl.ArtemisService;
-import org.onosproject.cli.AbstractShellCommand;
-
-/**
- * CLI to enable or disable BGP Update message logging.
- */
-@Command(scope = "artemis", name = "log-messages",
- description = "Show RIS messages in logger.")
-public class LogOptionsCommand extends AbstractShellCommand {
-
- @Option(name = "--enable", aliases = "-e", description = "Enable RIS message logging",
- required = false, multiValued = false)
- private boolean enable = false;
-
- @Option(name = "--disable", aliases = "-d", description = "Disable RIS message logging",
- required = false, multiValued = false)
- private boolean disable = false;
-
- @Override
- protected void execute() {
- ArtemisService artemisService = get(ArtemisService.class);
- if (enable) {
- artemisService.setLogger(true);
- } else if (disable) {
- artemisService.setLogger(false);
- }
- }
-}
\ No newline at end of file
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisConfig.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisConfig.java
index 54285a8..b21c5f6 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisConfig.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2015-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,8 +18,10 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import com.google.common.collect.Streams;
import org.json.JSONArray;
import org.json.JSONException;
+import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.Config;
@@ -31,14 +33,14 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Artemis Configuration Class.
*/
-class ArtemisConfig extends Config<ApplicationId> {
-
+public class ArtemisConfig extends Config<ApplicationId> {
private static final String PREFIXES = "prefixes";
/* */
private static final String PREFIX = "prefix";
@@ -49,18 +51,29 @@
private static final String NEIGHBOR = "neighbor";
private static final String ASN = "asn";
/* */
-
private static final String MONITORS = "monitors";
/* */
private static final String RIPE = "ripe";
private static final String EXABGP = "exabgp";
/* */
-
- private static final String FREQUENCY = "frequency";
-
+ private static final String MOAS_LEGIT = "legit";
+ private static final String TUNNEL_POINTS = "tunnelPoints";
+ private static final String TUNNEL_OVSDB_IP = "ovsdb_ip";
+ private static final String TUNNEL_LOCAL_IP = "local_ip";
+ private static final String TUNNEL_OVS_PORT = "ovs_port";
private final Logger log = LoggerFactory.getLogger(getClass());
+ Set<IpPrefix> prefixesToMonitor() {
+ JsonNode prefixesNode = object.path(PREFIXES);
+ if (!prefixesNode.isMissingNode()) {
+ return Streams.stream(prefixesNode)
+ .map(prefix -> IpPrefix.valueOf(prefix.get(PREFIX).asText()))
+ .collect(Collectors.toSet());
+ }
+ return null;
+ }
+
/**
* Gets the set of monitored prefixes with the details (prefix, paths and MOAS).
*
@@ -69,8 +82,8 @@
Set<ArtemisPrefixes> monitoredPrefixes() {
Set<ArtemisPrefixes> prefixes = Sets.newHashSet();
- JsonNode prefixesNode = object.get(PREFIXES);
- if (prefixesNode == null) {
+ JsonNode prefixesNode = object.path(PREFIXES);
+ if (prefixesNode.isMissingNode()) {
log.warn("prefixes field is null!");
return prefixes;
}
@@ -78,33 +91,16 @@
prefixesNode.forEach(jsonNode -> {
IpPrefix prefix = IpPrefix.valueOf(jsonNode.get(PREFIX).asText());
- Set<Integer> moasNumbers = Sets.newHashSet();
JsonNode moasNode = jsonNode.get(MOAS);
- moasNode.forEach(asn ->
- moasNumbers.add(asn.asInt())
- );
+ Set<IpAddress> moasIps = Streams.stream(moasNode)
+ .map(asn -> IpAddress.valueOf(asn.asText()))
+ .collect(Collectors.toSet());
- /*
- "paths" : [{
- "origin" : 65004,
- "neighbor" : [{
- "asn" : 65002,
- "neighbor": [{
- "asn" : 65001,
- }]
- }]
- }]
- */
-
- Map<Integer, Map<Integer, Set<Integer>>> paths = Maps.newHashMap();
JsonNode pathsNode = jsonNode.get(PATHS);
- pathsNode.forEach(path -> {
- addPath(paths, path);
- });
+ Map<Integer, Map<Integer, Set<Integer>>> paths = Maps.newHashMap();
+ pathsNode.forEach(path -> addPath(paths, path));
- // printPaths(paths);
-
- prefixes.add(new ArtemisPrefixes(prefix, moasNumbers, paths));
+ prefixes.add(new ArtemisPrefixes(prefix, moasIps, paths));
});
return prefixes;
@@ -146,7 +142,7 @@
paths.put(origin, first2second);
}
});
- // else append to paths without second neighbor
+ // else append to paths without second neighbor
} else {
if (!paths.containsKey(origin)) {
Map<Integer, Set<Integer>> first2second = Maps.newHashMap();
@@ -161,7 +157,7 @@
}
}
});
- // else append to paths only the origin
+ // else append to paths only the origin
} else {
if (!paths.containsKey(origin)) {
paths.put(origin, Maps.newHashMap());
@@ -169,34 +165,17 @@
}
}
- /**
- * Helper function to print the loaded ASN paths.
- *
- * @param paths ASN paths to print
- */
- private void printPaths(Map<Integer, Map<Integer, Set<Integer>>> paths) {
- log.warn("------------------------------------");
- paths.forEach((k, v) -> v.forEach((l, n) -> {
- n.forEach(p -> log.warn("Origin: " + k + ", 1st: " + l + ", 2nd: " + p));
- }));
- }
-
- /**
- * Gets the frequency of the detection module in milliseconds.
- *
- * @return frequency (ms)
- */
- int detectionFrequency() {
- JsonNode thresholdNode = object.get(FREQUENCY);
- int threshold = 0;
-
- if (thresholdNode == null) {
- log.warn("threshold field is null!");
- return threshold;
- }
-
- return thresholdNode.asInt();
- }
+// /**
+// * Helper function to print the loaded ASN paths.
+// *
+// * @param paths ASN paths to print
+// */
+// private void printPaths(Map<Integer, Map<Integer, Set<Integer>>> paths) {
+// log.warn("------------------------------------");
+// paths.forEach((k, v) -> v.forEach((l, n) -> {
+// n.forEach(p -> log.warn("Origin: " + k + ", 1st: " + l + ", 2nd: " + p));
+// }));
+// }
/**
* Gets the active route collectors.
@@ -206,36 +185,185 @@
Map<String, Set<String>> activeMonitors() {
Map<String, Set<String>> monitors = Maps.newHashMap();
- JsonNode monitorsNode = object.get(MONITORS);
+ JsonNode monitorsNode = object.path(MONITORS);
- JsonNode ripeNode = monitorsNode.path(RIPE);
- if (!ripeNode.isMissingNode()) {
- Set<String> hosts = Sets.newHashSet();
- ripeNode.forEach(host -> hosts.add(host.asText()));
- monitors.put(RIPE, hosts);
- }
+ if (!monitorsNode.isMissingNode()) {
+ JsonNode ripeNode = monitorsNode.path(RIPE);
+ if (!ripeNode.isMissingNode()) {
+ Set<String> hosts = Sets.newHashSet();
+ ripeNode.forEach(host -> hosts.add(host.asText()));
+ monitors.put(RIPE, hosts);
+ }
- JsonNode exabgpNode = monitorsNode.path(EXABGP);
- if (!exabgpNode.isMissingNode()) {
- Set<String> hosts = Sets.newHashSet();
- exabgpNode.forEach(host -> hosts.add(host.asText()));
- monitors.put(EXABGP, hosts);
+ JsonNode exabgpNode = monitorsNode.path(EXABGP);
+ if (!exabgpNode.isMissingNode()) {
+ Set<String> hosts = Sets.newHashSet();
+ exabgpNode.forEach(host -> hosts.add(host.asText()));
+ monitors.put(EXABGP, hosts);
+ }
}
return monitors;
}
/**
+ * Get the information about MOAS. Including remote MOAS server IPs, OVSDB ID and local tunnel IP.
+ *
+ * @return MOAS information
+ */
+ MoasInfo moasInfo() {
+ MoasInfo moasInfo = new MoasInfo();
+
+ JsonNode moasNode = object.path(MOAS);
+
+ if (!moasNode.isMissingNode()) {
+ JsonNode legitIpsNode = moasNode.path(MOAS_LEGIT);
+ if (!legitIpsNode.isMissingNode()) {
+ if (legitIpsNode.isArray()) {
+ moasInfo.setMoasAddresses(
+ Streams.stream(legitIpsNode)
+ .map(ipAddress -> IpAddress.valueOf(ipAddress.asText()))
+ .collect(Collectors.toSet())
+ );
+ } else {
+ log.warn("Legit MOAS field need to be a list");
+ }
+ } else {
+ log.warn("No IPs for legit MOAS specified in configuration");
+ }
+
+ JsonNode tunnelPointsNode = moasNode.path(TUNNEL_POINTS);
+ if (!tunnelPointsNode.isMissingNode()) {
+ if (tunnelPointsNode.isArray()) {
+ tunnelPointsNode.forEach(
+ tunnelPoint -> {
+ JsonNode idNode = tunnelPoint.path(TUNNEL_OVSDB_IP),
+ localNode = tunnelPoint.path(TUNNEL_LOCAL_IP),
+ ovsNode = tunnelPoint.path(TUNNEL_OVS_PORT);
+
+ if (!idNode.isMissingNode() && !localNode.isMissingNode()) {
+ moasInfo.addTunnelPoint(
+ new MoasInfo.TunnelPoint(
+ IpAddress.valueOf(idNode.asText()),
+ IpAddress.valueOf(localNode.asText()),
+ ovsNode.asText()
+ )
+ );
+ } else {
+ log.warn("Tunnel point need to have an ID and a Local IP");
+ }
+ }
+ );
+ } else {
+ log.warn("Tunnel points field need to be a list");
+ }
+ }
+ } else {
+ log.warn("No tunnel points specified in configuration");
+ }
+
+ return moasInfo;
+ }
+
+ /**
+ * Information holder for MOAS.
+ */
+ public static class MoasInfo {
+ private Set<IpAddress> moasAddresses;
+ private Set<TunnelPoint> tunnelPoints;
+
+ public MoasInfo() {
+ moasAddresses = Sets.newConcurrentHashSet();
+ tunnelPoints = Sets.newConcurrentHashSet();
+ }
+
+ public Set<IpAddress> getMoasAddresses() {
+ return moasAddresses;
+ }
+
+ public void setMoasAddresses(Set<IpAddress> moasAddresses) {
+ this.moasAddresses = moasAddresses;
+ }
+
+ public Set<TunnelPoint> getTunnelPoints() {
+ return tunnelPoints;
+ }
+
+ public void setTunnelPoints(Set<TunnelPoint> tunnelPoints) {
+ this.tunnelPoints = tunnelPoints;
+ }
+
+ public TunnelPoint getTunnelPoint() {
+ return tunnelPoints.iterator().next();
+ }
+
+ public void addTunnelPoint(TunnelPoint tunnelPoint) {
+ this.tunnelPoints.add(tunnelPoint);
+ }
+
+ @Override
+ public String toString() {
+ return "MoasInfo{" +
+ "moasAddresses=" + moasAddresses +
+ ", tunnelPoints=" + tunnelPoints +
+ '}';
+ }
+
+ public static class TunnelPoint {
+ private IpAddress ovsdbIp;
+ private IpAddress localIP;
+ private String ovsPort;
+
+ public TunnelPoint(IpAddress ovsdbIp, IpAddress localIP, String ovsPort) {
+ this.ovsdbIp = ovsdbIp;
+ this.localIP = localIP;
+ this.ovsPort = ovsPort;
+ }
+
+ public IpAddress getOvsdbIp() {
+ return ovsdbIp;
+ }
+
+ public void setOvsdbIp(IpAddress ovsdbIp) {
+ this.ovsdbIp = ovsdbIp;
+ }
+
+ public IpAddress getLocalIp() {
+ return localIP;
+ }
+
+ public void setLocalIp(IpAddress localIP) {
+ this.localIP = localIP;
+ }
+
+ public String getOvsPort() {
+ return ovsPort;
+ }
+
+ public void setOvsPort(String ovsPort) {
+ this.ovsPort = ovsPort;
+ }
+
+ @Override
+ public String toString() {
+ return "TunnelPoint{" +
+ "ovsdbIp='" + ovsdbIp + '\'' +
+ ", localIP=" + localIP +
+ ", ovsPort='" + ovsPort + '\'' +
+ '}';
+ }
+ }
+ }
+
+ /**
* Configuration for a specific prefix.
*/
- static class ArtemisPrefixes {
+ public class ArtemisPrefixes {
private IpPrefix prefix;
- private Set<Integer> moas;
+ private Set<IpAddress> moas;
private Map<Integer, Map<Integer, Set<Integer>>> paths;
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- ArtemisPrefixes(IpPrefix prefix, Set<Integer> moas, Map<Integer, Map<Integer, Set<Integer>>> paths) {
+ ArtemisPrefixes(IpPrefix prefix, Set<IpAddress> moas, Map<Integer, Map<Integer, Set<Integer>>> paths) {
this.prefix = checkNotNull(prefix);
this.moas = checkNotNull(moas);
this.paths = checkNotNull(paths);
@@ -245,7 +373,7 @@
return prefix;
}
- protected Set<Integer> moas() {
+ protected Set<IpAddress> moas() {
return moas;
}
@@ -261,8 +389,8 @@
*
* @param path as-path that announces our prefix and found from monitors
* @return <code>0</code> no bgp hijack detected
- * <code>50</code> friendly anycaster announcing our prefix
- * <code>100+i</code> BGP hijack type i (0 <= i <=2)
+ * <code>50</code> friendly anycaster announcing our prefix
+ * <code>100+i</code> BGP hijack type i (0 <= i <=2)
*/
int checkPath(JSONArray path) {
// TODO add MOAS check
@@ -288,6 +416,15 @@
}
@Override
+ public String toString() {
+ return "ArtemisPrefixes{" +
+ "prefix=" + prefix +
+ ", moas=" + moas +
+ ", paths=" + paths +
+ '}';
+ }
+
+ @Override
public int hashCode() {
return Objects.hashCode(prefix);
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisDeaggregatorImpl.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisDeaggregatorImpl.java
new file mode 100644
index 0000000..5660644
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisDeaggregatorImpl.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.util.CharsetUtil;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.json.JSONObject;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.TpPort;
+import org.onosproject.artemis.ArtemisDeaggregator;
+import org.onosproject.artemis.ArtemisEventListener;
+import org.onosproject.artemis.ArtemisMoasAgent;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.onosproject.artemis.ArtemisService;
+import org.onosproject.artemis.BgpSpeakers;
+import org.onosproject.artemis.impl.bgpspeakers.QuaggaBgpSpeakers;
+import org.onosproject.artemis.impl.moas.MoasClientController;
+import org.onosproject.artemis.impl.moas.MoasServerController;
+import org.onosproject.artemis.impl.objects.ArtemisMessage;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.intf.InterfaceService;
+import org.onosproject.ovsdb.controller.OvsdbBridge;
+import org.onosproject.ovsdb.controller.OvsdbClientService;
+import org.onosproject.ovsdb.controller.OvsdbController;
+import org.onosproject.ovsdb.controller.OvsdbInterface;
+import org.onosproject.routing.bgp.BgpInfoService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.onlab.packet.Ethernet.TYPE_IPV4;
+
+@Component(immediate = true)
+@Service
+public class ArtemisDeaggregatorImpl implements ArtemisDeaggregator {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final int PRIORITY = 1000;
+
+ /* Services */
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private BgpInfoService bgpInfoService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private ArtemisService artemisService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private OvsdbController ovsdbController;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private InterfaceService interfaceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private FlowRuleService flowRuleService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private CoreService coreService;
+
+ /* Variables */
+ private Set<BgpSpeakers> bgpSpeakers = Sets.newHashSet();
+ private MoasServerController moasServer;
+
+ private Port tunnelPort = null;
+ private ApplicationId appId;
+
+ private IpAddress remoteTunnelIp = null;
+ private IpPrefix remotePrefix = null;
+ private boolean rulesInstalled;
+
+ /* Agent */
+ private InternalMoasAgent moasAgent = new InternalMoasAgent();
+ private InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
+ private InternalDeviceListener deviceListener = new InternalDeviceListener();
+
+ private Set<MoasClientController> moasClientControllers = Sets.newConcurrentHashSet();
+
+ private final ArtemisEventListener artemisEventListener = this::handleArtemisEvent;
+
+ @Activate
+ protected void activate() {
+ rulesInstalled = false;
+
+ // FIXME: add other type of BGP Speakers when Dynamic Configuration is available
+ bgpSpeakers.add(new QuaggaBgpSpeakers(bgpInfoService));
+
+ moasServer = new MoasServerController();
+ moasServer.start(moasAgent, packetProcessor);
+
+ deviceService.addListener(deviceListener);
+
+ appId = coreService.getAppId("org.onosproject.artemis");
+
+ // enable OVSDB for the switches that we will install the GRE tunnel
+ artemisService.getConfig().ifPresent(config -> config.moasInfo().getTunnelPoints()
+ .forEach(tunnelPoint -> ovsdbController.connect(tunnelPoint.getOvsdbIp(), TpPort.tpPort(6640)))
+ );
+
+ artemisService.addListener(artemisEventListener);
+
+ log.info("Artemis Deaggregator Service Started");
+
+ /*
+ log.info("interfaces {}", interfaceService.getInterfaces());
+
+ [{
+ "name": "",
+ "connectPoint": "of:000000000000000a/2",
+ "ipAddresses": "[1.1.1.1/30]",
+ "macAddress": "00:00:00:00:00:01"
+ },
+ {
+ "name": "",
+ "connectPoint": "of:000000000000000a/3",
+ "ipAddresses": "[10.0.0.1/8]",
+ "macAddress": "00:00:00:00:00:01"
+ }]
+ */
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ moasServer.stop();
+
+ moasClientControllers.forEach(MoasClientController::stop);
+ moasClientControllers.clear();
+
+ flowRuleService.removeFlowRulesById(appId);
+ deviceService.removeListener(deviceListener);
+
+ remoteTunnelIp = null;
+ remotePrefix = null;
+ tunnelPort = null;
+
+ artemisService.removeListener(artemisEventListener);
+
+ log.info("Artemis Deaggregator Service Stopped");
+ }
+
+ /**
+ * Create a GRE tunnel interface pointing to remote MOAS.
+ *
+ * @param remoteIp remote ip on GRE tunnel
+ */
+ private void createTunnelInterface(IpAddress remoteIp) {
+ ovsdbController.getNodeIds().forEach(nodeId -> artemisService.getConfig().flatMap(config ->
+ config.moasInfo().getTunnelPoints()
+ .stream()
+ .filter(tunnelPoint -> tunnelPoint.getOvsdbIp().toString().equals(nodeId.getIpAddress()))
+ .findFirst()
+ ).ifPresent(tunnelPoint -> {
+ OvsdbClientService ovsdbClient = ovsdbController.getOvsdbClient(nodeId);
+ ovsdbClient.dropInterface("gre-int");
+ Map<String, String> options = Maps.newHashMap();
+ options.put("remote_ip", remoteIp.toString());
+ OvsdbInterface ovsdbInterface = OvsdbInterface.builder()
+ .name("gre-int")
+ .options(options)
+ .type(OvsdbInterface.Type.GRE)
+ .build();
+ OvsdbBridge mainBridge = ovsdbClient.getBridges().iterator().next();
+ ovsdbClient.createInterface(mainBridge.name(), ovsdbInterface);
+ log.info("Tunnel setup at {} - {}", nodeId, tunnelPoint);
+ }));
+ }
+
+ /**
+ * Install rules.
+ */
+ private void installRules() {
+ log.info("Remote Data {} - {} - {}", tunnelPort, remoteTunnelIp, remotePrefix);
+ // FIXME: currently works only for a simple pair of client-server
+ if (!rulesInstalled && tunnelPort != null && remoteTunnelIp != null) {
+ if (remotePrefix != null) {
+ installServerRules();
+ } else {
+ installClientRules();
+ }
+ rulesInstalled = true;
+ }
+ }
+
+ /**
+ * Rules to be installed on MOAS Client.
+ */
+ private void installClientRules() {
+ log.info("installClientRules");
+ artemisService.getConfig().ifPresent(config -> {
+ // selector
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(TYPE_IPV4)
+ .matchIPSrc(remoteTunnelIp.toIpPrefix())
+ .matchIPDst(config.moasInfo().getTunnelPoint().getLocalIp().toIpPrefix())
+ .build();
+ // treatment
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.LOCAL)
+ .build();
+ // forwarding objective builder
+ ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(PRIORITY)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .add();
+ // send flow objective to specified switch
+ flowObjectiveService.forward(DeviceId.deviceId(tunnelPort.element().id().toString()),
+ forwardingObjective);
+
+ log.info("Installing flow rule = {}", forwardingObjective);
+ });
+ }
+
+ /**
+ * Rules to be isntalled on MOAS Server.
+ */
+ private void installServerRules() {
+ log.info("installServerRules");
+ artemisService.getConfig().ifPresent(config -> {
+ // selector
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(TYPE_IPV4)
+ .matchIPDst(remotePrefix)
+ .build();
+ // treatment
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(tunnelPort.number())
+ .build();
+ // forwarding objective builder
+ ForwardingObjective forwardingObjective = DefaultForwardingObjective.builder()
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(PRIORITY)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .add();
+ // send flow objective to specified switch
+ flowObjectiveService.forward(DeviceId.deviceId(tunnelPort.element().id().toString()),
+ forwardingObjective);
+
+ log.info("Installing flow rule = {}", forwardingObjective);
+
+ // selector
+ selector = DefaultTrafficSelector.builder()
+ .matchEthType(TYPE_IPV4)
+ .matchIPSrc(config.moasInfo().getTunnelPoint().getLocalIp().toIpPrefix())
+ .matchIPDst(remoteTunnelIp.toIpPrefix())
+ .build();
+ // treatment
+ treatment = DefaultTrafficTreatment.builder()
+ // FIXME: find a better way
+ .setOutput(PortNumber.portNumber(2))
+ .build();
+ // forwarding objective builder
+ forwardingObjective = DefaultForwardingObjective.builder()
+ .withSelector(selector)
+ .withTreatment(treatment)
+ .withPriority(PRIORITY)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .add();
+ // send flow objective to specified switch
+ flowObjectiveService.forward(DeviceId.deviceId(tunnelPort.element().id().toString()),
+ forwardingObjective);
+
+ log.info("Installing flow rule = {}", forwardingObjective);
+ });
+ }
+
+ /**
+ * Handles a artemis event.
+ *
+ * @param event the artemis event
+ */
+ protected void handleArtemisEvent(ArtemisEvent event) {
+ if (event.type().equals(ArtemisEvent.Type.HIJACK_ADDED)) {
+ IpPrefix receivedPrefix = (IpPrefix) event.subject();
+
+ log.info("Deaggregator received a prefix " + receivedPrefix.toString());
+
+ // can only de-aggregate /23 subnets and higher
+ int cidr = receivedPrefix.prefixLength();
+ if (receivedPrefix.prefixLength() < 24) {
+ byte[] octets = receivedPrefix.address().toOctets();
+ int byteGroup = (cidr + 1) / 8,
+ bitPos = 8 - (cidr + 1) % 8;
+
+ octets[byteGroup] = (byte) (octets[byteGroup] & ~(1 << bitPos));
+ String low = IpPrefix.valueOf(IpAddress.Version.INET, octets, cidr + 1).toString();
+ octets[byteGroup] = (byte) (octets[byteGroup] | (1 << bitPos));
+ String high = IpPrefix.valueOf(IpAddress.Version.INET, octets, cidr + 1).toString();
+
+ String[] prefixes = {low, high};
+ bgpSpeakers.forEach(bgpSpeakers -> bgpSpeakers.announceSubPrefixes(prefixes));
+ } else {
+ log.warn("Initiating MOAS");
+
+ artemisService.getConfig().ifPresent(config -> config.monitoredPrefixes().forEach(artemisPrefixes -> {
+ log.info("checking if {} > {}", artemisPrefixes.prefix(), receivedPrefix);
+ if (artemisPrefixes.prefix().contains(receivedPrefix)) {
+ artemisPrefixes.moas().forEach(moasAddress -> {
+ log.info("Creating a client for {}", moasAddress);
+ MoasClientController client = new MoasClientController(
+ packetProcessor,
+ moasAddress,
+ config.moasInfo().getTunnelPoints().iterator().next()
+ .getLocalIp(),
+ receivedPrefix);
+ log.info("Running client");
+ client.run();
+ moasClientControllers.add(client);
+ }
+ );
+ }
+ }
+ ));
+ }
+
+ }
+ }
+
+ private class InternalPacketProcessor implements ArtemisPacketProcessor {
+ @Override
+ public void processMoasPacket(ArtemisMessage msg, ChannelHandlerContext ctx) {
+ log.info("Received {}", msg);
+ switch (msg.getType()) {
+ case INITIATE_FROM_CLIENT: {
+ artemisService.getConfig().ifPresent(config -> {
+ // SERVER SIDE CODE
+ createTunnelInterface(IpAddress.valueOf(msg.getLocalIp()));
+
+ ArtemisMessage message = new ArtemisMessage();
+ message.setType(ArtemisMessage.Type.INITIATE_FROM_SERVER);
+ message.setLocalIp(
+ config.moasInfo().getTunnelPoints()
+ .iterator()
+ .next()
+ .getLocalIp()
+ .toString());
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ String jsonInString = mapper.writeValueAsString(message);
+ ByteBuf buffer = Unpooled.copiedBuffer(jsonInString, CharsetUtil.UTF_8);
+ ctx.writeAndFlush(buffer);
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ log.warn(ExceptionUtils.getFullStackTrace(e));
+ }
+
+ remoteTunnelIp = IpAddress.valueOf(msg.getLocalIp());
+ remotePrefix = IpPrefix.valueOf(msg.getLocalPrefix());
+ });
+ break;
+ }
+ case INITIATE_FROM_SERVER: {
+ // CLIENT SIDE CODE
+ createTunnelInterface(IpAddress.valueOf(msg.getLocalIp()));
+
+ remoteTunnelIp = IpAddress.valueOf(msg.getLocalIp());
+
+ break;
+ }
+ default:
+ }
+
+ installRules();
+ }
+
+ @Override
+ public void processMonitorPacket(JSONObject msg) {
+
+ }
+ }
+
+ private class InternalMoasAgent implements ArtemisMoasAgent {
+
+ @Override
+ public void addMoas(IpAddress ipAddress, ChannelHandlerContext ctx) {
+ Optional<ArtemisConfig> config = artemisService.getConfig();
+ if (config.isPresent() && config.get().moasInfo().getMoasAddresses().contains(ipAddress)) {
+ log.info("Received Moas request from legit IP address");
+ } else {
+ log.info("Received Moas request from unknown IP address; ignoring..");
+ ctx.close();
+ }
+ }
+
+ @Override
+ public void removeMoas(IpAddress ipAddress) {
+
+ }
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+
+ /*
+ EVENT
+ DefaultDevice{id=of:000000000000000a, type=SWITCH, manufacturer=Nicira, Inc., hwVersion=Open vSwitch,
+ swVersion=2.8.0, serialNumber=None, driver=ovs}
+ DefaultPort{element=of:000000000000000a, number=5, isEnabled=true, type=COPPER, portSpeed=0, annotations=
+ {portMac=96:13:4c:12:ca:8a, portName=gre-int}}
+ */
+ @Override
+ public void event(DeviceEvent event) {
+ switch (event.type()) {
+ case PORT_UPDATED:
+ case PORT_ADDED: {
+ log.info("event {}", event);
+ // FIXME: currently only one tunnel is supported
+ if (event.port().annotations().keys().contains("portName") &&
+ event.port().annotations().value("portName").equals("gre-int")) {
+ tunnelPort = event.port();
+
+ installRules();
+ }
+ }
+ default:
+ }
+ }
+ }
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisDetectorImpl.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisDetectorImpl.java
new file mode 100644
index 0000000..09a8d2c
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisDetectorImpl.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.artemis.ArtemisDetector;
+import org.onosproject.artemis.ArtemisEventListener;
+import org.onosproject.artemis.ArtemisService;
+import org.onosproject.core.CoreService;
+import org.onosproject.event.EventDeliveryService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(immediate = true)
+@Service
+public class ArtemisDetectorImpl implements ArtemisDetector {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ /* Services */
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private ArtemisService artemisService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected EventDeliveryService eventDispatcher;
+
+ private final ArtemisEventListener artemisEventListener = this::handleArtemisEvent;
+
+ @Activate
+ protected void activate() {
+ artemisService.addListener(artemisEventListener);
+ log.info("Artemis Detector Service Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ artemisService.removeListener(artemisEventListener);
+ log.info("Artemis Detector Service Stopped");
+ }
+
+ /**
+ * Handles a artemis event.
+ *
+ * @param event the artemis event
+ */
+ void handleArtemisEvent(ArtemisEvent event) {
+ // If an instance was deactivated, check whether we need to roll back the upgrade.
+ if (event.type().equals(ArtemisEvent.Type.BGPUPDATE_ADDED)) {
+ JSONObject take = (JSONObject) event.subject();
+
+ log.info("Received information about monitored prefix " + take.toString());
+ artemisService.getConfig().ifPresent(config ->
+ config.monitoredPrefixes().forEach(artemisPrefix -> {
+ try {
+ IpPrefix prefix = artemisPrefix.prefix(), receivedPrefix;
+
+ receivedPrefix = IpPrefix.valueOf(take.getString("prefix"));
+
+ if (prefix.contains(receivedPrefix)) {
+ JSONArray path = take.getJSONArray("path");
+
+ int state = artemisPrefix.checkPath(path);
+ if (state >= 100) {
+ log.info("BGP Hijack detected; pushing prefix for hijack Deaggregation");
+ eventDispatcher.post(new ArtemisEvent(ArtemisEvent.Type.HIJACK_ADDED,
+ receivedPrefix));
+ } else {
+ log.info("BGP Update is legit");
+ }
+ }
+ } catch (JSONException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+ })
+ );
+ }
+ }
+
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisEvent.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisEvent.java
new file mode 100644
index 0000000..38deac7
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisEvent.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.event.AbstractEvent;
+
+import java.util.Objects;
+
+/**
+ * Artemis event.
+ */
+public class ArtemisEvent extends AbstractEvent<ArtemisEvent.Type, Object> {
+
+ /**
+ * Creates an event of a given type and for the specified state and the
+ * current time.
+ *
+ * @param type upgrade event type
+ * @param subject upgrade state
+ */
+ protected ArtemisEvent(Type type, Object subject) {
+ super(type, subject);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified state and time.
+ *
+ * @param type upgrade event type
+ * @param subject upgrade state
+ * @param time occurrence time
+ */
+ protected ArtemisEvent(Type type, Object subject, long time) {
+ super(type, subject, time);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), subject(), time());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ArtemisEvent) {
+ final ArtemisEvent other = (ArtemisEvent) obj;
+ return Objects.equals(this.type(), other.type()) &&
+ Objects.equals(this.subject(), other.subject()) &&
+ Objects.equals(this.time(), other.time());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this.getClass())
+ .add("type", type())
+ .add("subject", subject())
+ .add("time", time())
+ .toString();
+ }
+
+ /**
+ * Type of artemis-related events.
+ */
+ public enum Type {
+
+ /**
+ * Indicates that a hijack was detected.
+ */
+ HIJACK_ADDED,
+
+ /**
+ * Indicates that a bgp update message was received.
+ */
+ BGPUPDATE_ADDED,
+ }
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisManager.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisManager.java
index 8d10d2e..c714b05 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisManager.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,41 +13,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.onosproject.artemis.impl;
-import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onosproject.artemis.ArtemisEventListener;
+import org.onosproject.artemis.ArtemisService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.event.AbstractListenerManager;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.routing.bgp.BgpInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.Map;
import java.util.Optional;
-import java.util.Set;
-import java.util.Timer;
-/**
- * Artemis Component.
- */
@Component(immediate = true)
@Service
-public class ArtemisManager implements ArtemisService {
+public class ArtemisManager
+ extends AbstractListenerManager<ArtemisEvent, ArtemisEventListener>
+ implements ArtemisService {
+
private static final String ARTEMIS_APP_ID = "org.onosproject.artemis";
private static final Class<ArtemisConfig> CONFIG_CLASS = ArtemisConfig.class;
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private final InternalNetworkConfigListener configListener =
+ new InternalNetworkConfigListener();
+ /* Services */
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private NetworkConfigRegistry registry;
@@ -57,21 +60,12 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
private CoreService coreService;
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- private BgpInfoService bgpInfoService;
-
- private final Logger log = LoggerFactory.getLogger(getClass());
-
+ /* Variables */
private ApplicationId appId;
- public static boolean logging = false;
+ private ArtemisConfig artemisConfig;
- private Set<PrefixHandler> prefixHandlers = Sets.newHashSet();
- private Deaggregator deaggr;
- private Timer timer;
- private final InternalNetworkConfigListener configListener =
- new InternalNetworkConfigListener();
-
+ /* Config */
private ConfigFactory<ApplicationId, ArtemisConfig> artemisConfigFactory =
new ConfigFactory<ApplicationId, ArtemisConfig>(
SubjectFactories.APP_SUBJECT_FACTORY, ArtemisConfig.class, "artemis") {
@@ -86,72 +80,25 @@
appId = coreService.registerApplication(ARTEMIS_APP_ID);
configService.addListener(configListener);
registry.registerConfigFactory(artemisConfigFactory);
- log.info("Artemis Started");
+
+ eventDispatcher.addSink(ArtemisEvent.class, listenerRegistry);
+
+ log.info("Artemis Service Started");
}
@Deactivate
protected void deactivate() {
configService.removeListener(configListener);
registry.unregisterConfigFactory(artemisConfigFactory);
- prefixHandlers.forEach(PrefixHandler::stopPrefixMonitors);
- log.info("Artemis Stopped");
- }
- /**
- * Helper function to start and stop monitors on configuration changes.
- */
- private void setUpConfiguration() {
- ArtemisConfig config = configService.getConfig(appId, CONFIG_CLASS);
+ eventDispatcher.removeSink(ArtemisEvent.class);
- if (config == null) {
- log.warn("No artemis config available!");
- return;
- }
-
- final Set<ArtemisConfig.ArtemisPrefixes> prefixes = config.monitoredPrefixes();
- final Integer frequency = config.detectionFrequency();
- final Map<String, Set<String>> monitors = config.activeMonitors();
-
- Set<PrefixHandler> toRemove = Sets.newHashSet(prefixHandlers);
-
- for (ArtemisConfig.ArtemisPrefixes curr : prefixes) {
- final Optional<PrefixHandler> handler = prefixHandlers
- .stream()
- .filter(prefixHandler -> prefixHandler.getPrefix().equals(curr.prefix()))
- .findFirst();
-
- if (handler.isPresent()) {
- PrefixHandler oldHandler = handler.get();
- oldHandler.changeMonitors(monitors);
-
- // remove the ones we are going to keep from toRemove list
- toRemove.remove(oldHandler);
- } else {
- // Add new handler
- PrefixHandler newHandler = new PrefixHandler(curr.prefix(), monitors);
- newHandler.startPrefixMonitors();
- prefixHandlers.add(newHandler);
- }
- }
-
- // stop and remove old monitors that do not exist on new configuration
- toRemove.forEach(PrefixHandler::stopPrefixMonitors);
- prefixHandlers.removeAll(toRemove);
-
- // new timer task with updated bgp speakers
- deaggr = new Deaggregator(bgpInfoService);
- deaggr.setPrefixes(prefixes);
-
- if (timer != null) {
- timer.cancel();
- }
- timer = new Timer();
- timer.scheduleAtFixedRate(deaggr, frequency, frequency);
+ log.info("Artemis Service Stopped");
}
@Override
- public void setLogger(boolean value) {
- logging = value;
+ public Optional<ArtemisConfig> getConfig() {
+ return Optional.ofNullable(artemisConfig);
}
private class InternalNetworkConfigListener implements NetworkConfigListener {
@@ -160,19 +107,27 @@
public void event(NetworkConfigEvent event) {
switch (event.type()) {
case CONFIG_REGISTERED:
+ case CONFIG_UNREGISTERED: {
break;
- case CONFIG_UNREGISTERED:
- break;
- case CONFIG_ADDED:
- case CONFIG_UPDATED:
- case CONFIG_REMOVED:
+ }
+ case CONFIG_REMOVED: {
if (event.configClass() == CONFIG_CLASS) {
- setUpConfiguration();
+ artemisConfig = null;
}
break;
+ }
+ case CONFIG_UPDATED:
+ case CONFIG_ADDED: {
+ if (event.configClass() == CONFIG_CLASS) {
+ event.config().ifPresent(config -> artemisConfig = (ArtemisConfig) config);
+ }
+ break;
+ }
default:
break;
}
}
+
}
+
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisMonitorImpl.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisMonitorImpl.java
new file mode 100755
index 0000000..1f4d757
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/ArtemisMonitorImpl.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl;
+
+import com.google.common.collect.Sets;
+import io.netty.channel.ChannelHandlerContext;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.json.JSONObject;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.artemis.ArtemisMonitor;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.onosproject.artemis.impl.objects.ArtemisMessage;
+import org.onosproject.event.EventDeliveryService;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Component(immediate = true)
+@Service
+public class ArtemisMonitorImpl implements ArtemisMonitor {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final Class<ArtemisConfig> CONFIG_CLASS = ArtemisConfig.class;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected EventDeliveryService eventDispatcher;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private NetworkConfigService configService;
+
+ /* Variables */
+ private Set<PrefixHandler> prefixHandlers = Sets.newHashSet();
+ private InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
+
+ private final InternalNetworkConfigListener configListener =
+ new InternalNetworkConfigListener();
+
+ @Activate
+ protected void activate() {
+ configService.addListener(configListener);
+ log.info("Artemis Monitor Service Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ configService.removeListener(configListener);
+ prefixHandlers.forEach(PrefixHandler::stopPrefixMonitors);
+ prefixHandlers.clear();
+
+ log.info("Artemis Monitor Service Stopped");
+ }
+
+ private class InternalPacketProcessor implements ArtemisPacketProcessor {
+
+ @Override
+ public void processMoasPacket(ArtemisMessage msg, ChannelHandlerContext ctx) {
+
+ }
+
+ @Override
+ public void processMonitorPacket(JSONObject msg) {
+ // TODO: in future maybe store the BGP Update message and propagate it to the cluster instead of Events
+ eventDispatcher.post(new ArtemisEvent(ArtemisEvent.Type.BGPUPDATE_ADDED, msg));
+ }
+ }
+
+ private class InternalNetworkConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ switch (event.type()) {
+ case CONFIG_REGISTERED:
+ case CONFIG_UNREGISTERED: {
+ break;
+ }
+ case CONFIG_REMOVED: {
+ if (event.configClass() == CONFIG_CLASS) {
+ prefixHandlers.forEach(PrefixHandler::stopPrefixMonitors);
+ prefixHandlers.clear();
+ }
+ break;
+ }
+ case CONFIG_UPDATED:
+ case CONFIG_ADDED: {
+ if (event.configClass() == CONFIG_CLASS) {
+ event.config().ifPresent(config -> {
+ ArtemisConfig artemisConfig = (ArtemisConfig) config;
+ Set<IpPrefix> ipPrefixes = artemisConfig.prefixesToMonitor();
+ Map<String, Set<String>> monitors = artemisConfig.activeMonitors();
+
+ prefixHandlers.forEach(PrefixHandler::stopPrefixMonitors);
+ prefixHandlers.clear();
+ prefixHandlers = ipPrefixes.stream()
+ .map(prefix -> new PrefixHandler(prefix, monitors, packetProcessor))
+ .collect(Collectors.toSet());
+
+ prefixHandlers.forEach(PrefixHandler::startPrefixMonitors);
+ });
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ }
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/DataHandler.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/DataHandler.java
deleted file mode 100644
index e4eb2cf..0000000
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/DataHandler.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * 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.artemis.impl;
-
-import org.json.JSONObject;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Helper class that handles BGP Update messages.
- */
-public final class DataHandler {
- private static final File DATA_FILE = new File("data.json");
- private static final File HIJACKS_FILE = new File("hijack.json");
-
- private final AtomicReference<ArrayList<JSONObject>> data = new AtomicReference<ArrayList<JSONObject>>();
-
- private static DataHandler instance = new DataHandler();
-
- private DataHandler() {
- data.set(new ArrayList<>());
- }
-
- /**
- * Singleton for data handler class.
- *
- * @return instance of class
- */
- public static synchronized DataHandler getInstance() {
- if (instance == null) {
- instance = new DataHandler();
- }
- return instance;
- }
-
- /**
- * Atomic append a BGP update message to a list.
- *
- * @param obj BGP update message
- */
- public synchronized void appendData(JSONObject obj) {
- data.get().add(obj);
- }
-
- /**
- * Atomic read and clear a list of BGP updates.
- *
- * @return list of messages that received in 'threshold' period
- */
- synchronized ArrayList<JSONObject> getData() {
- ArrayList<JSONObject> tmp = (ArrayList<JSONObject>) data.get().clone();
- data.get().clear();
- return tmp;
- }
-
- /**
- * A serializer to write incoming BGP updates and hijack attempts to json files.
- */
- public static class Serializer {
- private static RandomAccessFile fwData, fwHijack;
- private static long lengthData, lengthHijack;
-
- static {
- try {
- if (DATA_FILE.exists()) {
- fwData = new RandomAccessFile(DATA_FILE, "rw");
- } else {
- fwData = new RandomAccessFile(DATA_FILE, "rw");
- fwData.writeBytes("[\n]");
- }
- lengthData = fwData.length() - 1;
-
- if (HIJACKS_FILE.exists()) {
- fwHijack = new RandomAccessFile(HIJACKS_FILE, "rw");
- } else {
- fwHijack = new RandomAccessFile(HIJACKS_FILE, "rw");
- fwHijack.writeBytes("[\n]");
- }
- lengthHijack = fwHijack.length() - 1;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Writes BGP update to json file.
- *
- * @param data BGP update
- */
- public static synchronized void writeData(Object data) {
- try {
- String entry = data.toString() + ",\n]";
- fwData.seek(lengthData);
- fwData.writeBytes(entry);
- lengthData += entry.length() - 1;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Writes detected BGP hijack to json file.
- *
- * @param data BGP update of hijack
- */
- static synchronized void writeHijack(Object data) {
- try {
- String entry = data.toString() + ",\n]";
- fwHijack.seek(lengthHijack);
- fwHijack.writeBytes(entry);
- lengthHijack += entry.length() - 1;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/Deaggregator.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/Deaggregator.java
deleted file mode 100644
index b78ade1..0000000
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/Deaggregator.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * 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.artemis.impl;
-
-import com.google.common.collect.Sets;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.artemis.impl.bgpspeakers.BgpSpeakers;
-import org.onosproject.artemis.impl.bgpspeakers.QuaggaBgpSpeakers;
-import org.onosproject.routing.bgp.BgpInfoService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Set;
-
-/**
- * Timertask class which detects and mitigates BGP hijacks.
- */
-class Deaggregator extends java.util.TimerTask {
-
- private final Logger log = LoggerFactory.getLogger(getClass());
- private Set<ArtemisConfig.ArtemisPrefixes> prefixes = Sets.newHashSet();
- private Set<BgpSpeakers> bgpSpeakers = Sets.newHashSet();
-
- Deaggregator(BgpInfoService bgpInfoService) {
- super();
- // deaggregator must know the type of the connected BGP speakers and the BGP info.
- // for this example we only have one Quagga BGP speaker.
- bgpSpeakers.add(new QuaggaBgpSpeakers(bgpInfoService));
- }
-
- @Override
- public void run() {
- ArrayList<JSONObject> messagesArray = DataHandler.getInstance().getData();
-// log.info("Messages size: " + messagesArray.size());
-
- // Example of BGP Update message:
- // {
- // "path":[65001, 65002, 65004], (origin being last)
- // "prefix":"12.0.0.0/8",
- // }
-
- prefixes.forEach(prefix -> {
- IpPrefix monitoredPrefix = prefix.prefix();
-
- // for each update message in memory check for hijack
- for (JSONObject tmp : messagesArray) {
- IpPrefix receivedPrefix = null;
- try {
- receivedPrefix = IpPrefix.valueOf(tmp.getString("prefix"));
- } catch (JSONException e) {
- log.warn("JSONException: " + e.getMessage());
- e.printStackTrace();
- }
- if (receivedPrefix == null) {
- continue;
- }
-
- // check if the announced network address is inside our subnet
- if (monitoredPrefix.contains(receivedPrefix)) {
- JSONArray path = null;
- try {
- path = tmp.getJSONArray("path");
- } catch (JSONException e) {
- log.warn("JSONException: " + e.getMessage());
- e.printStackTrace();
- }
- if (path == null) {
- continue;
- }
-
- int state = prefix.checkPath(path);
- if (state >= 100) {
- log.warn("BGP Hijack detected of type " +
- (state - 100) + "\n" + tmp.toString());
- DataHandler.Serializer.writeHijack(tmp);
- // can only de-aggregate /23 subnets and higher
- int cidr = receivedPrefix.prefixLength();
- if (receivedPrefix.prefixLength() < 24) {
- byte[] octets = receivedPrefix.address().toOctets();
- int byteGroup = (cidr + 1) / 8,
- bitPos = 8 - (cidr + 1) % 8;
-
- octets[byteGroup] = (byte) (octets[byteGroup] & ~(1 << bitPos));
- String low = IpPrefix.valueOf(IpAddress.Version.INET, octets, cidr + 1).toString();
- octets[byteGroup] = (byte) (octets[byteGroup] | (1 << bitPos));
- String high = IpPrefix.valueOf(IpAddress.Version.INET, octets, cidr + 1).toString();
-
- String[] prefixes = {low, high};
- bgpSpeakers.forEach(bgpSpeakers -> bgpSpeakers.announceSubPrefixes(prefixes));
- } else {
- log.warn("Cannot announce smaller prefix than /24");
- }
- }
- }
- }
- });
- }
-
- public Set<ArtemisConfig.ArtemisPrefixes> getPrefixes() {
- return prefixes;
- }
-
- public void setPrefixes(Set<ArtemisConfig.ArtemisPrefixes> prefixes) {
- this.prefixes = prefixes;
- }
-}
\ No newline at end of file
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/PrefixHandler.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/PrefixHandler.java
index 57553b5..6fa407e 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/PrefixHandler.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/PrefixHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,12 +15,12 @@
*/
package org.onosproject.artemis.impl;
-import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onlab.packet.IpPrefix;
-import org.onosproject.artemis.impl.monitors.ExaBgpMonitor;
-import org.onosproject.artemis.impl.monitors.Monitor;
-import org.onosproject.artemis.impl.monitors.RipeMonitor;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.onosproject.artemis.Monitors;
+import org.onosproject.artemis.impl.monitors.ExaBgpMonitors;
+import org.onosproject.artemis.impl.monitors.RipeMonitors;
import java.util.Map;
import java.util.Objects;
@@ -33,22 +33,23 @@
class PrefixHandler {
private IpPrefix prefix;
- private Set<Monitor> prefixMonitors = Sets.newHashSet();
+ private Set<Monitors> prefixMonitors = Sets.newHashSet();
/**
* Constructor that takes a CIDR-notation string and a list of monitors.
*
- * @param prefix A CIDR-notation string, e.g. "192.168.0.1/24"
- * @param monitors A map of strings to a set of string for monitors, e.g. "ripe", ["host1","host2",..]
+ * @param prefix A CIDR-notation string, e.g. "192.168.0.1/24"
+ * @param monitors A map of strings to a set of string for monitors, e.g. "ripe", ["host1","host2",..]
+ * @param packetProcessor Packet processor
*/
- PrefixHandler(IpPrefix prefix, Map<String, Set<String>> monitors) {
+ PrefixHandler(IpPrefix prefix, Map<String, Set<String>> monitors, ArtemisPacketProcessor packetProcessor) {
this.prefix = prefix;
monitors.forEach((type, values) -> {
- if (type.equals(Monitor.Types.RIPE.toString())) {
- values.forEach(host -> prefixMonitors.add(new RipeMonitor(prefix, host)));
- } else if (type.equals(Monitor.Types.EXABGP.toString())) {
- values.forEach(host -> prefixMonitors.add(new ExaBgpMonitor(prefix, host)));
+ if (Monitors.Types.getEnum(type).equals(Monitors.Types.RIPE)) {
+ values.forEach(host -> prefixMonitors.add(new RipeMonitors(prefix, host, packetProcessor)));
+ } else if (Monitors.Types.getEnum(type).equals(Monitors.Types.EXABGP)) {
+ values.forEach(host -> prefixMonitors.add(new ExaBgpMonitors(prefix, host, packetProcessor)));
}
});
}
@@ -57,14 +58,14 @@
* Start all monitors for this prefix.
*/
void startPrefixMonitors() {
- prefixMonitors.forEach(Monitor::startMonitor);
+ prefixMonitors.forEach(Monitors::startMonitor);
}
/**
* Stop all monitors for this prefix.
*/
void stopPrefixMonitors() {
- prefixMonitors.forEach(Monitor::stopMonitor);
+ prefixMonitors.forEach(Monitors::stopMonitor);
}
/**
@@ -76,61 +77,20 @@
return prefix;
}
- /**
- * Changes the monitors based on the new list given.
- *
- * @param newMonitors monitors to be added
- */
- void changeMonitors(Map<String, Set<String>> newMonitors) {
- Set<String> newTypes = newMonitors.keySet();
- Set<Monitor> monToRemove = Sets.newHashSet();
- Map<String, Set<String>> monToAdd = Maps.newHashMap(newMonitors);
-
- prefixMonitors.forEach(monitor -> {
- String oldType = monitor.getType().toString();
- if (newTypes.contains(oldType)) {
- Set<String> newHosts = newMonitors.get(oldType);
- String oldHost = monitor.getHost();
- if (newHosts.contains(oldHost)) {
- monToAdd.remove(oldHost, oldHost);
- } else {
- monToRemove.add(monitor);
- }
- } else {
- monToRemove.add(monitor);
- }
- });
-
- monToRemove.forEach(Monitor::stopMonitor);
- prefixMonitors.removeAll(monToRemove);
-
- //TODO
- monToAdd.forEach((type, values) -> {
- if (type.equals(Monitor.Types.RIPE.toString())) {
- values.forEach(host -> prefixMonitors.add(new RipeMonitor(prefix, host)));
- } else if (type.equals(Monitor.Types.EXABGP.toString())) {
- values.forEach(host -> prefixMonitors.add(new ExaBgpMonitor(prefix, host)));
- }
- });
-
- startPrefixMonitors();
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ PrefixHandler that = (PrefixHandler) o;
+ return Objects.equals(prefix, that.prefix);
}
@Override
public int hashCode() {
- return Objects.hashCode(prefix);
+ return Objects.hash(prefix);
}
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj instanceof PrefixHandler) {
- final PrefixHandler that = (PrefixHandler) obj;
- return Objects.equals(this.prefix, that.prefix);
- }
- return false;
- }
-
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/BgpSpeakers.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/BgpSpeakers.java
deleted file mode 100644
index a3642ed..0000000
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/BgpSpeakers.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2016-present Open Networking Foundation
- *
- * 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.artemis.impl.bgpspeakers;
-
-import org.onosproject.routing.bgp.BgpInfoService;
-import org.onosproject.routing.bgp.BgpSession;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collection;
-
-/**
- * Abstract class for all the types of BGP Speakers.
- */
-public abstract class BgpSpeakers {
-
- final Logger log = LoggerFactory.getLogger(getClass());
- Collection<BgpSession> bgpSessions;
-
- BgpSpeakers(BgpInfoService bgpInfoService) {
- this.bgpSessions = bgpInfoService.getBgpSessions();
- }
-
- /**
- * Abstract function which announces the two new subprefixes on the BGP Speaker.
- * @param prefixes list of two prefixes
- */
- public abstract void announceSubPrefixes(String[] prefixes);
-}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/QuaggaBgpSpeakers.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/QuaggaBgpSpeakers.java
index 462a033..8c95896 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/QuaggaBgpSpeakers.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/QuaggaBgpSpeakers.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,8 +15,12 @@
*/
package org.onosproject.artemis.impl.bgpspeakers;
+import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.net.telnet.TelnetClient;
+import org.onosproject.artemis.BgpSpeakers;
import org.onosproject.routing.bgp.BgpInfoService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.io.PrintStream;
@@ -25,20 +29,23 @@
/**
* Quagga interface to connect and announce prefixes.
*/
-public class QuaggaBgpSpeakers extends BgpSpeakers {
+public class QuaggaBgpSpeakers implements BgpSpeakers {
+ // TODO: move this to configuration
private static final String PASSWORD = "sdnip";
-
+ private final Logger log = LoggerFactory.getLogger(getClass());
private TelnetClient telnet = new TelnetClient();
private InputStream in;
private PrintStream out;
+ private BgpInfoService bgpInfoService;
public QuaggaBgpSpeakers(BgpInfoService bgpInfoService) {
- super(bgpInfoService);
+ this.bgpInfoService = bgpInfoService;
}
@Override
public void announceSubPrefixes(String[] prefixes) {
- bgpSessions.forEach((session) -> {
+ log.info("Announcing subprefixes: {}", (Object[]) prefixes);
+ bgpInfoService.getBgpSessions().forEach((session) -> {
String peerIp = session.remoteInfo().ip4Address().toString(),
localAs = String.valueOf(session.remoteInfo().as4Number());
assert peerIp != null;
@@ -59,7 +66,7 @@
log.info("Announced " + prefixes[0] + " and " + prefixes[1] + " at " + peerIp);
} catch (Exception e) {
- log.warn(e.getMessage());
+ log.error(ExceptionUtils.getFullStackTrace(e));
}
});
}
@@ -85,7 +92,7 @@
ch = (char) in.read();
}
} catch (Exception e) {
- log.warn(e.getMessage());
+ log.error(ExceptionUtils.getFullStackTrace(e));
}
return null;
}
@@ -100,7 +107,7 @@
out.println(value);
out.flush();
} catch (Exception e) {
- log.warn(e.getMessage());
+ log.error(ExceptionUtils.getFullStackTrace(e));
}
}
@@ -108,7 +115,7 @@
* Configure terminal and announce prefix inside the Quagga router.
*
* @param prefixes prefixes to announce
- * @param localAs ASN of BGP Speaker
+ * @param localAs ASN of BGP Speaker
*/
private void announcePrefix(String[] prefixes, String localAs) {
write("en");
@@ -131,7 +138,7 @@
try {
telnet.disconnect();
} catch (Exception e) {
- log.warn(e.getMessage());
+ log.error(ExceptionUtils.getFullStackTrace(e));
}
}
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/package-info.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/package-info.java
index 2dfcb49..4eb19fd 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/package-info.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/bgpspeakers/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasClientController.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasClientController.java
new file mode 100644
index 0000000..fccda3e
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasClientController.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl.moas;
+
+import com.google.common.annotations.Beta;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * MOAS Client Controller.
+ */
+@Beta
+public class MoasClientController {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private IpAddress host;
+ private EventLoopGroup workerGroup;
+ private MoasClientHandler ach;
+ private ChannelFuture channel;
+ private IpAddress localIp;
+ private IpPrefix localPrefix;
+ private ArtemisPacketProcessor packetProcessor;
+
+ public MoasClientController(ArtemisPacketProcessor packetProcessor,
+ IpAddress host, IpAddress localIp, IpPrefix localPrefix) {
+ this.host = host;
+ this.ach = null;
+ this.localIp = localIp;
+ this.localPrefix = localPrefix;
+ this.packetProcessor = packetProcessor;
+ }
+
+ /**
+ * Run the MOAS client.
+ */
+ public void run() {
+ try {
+ final Bootstrap bootstrap = createBootstrap();
+
+ ach = new MoasClientHandler(localIp, localPrefix, packetProcessor);
+
+ bootstrap.handler(new ChannelInitializer<SocketChannel>() {
+ @Override
+ public void initChannel(SocketChannel ch) throws Exception {
+ ch.pipeline().addLast(ach);
+ }
+ });
+
+ channel = bootstrap.connect(host.toInetAddress(), 32323).sync();
+ } catch (Exception e) {
+ log.warn(ExceptionUtils.getFullStackTrace(e));
+ }
+ }
+
+ /**
+ * Bootstrap netty socket.
+ *
+ * @return bootstrap
+ * @throws Exception exception
+ */
+ private Bootstrap createBootstrap() throws Exception {
+ try {
+ workerGroup = new NioEventLoopGroup();
+ return new Bootstrap()
+ .group(workerGroup)
+ .channel(NioSocketChannel.class)
+ .option(ChannelOption.SO_KEEPALIVE, true);
+ } catch (Exception e) {
+ throw new Exception(e);
+ }
+ }
+
+ /**
+ * Stop the MOAS client.
+ */
+ public void stop() {
+ channel.channel().close();
+ workerGroup.shutdownGracefully();
+ }
+
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasClientHandler.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasClientHandler.java
new file mode 100644
index 0000000..58954d9
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasClientHandler.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl.moas;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.annotations.Beta;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.util.CharsetUtil;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.onosproject.artemis.impl.objects.ArtemisMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+
+/**
+ * MOAS Client channel handler.
+ */
+@Sharable
+@Beta
+public class MoasClientHandler extends ChannelInboundHandlerAdapter {
+
+ private static final Logger log =
+ LoggerFactory.getLogger(MoasClientHandler.class);
+
+ private IpAddress localIp;
+ private IpPrefix localPrefix;
+ private ArtemisPacketProcessor packetProcessor;
+
+ MoasClientHandler(IpAddress localIp, IpPrefix localPrefix, ArtemisPacketProcessor packetProcessor) {
+ this.localIp = localIp;
+ this.packetProcessor = packetProcessor;
+ this.localPrefix = localPrefix;
+ }
+
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ log.info("Connected to server {}", ctx.channel().remoteAddress());
+
+ ArtemisMessage message = new ArtemisMessage();
+ message.setType(ArtemisMessage.Type.INITIATE_FROM_CLIENT);
+ message.setLocalIp(localIp.toString());
+ message.setLocalPrefix(localPrefix.toString());
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ String jsonInString = mapper.writeValueAsString(message);
+ ByteBuf buffer = Unpooled.copiedBuffer(jsonInString, CharsetUtil.UTF_8);
+ ctx.writeAndFlush(buffer);
+ } catch (JsonProcessingException e) {
+ e.printStackTrace();
+ log.warn(ExceptionUtils.getFullStackTrace(e));
+ }
+ }
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws IOException {
+ ByteBuf in = (ByteBuf) msg;
+ String strMsg = in.toString(io.netty.util.CharsetUtil.US_ASCII);
+
+ ObjectMapper mapper = new ObjectMapper();
+ ArtemisMessage actObj = mapper.readValue(strMsg, ArtemisMessage.class);
+
+ packetProcessor.processMoasPacket(actObj, ctx);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ log.error(ExceptionUtils.getFullStackTrace(cause));
+ cause.printStackTrace();
+ ctx.close();
+ }
+
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasServerController.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasServerController.java
new file mode 100644
index 0000000..c27a134
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasServerController.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl.moas;
+
+import com.google.common.annotations.Beta;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.artemis.ArtemisMoasAgent;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * MOAS Server Controller.
+ */
+@Beta
+public class MoasServerController {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ protected ArtemisMoasAgent deviceAgent;
+ protected ArtemisPacketProcessor packetAgent;
+
+ private EventLoopGroup bossGroup;
+ private EventLoopGroup workerGroup;
+ private ChannelFuture channel;
+ private int port = 32323;
+
+ private boolean isRunning = false;
+
+ /**
+ * Run the MOAS Servcer.
+ */
+ private void run() {
+ final MoasServerController ctrl = this;
+ try {
+ final ServerBootstrap bootstrap = createServerBootStrap();
+
+ bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
+ @Override
+ public void initChannel(SocketChannel ch) throws Exception {
+ ch.pipeline().addLast(
+ new MoasServerHandler(ctrl)
+ );
+ }
+ });
+
+ channel = bootstrap.bind(port).sync();
+ isRunning = true;
+ } catch (Exception e) {
+ log.warn(ExceptionUtils.getFullStackTrace(e));
+ }
+ }
+
+ /**
+ * Create netty server bootstrap.
+ *
+ * @return bootstrap
+ * @throws Exception exception
+ */
+ private ServerBootstrap createServerBootStrap() throws Exception {
+ try {
+ bossGroup = new NioEventLoopGroup();
+ workerGroup = new NioEventLoopGroup();
+
+ return new ServerBootstrap()
+ .group(bossGroup, workerGroup)
+ .channel(NioServerSocketChannel.class)
+ .option(ChannelOption.SO_REUSEADDR, true)
+ .childOption(ChannelOption.SO_KEEPALIVE, true)
+ .childOption(ChannelOption.TCP_NODELAY, true);
+ } catch (Exception e) {
+ throw new Exception(e);
+ }
+ }
+
+ /**
+ * Start Server Controller and initialize agents.
+ *
+ * @param deviceAgent device agent
+ * @param packetAgent packet agen
+ */
+ public void start(ArtemisMoasAgent deviceAgent, ArtemisPacketProcessor packetAgent) {
+ if (isRunning) {
+ stop();
+ this.deviceAgent = deviceAgent;
+ this.packetAgent = packetAgent;
+ run();
+ } else {
+ this.deviceAgent = deviceAgent;
+ this.packetAgent = packetAgent;
+ run();
+ }
+ isRunning = true;
+ }
+
+ /**
+ * Stop Server Controller.
+ */
+ public void stop() {
+ if (isRunning) {
+ channel.channel().close();
+ bossGroup.shutdownGracefully();
+ workerGroup.shutdownGracefully();
+ isRunning = false;
+ }
+ }
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasServerHandler.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasServerHandler.java
new file mode 100644
index 0000000..d140416
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/MoasServerHandler.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl.moas;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.annotations.Beta;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandler.Sharable;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onlab.packet.IpAddress;
+import org.onosproject.artemis.impl.objects.ArtemisMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+/**
+ * MOAS Server channel handler.
+ */
+@Sharable
+@Beta
+public class MoasServerHandler extends ChannelInboundHandlerAdapter {
+
+ private static final Logger log =
+ LoggerFactory.getLogger(MoasServerHandler.class);
+
+ private MoasServerController controller;
+
+ MoasServerHandler(MoasServerController controller) {
+ this.controller = controller;
+ }
+
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ final SocketAddress address = ctx.channel().remoteAddress();
+ if (!(address instanceof InetSocketAddress)) {
+ log.warn("Invalid client connection. MOAS is identified based on IP");
+ ctx.close();
+ return;
+ }
+
+ final InetSocketAddress inetAddress = (InetSocketAddress) address;
+ final String host = inetAddress.getHostString();
+ log.info("New client connected to the Server: {}", host);
+
+ controller.deviceAgent.addMoas(IpAddress.valueOf(host), ctx);
+ }
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws IOException {
+ ByteBuf in = (ByteBuf) msg;
+ String strMsg = in.toString(io.netty.util.CharsetUtil.US_ASCII);
+
+ ObjectMapper mapper = new ObjectMapper();
+ ArtemisMessage actObj = mapper.readValue(strMsg, ArtemisMessage.class);
+
+ controller.packetAgent.processMoasPacket(actObj, ctx);
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ log.error(ExceptionUtils.getFullStackTrace(cause));
+ cause.printStackTrace();
+ ctx.close();
+ }
+
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/package-info.java
similarity index 82%
copy from apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java
copy to apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/package-info.java
index b2d0dc4..dfe902f 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/moas/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,6 @@
*/
/**
- * Artemis CLI commands.
+ * MOAS related package.
*/
-package org.onosproject.artemis.cli;
\ No newline at end of file
+package org.onosproject.artemis.impl.moas;
\ No newline at end of file
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/ExaBgpMonitor.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/ExaBgpMonitors.java
similarity index 79%
rename from apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/ExaBgpMonitor.java
rename to apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/ExaBgpMonitors.java
index 44019d5..5fb9be4 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/ExaBgpMonitor.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/ExaBgpMonitors.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@
import org.json.JSONException;
import org.json.JSONObject;
import org.onlab.packet.IpPrefix;
-import org.onosproject.artemis.impl.ArtemisManager;
-import org.onosproject.artemis.impl.DataHandler;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.onosproject.artemis.Monitors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,17 +29,19 @@
import java.util.Objects;
/**
- * Implementation of ExaBGP Route Collector Monitor.
+ * Implementation of ExaBGP Route Collector Monitors.
*/
-public class ExaBgpMonitor extends Monitor {
+public class ExaBgpMonitors implements Monitors {
+ private final Logger log = LoggerFactory.getLogger(getClass());
private String host;
private Socket socket;
+ private IpPrefix prefix;
+ private ArtemisPacketProcessor packetProcessor;
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- public ExaBgpMonitor(IpPrefix prefix, String host) {
- super(prefix);
+ public ExaBgpMonitors(IpPrefix prefix, String host, ArtemisPacketProcessor packetProcessor) {
this.host = host;
+ this.prefix = prefix;
+ this.packetProcessor = packetProcessor;
}
/**
@@ -56,22 +58,20 @@
}
}
+ /**
+ * ExaBGP message received on the socket.io.
+ *
+ * @param args exabgp message
+ */
private void onExaMessage(Object[] args) {
JSONObject message = (JSONObject) args[0];
try {
if (message.getString("type").equals("A")) {
- // Write BGP message to a json database
- DataHandler.Serializer.writeData(args[0]);
-
- if (ArtemisManager.logging) {
- log.info(message.toString());
- }
-
// Example of BGP Update message:
// {
// "path":[65001],
- // "peer":"1.1.1.1",
+ // "peer":"1.1.1.s1",
// "prefix":"12.0.0.0/8",
// "host":"exabgp", <-- Can put IP here
// "type":"A",
@@ -85,7 +85,7 @@
message.remove("timestamp");
// Append synchronized message to message list in memory.
- DataHandler.getInstance().appendData(message);
+ packetProcessor.processMonitorPacket(message);
}
} catch (JSONException e) {
e.printStackTrace();
@@ -93,6 +93,16 @@
}
@Override
+ public IpPrefix getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public void setPrefix(IpPrefix prefix) {
+ this.prefix = prefix;
+ }
+
+ @Override
public void startMonitor() {
if (!isRunning()) {
log.info("Starting EXA monitor for " + prefix + " / " + host);
@@ -120,11 +130,6 @@
}
@Override
- public Types getType() {
- return Types.EXABGP;
- }
-
- @Override
public boolean isRunning() {
return this.socket != null;
}
@@ -149,8 +154,8 @@
if (this == obj) {
return true;
}
- if (obj instanceof ExaBgpMonitor) {
- final ExaBgpMonitor that = (ExaBgpMonitor) obj;
+ if (obj instanceof ExaBgpMonitors) {
+ final ExaBgpMonitors that = (ExaBgpMonitors) obj;
return Objects.equals(this.prefix, that.prefix) &&
Objects.equals(this.host, that.host);
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/RipeMonitor.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/RipeMonitors.java
similarity index 82%
rename from apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/RipeMonitor.java
rename to apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/RipeMonitors.java
index 811eece..e848875 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/RipeMonitor.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/RipeMonitors.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,11 +17,12 @@
import io.socket.client.IO;
import io.socket.client.Socket;
+import org.apache.commons.lang.exception.ExceptionUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.onlab.packet.IpPrefix;
-import org.onosproject.artemis.impl.ArtemisManager;
-import org.onosproject.artemis.impl.DataHandler;
+import org.onosproject.artemis.ArtemisPacketProcessor;
+import org.onosproject.artemis.Monitors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,17 +30,19 @@
import java.util.Objects;
/**
- * Implementation of RIPE Route Collector Monitor.
+ * Implementation of RIPE Route Collector Monitors.
*/
-public class RipeMonitor extends Monitor {
+public class RipeMonitors implements Monitors {
+ private final Logger log = LoggerFactory.getLogger(getClass());
private String host;
private Socket socket;
+ private IpPrefix prefix;
+ private ArtemisPacketProcessor packetProcessor;
- private final Logger log = LoggerFactory.getLogger(getClass());
-
- public RipeMonitor(IpPrefix prefix, String host) {
- super(prefix);
+ public RipeMonitors(IpPrefix prefix, String host, ArtemisPacketProcessor packetProcessor) {
+ this.prefix = prefix;
this.host = host;
+ this.packetProcessor = packetProcessor;
}
/**
@@ -64,6 +67,16 @@
}
}
+ @Override
+ public IpPrefix getPrefix() {
+ return prefix;
+ }
+
+ @Override
+ public void setPrefix(IpPrefix prefix) {
+ this.prefix = prefix;
+ }
+
/**
* socket.io onRisMessage event handler.
* This event is custom made that triggers when it receives an BGP update/withdraw for our prefix.
@@ -74,13 +87,6 @@
try {
JSONObject message = (JSONObject) args[0];
if (message.getString("type").equals("A")) {
- // Write BGP message to a json database
- DataHandler.Serializer.writeData(args[0]);
-
- if (ArtemisManager.logging) {
- log.info(message.toString());
- }
-
// Example of BGP Update message:
// {
// "timestamp":1488044022.97,
@@ -101,9 +107,10 @@
message.remove("host");
// Append synchronized message to message list in memory.
- DataHandler.getInstance().appendData(message);
+ packetProcessor.processMonitorPacket(message);
}
} catch (JSONException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
e.printStackTrace();
}
socket.emit("ping");
@@ -122,6 +129,7 @@
this.socket.on(Socket.EVENT_PONG, args -> socket.emit("ping"));
this.socket.on("ris_message", this::onRisMessage);
} catch (URISyntaxException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
e.printStackTrace();
}
@@ -141,11 +149,6 @@
}
@Override
- public Types getType() {
- return Types.RIPE;
- }
-
- @Override
public boolean isRunning() {
return this.socket != null;
}
@@ -170,8 +173,8 @@
if (this == obj) {
return true;
}
- if (obj instanceof RipeMonitor) {
- final RipeMonitor that = (RipeMonitor) obj;
+ if (obj instanceof RipeMonitors) {
+ final RipeMonitors that = (RipeMonitors) obj;
return Objects.equals(this.prefix, that.prefix) &&
Objects.equals(this.host, that.host);
}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/package-info.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/package-info.java
index 8804874..d47aa36 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/package-info.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/monitors/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/objects/ArtemisMessage.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/objects/ArtemisMessage.java
new file mode 100644
index 0000000..78d4e44
--- /dev/null
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/objects/ArtemisMessage.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.artemis.impl.objects;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import java.io.Serializable;
+
+/**
+ * Messages that are exchanged between the two MOAS entities.
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+ "type", "localIp", "localPrefix"
+})
+public class ArtemisMessage implements Serializable {
+
+ @JsonProperty("type")
+ private Type type;
+
+ @JsonProperty("localIp")
+ private String localIp;
+
+ @JsonProperty("localPrefix")
+ private String localPrefix;
+
+ public Type getType() {
+ return type;
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ public String getLocalIp() {
+ return localIp;
+ }
+
+ public void setLocalIp(String localIp) {
+ this.localIp = localIp;
+ }
+
+ public String getLocalPrefix() {
+ return localPrefix;
+ }
+
+ public void setLocalPrefix(String localPrefix) {
+ this.localPrefix = localPrefix;
+ }
+
+ @Override
+ public String toString() {
+ return "ArtemisMessage{" +
+ "type=" + type +
+ ", localIp=" + localIp +
+ ", localPrefix=" + localPrefix +
+ '}';
+ }
+
+ public enum Type {
+ INITIATE_FROM_CLIENT,
+ INITIATE_FROM_SERVER
+ }
+}
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/objects/package-info.java
similarity index 82%
copy from apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java
copy to apps/artemis/src/main/java/org/onosproject/artemis/impl/objects/package-info.java
index b2d0dc4..65b1b22 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/objects/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,6 @@
*/
/**
- * Artemis CLI commands.
+ * Custom objects.
*/
-package org.onosproject.artemis.cli;
\ No newline at end of file
+package org.onosproject.artemis.impl.objects;
\ No newline at end of file
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/impl/package-info.java b/apps/artemis/src/main/java/org/onosproject/artemis/impl/package-info.java
index 13f5fc3..633afc5 100644
--- a/apps/artemis/src/main/java/org/onosproject/artemis/impl/package-info.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/impl/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,6 @@
*/
/**
- * Artemis component.
+ * Implementation classes.
*/
package org.onosproject.artemis.impl;
\ No newline at end of file
diff --git a/apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java b/apps/artemis/src/main/java/org/onosproject/artemis/package-info.java
old mode 100644
new mode 100755
similarity index 83%
rename from apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java
rename to apps/artemis/src/main/java/org/onosproject/artemis/package-info.java
index b2d0dc4..07d5aab
--- a/apps/artemis/src/main/java/org/onosproject/artemis/cli/package-info.java
+++ b/apps/artemis/src/main/java/org/onosproject/artemis/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016-present Open Networking Foundation
+ * Copyright 2017-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,6 @@
*/
/**
- * Artemis CLI commands.
+ * Artemis.
*/
-package org.onosproject.artemis.cli;
\ No newline at end of file
+package org.onosproject.artemis;
\ No newline at end of file
diff --git a/apps/artemis/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/artemis/src/main/resources/OSGI-INF/blueprint/shell-config.xml
old mode 100644
new mode 100755
index adf71ca..af1af5a
--- a/apps/artemis/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/artemis/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -16,9 +16,6 @@
<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.artemis.cli.LogOptionsCommand"/>
- </command>
</command-bundle>
</blueprint>
diff --git a/tools/tutorials/artemis/topo.py b/tools/tutorials/artemis/artemis-topo.py
similarity index 100%
rename from tools/tutorials/artemis/topo.py
rename to tools/tutorials/artemis/artemis-topo.py
diff --git a/tools/tutorials/artemis/configs/network-cfg.json b/tools/tutorials/artemis/configs/network-cfg.json
index 8b5d56f..35380ce 100644
--- a/tools/tutorials/artemis/configs/network-cfg.json
+++ b/tools/tutorials/artemis/configs/network-cfg.json
@@ -1,5 +1,75 @@
{
- "ports" : {
+ "apps": {
+ "org.onosproject.artemis": {
+ "artemis": {
+ "moas": { },
+ "monitors": {
+ "exabgp": [
+ "192.168.1.2:5000"
+ ],
+ "ripe": []
+ },
+ "prefixes": [
+ {
+ "moas": [ ],
+ "paths": [
+ {
+ "neighbor": [
+ {
+ "asn": 65002,
+ "neighbor": [
+ 65001
+ ]
+ }
+ ],
+ "origin": 65004
+ }
+ ],
+ "prefix": "40.0.0.0/8"
+ }
+ ]
+ }
+ },
+ "org.onosproject.reactive.routing": {
+ "reactiveRouting": {
+ "ip4LocalPrefixes": [
+ {
+ "ipPrefix" : "40.0.0.0/24",
+ "type" : "PUBLIC",
+ "gatewayIp" : "40.0.0.1"
+ },
+ {
+ "ipPrefix" : "150.1.3.0/30",
+ "type" : "PRIVATE",
+ "gatewayIp" : "150.1.3.2"
+ }
+ ],
+ "ip6LocalPrefixes": [],
+ "virtualGatewayMacAddress": "e2:f5:32:16:9a:46"
+ }
+ },
+ "org.onosproject.router": {
+ "bgp": {
+ "bgpSpeakers" : [
+ {
+ "name" : "speaker1",
+ "connectPoint" : "of:00002a45d713e141/4",
+ "peers" : [
+ "150.1.3.1"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ "devices": {
+ "ovsdb:192.168.0.2": {
+ "basic": {
+ "driver": "ovs"
+ }
+ }
+ },
+ "ports": {
"of:00002a45d713e141/2" : {
"interfaces" : [
{
@@ -18,67 +88,5 @@
}
]
}
- },
- "apps" : {
- "org.onosproject.router" : {
- "bgp" : {
- "bgpSpeakers" : [
- {
- "name" : "speaker1",
- "connectPoint" : "of:00002a45d713e141/4",
- "peers" : [
- "150.1.3.1"
- ]
- }
- ]
- }
- },
- "org.onosproject.reactive.routing" : {
- "reactiveRouting" : {
- "ip4LocalPrefixes" : [
- {
- "ipPrefix" : "40.0.0.0/24",
- "type" : "PUBLIC",
- "gatewayIp" : "40.0.0.1"
- },
- {
- "ipPrefix" : "150.1.3.0/30",
- "type" : "PRIVATE",
- "gatewayIp" : "150.1.3.2"
- }
- ],
- "ip6LocalPrefixes" : [
- ],
- "virtualGatewayMacAddress" : "e2:f5:32:16:9a:46"
- }
- },
- "org.onosproject.artemis" : {
- "artemis" : {
- "prefixes" : [
- {
- "prefix" : "40.0.0.0/8",
- "paths" : [
- {
- "origin" : 65004,
- "neighbor" : [
- {
- "asn" : 65002,
- "neighbor": [
- 65001
- ]
- }
- ]
- }
- ],
- "moas" : [ ]
- }
- ],
- "frequency" : 3000,
- "monitors" : {
- "ripe" : [ ],
- "exabgp": [ "192.168.1.2:5000" ]
- }
- }
- }
}
-}
+}
\ No newline at end of file