alshabib
Committed by Ali Al-Shabibi

removing cord-related applications

Change-Id: Ia232adeecf0f5ea17061b3fb7ca851b6a00e0f99
Showing 96 changed files with 0 additions and 12114 deletions
...@@ -99,7 +99,6 @@ APPS = [ ...@@ -99,7 +99,6 @@ APPS = [
99 # Apps 99 # Apps
100 '//apps/dhcp:onos-apps-dhcp-oar', 100 '//apps/dhcp:onos-apps-dhcp-oar',
101 '//apps/fwd:onos-apps-fwd-oar', 101 '//apps/fwd:onos-apps-fwd-oar',
102 - '//apps/aaa:onos-apps-aaa-oar',
103 '//apps/acl:onos-apps-acl-oar', 102 '//apps/acl:onos-apps-acl-oar',
104 '//apps/bgprouter:onos-apps-bgprouter-oar', 103 '//apps/bgprouter:onos-apps-bgprouter-oar',
105 '//apps/cip:onos-apps-cip-oar', 104 '//apps/cip:onos-apps-cip-oar',
...@@ -109,10 +108,7 @@ APPS = [ ...@@ -109,10 +108,7 @@ APPS = [
109 '//apps/segmentrouting:onos-apps-segmentrouting-oar', 108 '//apps/segmentrouting:onos-apps-segmentrouting-oar',
110 '//apps/gangliametrics:onos-apps-gangliametrics-oar', 109 '//apps/gangliametrics:onos-apps-gangliametrics-oar',
111 '//apps/graphitemetrics:onos-apps-graphitemetrics-oar', 110 '//apps/graphitemetrics:onos-apps-graphitemetrics-oar',
112 - '//apps/igmp:onos-apps-igmp-oar',
113 - '//apps/cordmcast:onos-apps-cordmcast-oar',
114 '//apps/flowanalyzer:onos-apps-flowanalyzer-oar', 111 '//apps/flowanalyzer:onos-apps-flowanalyzer-oar',
115 - '//apps/olt:onos-apps-olt-oar',
116 '//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar', 112 '//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar',
117 '//apps/metrics:onos-apps-metrics-oar', 113 '//apps/metrics:onos-apps-metrics-oar',
118 '//apps/mfwd:onos-apps-mfwd-oar', 114 '//apps/mfwd:onos-apps-mfwd-oar',
...@@ -137,7 +133,6 @@ APPS = [ ...@@ -137,7 +133,6 @@ APPS = [
137 '//apps/test/loadtest:onos-apps-test-loadtest-oar', 133 '//apps/test/loadtest:onos-apps-test-loadtest-oar',
138 '//apps/test/messaging-perf:onos-apps-test-messaging-perf-oar', 134 '//apps/test/messaging-perf:onos-apps-test-messaging-perf-oar',
139 '//apps/virtualbng:onos-apps-virtualbng-oar', 135 '//apps/virtualbng:onos-apps-virtualbng-oar',
140 - '//apps/cordvtn:onos-apps-cordvtn-oar',
141 '//apps/vpls:onos-apps-vpls-oar', 136 '//apps/vpls:onos-apps-vpls-oar',
142 '//apps/vrouter:onos-apps-vrouter-oar', 137 '//apps/vrouter:onos-apps-vrouter-oar',
143 '//apps/vtn:onos-apps-vtn-oar', 138 '//apps/vtn:onos-apps-vtn-oar',
...@@ -145,7 +140,6 @@ APPS = [ ...@@ -145,7 +140,6 @@ APPS = [
145 '//apps/openstacknode:onos-apps-openstacknode-oar', 140 '//apps/openstacknode:onos-apps-openstacknode-oar',
146 '//apps/cpman/app:onos-apps-cpman-app-oar', 141 '//apps/cpman/app:onos-apps-cpman-app-oar',
147 '//apps/xosclient:onos-apps-xosclient-oar', 142 '//apps/xosclient:onos-apps-xosclient-oar',
148 - '//apps/cordconfig:onos-apps-cordconfig',
149 ] 143 ]
150 144
151 APP_JARS = [ 145 APP_JARS = [
...@@ -154,7 +148,6 @@ APP_JARS = [ ...@@ -154,7 +148,6 @@ APP_JARS = [
154 '//apps/dhcp/api:onos-apps-dhcp-api', 148 '//apps/dhcp/api:onos-apps-dhcp-api',
155 '//apps/dhcp/app:onos-apps-dhcp-app', 149 '//apps/dhcp/app:onos-apps-dhcp-app',
156 '//apps/fwd:onos-apps-fwd', 150 '//apps/fwd:onos-apps-fwd',
157 - '//apps/olt:onos-apps-olt-api',
158 '//apps/iptopology-api:onos-apps-iptopology-api', 151 '//apps/iptopology-api:onos-apps-iptopology-api',
159 '//apps/openstacknode:onos-apps-openstacknode', 152 '//apps/openstacknode:onos-apps-openstacknode',
160 '//apps/routing:onos-apps-routing', 153 '//apps/routing:onos-apps-routing',
......
1 -COMPILE_DEPS = [
2 - '//lib:CORE_DEPS',
3 - '//lib:org.apache.karaf.shell.console',
4 - '//cli:onos-cli',
5 -]
6 -
7 -TEST_DEPS = [
8 - '//lib:TEST_ADAPTERS',
9 - '//core/common:onos-core-common',
10 -]
11 -
12 -osgi_jar_with_tests (
13 - deps = COMPILE_DEPS,
14 - test_deps = TEST_DEPS,
15 -)
16 -
17 -onos_app (
18 - title = 'Authentication App',
19 - category = 'Security',
20 - url = 'http://onosproject.org',
21 - description = 'ONOS authentication application.',
22 -)
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<app name="org.onosproject.aaa" origin="ATT" version="${project.version}"
18 - category="Security" url="http://onosproject.org" title="Authentication App"
19 - featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
20 - features="${project.artifactId}">
21 - <description>${project.description}</description>
22 - <artifact>mvn:${project.groupId}/${project.artifactId}/${project.version}</artifact>
23 -</app>
1 -<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
18 - <feature name="${project.artifactId}" version="${project.version}"
19 - description="${project.description}">
20 - <feature>onos-api</feature>
21 - <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
22 - </feature>
23 -</features>
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onos-apps</artifactId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 - <artifactId>onos-app-aaa</artifactId>
30 - <packaging>bundle</packaging>
31 -
32 - <description>ONOS authentication application</description>
33 -
34 - <dependencies>
35 - <dependency>
36 - <groupId>org.osgi</groupId>
37 - <artifactId>org.osgi.compendium</artifactId>
38 - </dependency>
39 -
40 - <dependency>
41 - <groupId>org.onosproject</groupId>
42 - <artifactId>onos-api</artifactId>
43 - <version>${project.version}</version>
44 - </dependency>
45 -
46 - <dependency>
47 - <groupId>org.onosproject</groupId>
48 - <artifactId>onlab-junit</artifactId>
49 - <scope>test</scope>
50 - </dependency>
51 -
52 - <dependency>
53 - <groupId>org.onosproject</groupId>
54 - <artifactId>onlab-osgi</artifactId>
55 - <version>${project.version}</version>
56 - <classifier>tests</classifier>
57 - <scope>test</scope>
58 - </dependency>
59 -
60 - <dependency>
61 - <groupId>org.onosproject</groupId>
62 - <artifactId>onos-api</artifactId>
63 - <version>${project.version}</version>
64 - <classifier>tests</classifier>
65 - <scope>test</scope>
66 - </dependency>
67 -
68 - <dependency>
69 - <groupId>org.onosproject</groupId>
70 - <artifactId>onos-cli</artifactId>
71 - <version>${project.version}</version>
72 - </dependency>
73 -
74 - <dependency>
75 - <groupId>org.apache.karaf.shell</groupId>
76 - <artifactId>org.apache.karaf.shell.console</artifactId>
77 - </dependency>
78 - </dependencies>
79 -
80 -
81 - <build>
82 - <plugins>
83 - <plugin>
84 - <groupId>org.apache.felix</groupId>
85 - <artifactId>maven-bundle-plugin</artifactId>
86 - </plugin>
87 -
88 - <plugin>
89 - <groupId>org.apache.felix</groupId>
90 - <artifactId>maven-scr-plugin</artifactId>
91 - </plugin>
92 - <plugin>
93 - <groupId>org.onosproject</groupId>
94 - <artifactId>onos-maven-plugin</artifactId>
95 - </plugin>
96 - </plugins>
97 - </build>
98 -</project>
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.aaa;
17 -
18 -import org.onosproject.core.ApplicationId;
19 -import org.onosproject.net.config.Config;
20 -import org.onosproject.net.config.basics.BasicElementConfig;
21 -
22 -import java.net.InetAddress;
23 -import java.net.UnknownHostException;
24 -
25 -/**
26 - * Network config for the AAA app.
27 - */
28 -public class AaaConfig extends Config<ApplicationId> {
29 -
30 - private static final String RADIUS_IP = "radiusIp";
31 - private static final String RADIUS_SERVER_PORT = "1812";
32 - private static final String RADIUS_MAC = "radiusMac";
33 - private static final String NAS_IP = "nasIp";
34 - private static final String NAS_MAC = "nasMac";
35 - private static final String RADIUS_SECRET = "radiusSecret";
36 - private static final String RADIUS_SWITCH = "radiusSwitch";
37 - private static final String RADIUS_PORT = "radiusPort";
38 -
39 - // RADIUS server IP address
40 - protected static final String DEFAULT_RADIUS_IP = "10.128.10.4";
41 -
42 - // RADIUS MAC address
43 - protected static final String DEFAULT_RADIUS_MAC = "00:00:00:00:01:10";
44 -
45 - // NAS IP address
46 - protected static final String DEFAULT_NAS_IP = "10.128.9.244";
47 -
48 - // NAS MAC address
49 - protected static final String DEFAULT_NAS_MAC = "00:00:00:00:10:01";
50 -
51 - // RADIUS server shared secret
52 - protected static final String DEFAULT_RADIUS_SECRET = "ONOSecret";
53 -
54 - // Radius Switch Id
55 - protected static final String DEFAULT_RADIUS_SWITCH = "of:90e2ba82f97791e9";
56 -
57 - // Radius Port Number
58 - protected static final String DEFAULT_RADIUS_PORT = "129";
59 -
60 - // Radius Server UDP Port Number
61 - protected static final String DEFAULT_RADIUS_SERVER_PORT = "1812";
62 -
63 - /**
64 - * Gets the value of a string property, protecting for an empty
65 - * JSON object.
66 - *
67 - * @param name name of the property
68 - * @param defaultValue default value if none has been specified
69 - * @return String value if one os found, default value otherwise
70 - */
71 - private String getStringProperty(String name, String defaultValue) {
72 - if (object == null) {
73 - return defaultValue;
74 - }
75 - return get(name, defaultValue);
76 - }
77 -
78 - /**
79 - * Returns the NAS ip.
80 - *
81 - * @return ip address or null if not set
82 - */
83 - public InetAddress nasIp() {
84 - try {
85 - return InetAddress.getByName(getStringProperty(NAS_IP, DEFAULT_NAS_IP));
86 - } catch (UnknownHostException e) {
87 - return null;
88 - }
89 - }
90 -
91 - /**
92 - * Sets the NAS ip.
93 - *
94 - * @param ip new ip address; null to clear
95 - * @return self
96 - */
97 - public BasicElementConfig nasIp(String ip) {
98 - return (BasicElementConfig) setOrClear(NAS_IP, ip);
99 - }
100 -
101 - /**
102 - * Returns the RADIUS server ip.
103 - *
104 - * @return ip address or null if not set
105 - */
106 - public InetAddress radiusIp() {
107 - try {
108 - return InetAddress.getByName(getStringProperty(RADIUS_IP, DEFAULT_RADIUS_IP));
109 - } catch (UnknownHostException e) {
110 - return null;
111 - }
112 - }
113 -
114 - /**
115 - * Sets the RADIUS server ip.
116 - *
117 - * @param ip new ip address; null to clear
118 - * @return self
119 - */
120 - public BasicElementConfig radiusIp(String ip) {
121 - return (BasicElementConfig) setOrClear(RADIUS_IP, ip);
122 - }
123 -
124 - /**
125 - * Returns the RADIUS MAC address.
126 - *
127 - * @return mac address or null if not set
128 - */
129 - public String radiusMac() {
130 - return getStringProperty(RADIUS_MAC, DEFAULT_RADIUS_MAC);
131 - }
132 -
133 - /**
134 - * Sets the RADIUS MAC address.
135 - *
136 - * @param mac new MAC address; null to clear
137 - * @return self
138 - */
139 - public BasicElementConfig radiusMac(String mac) {
140 - return (BasicElementConfig) setOrClear(RADIUS_MAC, mac);
141 - }
142 -
143 - /**
144 - * Returns the RADIUS MAC address.
145 - *
146 - * @return mac address or null if not set
147 - */
148 - public String nasMac() {
149 - return getStringProperty(NAS_MAC, DEFAULT_NAS_MAC);
150 - }
151 -
152 - /**
153 - * Sets the RADIUS MAC address.
154 - *
155 - * @param mac new MAC address; null to clear
156 - * @return self
157 - */
158 - public BasicElementConfig nasMac(String mac) {
159 - return (BasicElementConfig) setOrClear(NAS_MAC, mac);
160 - }
161 -
162 - /**
163 - * Returns the RADIUS secret.
164 - *
165 - * @return radius secret or null if not set
166 - */
167 - public String radiusSecret() {
168 - return getStringProperty(RADIUS_SECRET, DEFAULT_RADIUS_SECRET);
169 - }
170 -
171 - /**
172 - * Sets the RADIUS secret.
173 - *
174 - * @param secret new MAC address; null to clear
175 - * @return self
176 - */
177 - public BasicElementConfig radiusSecret(String secret) {
178 - return (BasicElementConfig) setOrClear(RADIUS_SECRET, secret);
179 - }
180 -
181 - /**
182 - * Returns the ID of the RADIUS switch.
183 - *
184 - * @return radius switch ID or null if not set
185 - */
186 - public String radiusSwitch() {
187 - return getStringProperty(RADIUS_SWITCH, DEFAULT_RADIUS_SWITCH);
188 - }
189 -
190 - /**
191 - * Sets the ID of the RADIUS switch.
192 - *
193 - * @param switchId new RADIUS switch ID; null to clear
194 - * @return self
195 - */
196 - public BasicElementConfig radiusSwitch(String switchId) {
197 - return (BasicElementConfig) setOrClear(RADIUS_SWITCH, switchId);
198 - }
199 -
200 - /**
201 - * Returns the RADIUS port.
202 - *
203 - * @return radius port or null if not set
204 - */
205 - public long radiusPort() {
206 - return Integer.parseInt(getStringProperty(RADIUS_PORT, DEFAULT_RADIUS_PORT));
207 - }
208 -
209 - /**
210 - * Sets the RADIUS port.
211 - *
212 - * @param port new RADIUS port; null to clear
213 - * @return self
214 - */
215 - public BasicElementConfig radiusPort(long port) {
216 - return (BasicElementConfig) setOrClear(RADIUS_PORT, port);
217 - }
218 -
219 - /**
220 - * Returns the RADIUS server UDP port.
221 - *
222 - * @return radius server UDP port.
223 - */
224 - public short radiusServerUdpPort() {
225 - return Short.parseShort(getStringProperty(RADIUS_SERVER_PORT,
226 - DEFAULT_RADIUS_SERVER_PORT));
227 - }
228 -
229 - /**
230 - * Sets the RADIUS port.
231 - *
232 - * @param port new RADIUS UDP port; -1 to clear
233 - * @return self
234 - */
235 - public BasicElementConfig radiusServerUdpPort(short port) {
236 - return (BasicElementConfig) setOrClear(RADIUS_SERVER_PORT, (long) port);
237 - }
238 -
239 -}
1 -/*
2 - * Copyright 2015 AT&T Foundry
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.aaa;
17 -
18 -import java.io.IOException;
19 -import java.net.DatagramPacket;
20 -import java.net.DatagramSocket;
21 -import java.net.InetAddress;
22 -import java.net.InetSocketAddress;
23 -import java.nio.ByteBuffer;
24 -import java.util.concurrent.ExecutorService;
25 -import java.util.concurrent.Executors;
26 -
27 -import org.apache.felix.scr.annotations.Activate;
28 -import org.apache.felix.scr.annotations.Component;
29 -import org.apache.felix.scr.annotations.Deactivate;
30 -import org.apache.felix.scr.annotations.Reference;
31 -import org.apache.felix.scr.annotations.ReferenceCardinality;
32 -import org.onlab.packet.DeserializationException;
33 -import org.onlab.packet.EAP;
34 -import org.onlab.packet.EAPOL;
35 -import org.onlab.packet.EthType;
36 -import org.onlab.packet.Ethernet;
37 -import org.onlab.packet.MacAddress;
38 -import org.onlab.packet.RADIUS;
39 -import org.onlab.packet.RADIUSAttribute;
40 -import org.onosproject.core.ApplicationId;
41 -import org.onosproject.core.CoreService;
42 -import org.onosproject.net.ConnectPoint;
43 -import org.onosproject.net.DeviceId;
44 -import org.onosproject.net.PortNumber;
45 -import org.onosproject.net.config.ConfigFactory;
46 -import org.onosproject.net.config.NetworkConfigEvent;
47 -import org.onosproject.net.config.NetworkConfigListener;
48 -import org.onosproject.net.config.NetworkConfigRegistry;
49 -import org.onosproject.net.flow.DefaultTrafficSelector;
50 -import org.onosproject.net.flow.DefaultTrafficTreatment;
51 -import org.onosproject.net.flow.TrafficSelector;
52 -import org.onosproject.net.flow.TrafficTreatment;
53 -import org.onosproject.net.packet.DefaultOutboundPacket;
54 -import org.onosproject.net.packet.InboundPacket;
55 -import org.onosproject.net.packet.OutboundPacket;
56 -import org.onosproject.net.packet.PacketContext;
57 -import org.onosproject.net.packet.PacketProcessor;
58 -import org.onosproject.net.packet.PacketService;
59 -import org.slf4j.Logger;
60 -
61 -import com.google.common.util.concurrent.ThreadFactoryBuilder;
62 -
63 -import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
64 -import static org.onosproject.net.packet.PacketPriority.CONTROL;
65 -import static org.slf4j.LoggerFactory.getLogger;
66 -
67 -/**
68 - * AAA application for ONOS.
69 - */
70 -@Component(immediate = true)
71 -public class AaaManager {
72 -
73 - // for verbose output
74 - private final Logger log = getLogger(getClass());
75 -
76 - // a list of our dependencies :
77 - // to register with ONOS as an application - described next
78 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 - protected CoreService coreService;
80 -
81 - // to receive Packet-in events that we'll respond to
82 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 - protected PacketService packetService;
84 -
85 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 - protected NetworkConfigRegistry netCfgService;
87 -
88 - // Parsed RADIUS server addresses
89 - protected InetAddress radiusIpAddress;
90 - protected String radiusMacAddress;
91 -
92 - // NAS IP address
93 - protected InetAddress nasIpAddress;
94 - protected String nasMacAddress;
95 -
96 - // RADIUS server secret
97 - protected String radiusSecret;
98 -
99 - // ID of RADIUS switch
100 - protected String radiusSwitch;
101 -
102 - // RADIUS port number
103 - protected long radiusPort;
104 -
105 - // RADIUS server TCP port number
106 - protected short radiusServerPort;
107 -
108 - // our application-specific event handler
109 - private ReactivePacketProcessor processor = new ReactivePacketProcessor();
110 -
111 - // our unique identifier
112 - private ApplicationId appId;
113 -
114 - // Socket used for UDP communications with RADIUS server
115 - private DatagramSocket radiusSocket;
116 -
117 - // Executor for RADIUS communication thread
118 - private ExecutorService executor;
119 -
120 - // Configuration properties factory
121 - private final ConfigFactory factory =
122 - new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
123 - AaaConfig.class,
124 - "AAA") {
125 - @Override
126 - public AaaConfig createConfig() {
127 - return new AaaConfig();
128 - }
129 - };
130 -
131 - // Listener for config changes
132 - private final InternalConfigListener cfgListener = new InternalConfigListener();
133 -
134 - /**
135 - * Builds an EAPOL packet based on the given parameters.
136 - *
137 - * @param dstMac destination MAC address
138 - * @param srcMac source MAC address
139 - * @param vlan vlan identifier
140 - * @param eapolType EAPOL type
141 - * @param eap EAP payload
142 - * @return Ethernet frame
143 - */
144 - private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
145 - short vlan, byte eapolType, EAP eap) {
146 -
147 - Ethernet eth = new Ethernet();
148 - eth.setDestinationMACAddress(dstMac.toBytes());
149 - eth.setSourceMACAddress(srcMac.toBytes());
150 - eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
151 - if (vlan != Ethernet.VLAN_UNTAGGED) {
152 - eth.setVlanID(vlan);
153 - }
154 - //eapol header
155 - EAPOL eapol = new EAPOL();
156 - eapol.setEapolType(eapolType);
157 - eapol.setPacketLength(eap.getLength());
158 -
159 - //eap part
160 - eapol.setPayload(eap);
161 -
162 - eth.setPayload(eapol);
163 - eth.setPad(true);
164 - return eth;
165 - }
166 -
167 - private void initializeLocalState() {
168 - try {
169 - radiusSocket = new DatagramSocket(null);
170 - radiusSocket.setReuseAddress(true);
171 - radiusSocket.bind(new InetSocketAddress(radiusServerPort));
172 - } catch (Exception ex) {
173 - log.error("Can't open RADIUS socket", ex);
174 - }
175 -
176 - executor = Executors.newSingleThreadExecutor(
177 - new ThreadFactoryBuilder()
178 - .setNameFormat("AAA-radius-%d").build());
179 - executor.execute(radiusListener);
180 - }
181 -
182 - @Activate
183 - public void activate() {
184 - netCfgService.addListener(cfgListener);
185 - netCfgService.registerConfigFactory(factory);
186 -
187 - // "org.onosproject.aaa" is the FQDN of our app
188 - appId = coreService.registerApplication("org.onosproject.aaa");
189 -
190 - cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
191 -
192 - // register our event handler
193 - packetService.addProcessor(processor, PacketProcessor.director(2));
194 - requestIntercepts();
195 -
196 - StateMachine.initializeMaps();
197 -
198 - initializeLocalState();
199 - log.info("Started");
200 - }
201 -
202 - @Deactivate
203 - public void deactivate() {
204 - withdrawIntercepts();
205 - // de-register and null our handler
206 - packetService.removeProcessor(processor);
207 - processor = null;
208 - StateMachine.destroyMaps();
209 - radiusSocket.close();
210 - executor.shutdownNow();
211 - log.info("Stopped");
212 - }
213 -
214 - protected void sendRadiusPacket(RADIUS radiusPacket) {
215 -
216 - try {
217 - final byte[] data = radiusPacket.serialize();
218 - final DatagramSocket socket = radiusSocket;
219 -
220 - DatagramPacket packet =
221 - new DatagramPacket(data, data.length,
222 - radiusIpAddress, radiusServerPort);
223 -
224 - socket.send(packet);
225 - } catch (IOException e) {
226 - log.info("Cannot send packet to RADIUS server", e);
227 - }
228 - }
229 -
230 - /**
231 - * Request packet in via PacketService.
232 - */
233 - private void requestIntercepts() {
234 - TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
235 - selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort());
236 - packetService.requestPackets(selector.build(),
237 - CONTROL, appId);
238 - }
239 -
240 - /**
241 - * Cancel request for packet in via PacketService.
242 - */
243 - private void withdrawIntercepts() {
244 - TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
245 - selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort());
246 - packetService.cancelPackets(selector.build(), CONTROL, appId);
247 - }
248 -
249 - /**
250 - * Send the ethernet packet to the supplicant.
251 - *
252 - * @param ethernetPkt the ethernet packet
253 - * @param connectPoint the connect point to send out
254 - */
255 - private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint) {
256 - TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
257 - OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
258 - treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
259 - packetService.emit(packet);
260 - }
261 -
262 - // our handler defined as a private inner class
263 -
264 - /**
265 - * Packet processor responsible for forwarding packets along their paths.
266 - */
267 - private class ReactivePacketProcessor implements PacketProcessor {
268 - @Override
269 - public void process(PacketContext context) {
270 -
271 - // Extract the original Ethernet frame from the packet information
272 - InboundPacket pkt = context.inPacket();
273 - Ethernet ethPkt = pkt.parsed();
274 - if (ethPkt == null) {
275 - return;
276 - }
277 - try {
278 - // identify if incoming packet comes from supplicant (EAP) or RADIUS
279 - switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
280 - case EAPOL:
281 - handleSupplicantPacket(context.inPacket());
282 - break;
283 - default:
284 - log.trace("Skipping Ethernet packet type {}",
285 - EthType.EtherType.lookup(ethPkt.getEtherType()));
286 - }
287 - } catch (StateMachineException e) {
288 - log.warn("Unable to process RADIUS packet:", e);
289 - }
290 - }
291 -
292 - /**
293 - * Creates and initializes common fields of a RADIUS packet.
294 - *
295 - * @param stateMachine state machine for the request
296 - * @param eapPacket EAP packet
297 - * @return RADIUS packet
298 - */
299 - private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
300 - RADIUS radiusPayload =
301 - new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
302 - eapPacket.getIdentifier());
303 -
304 - // set Request Authenticator in StateMachine
305 - stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
306 -
307 - radiusPayload.setIdentifier(identifier);
308 - radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
309 - stateMachine.username());
310 -
311 - radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
312 - AaaManager.this.nasIpAddress.getAddress());
313 -
314 - radiusPayload.encapsulateMessage(eapPacket);
315 -
316 - return radiusPayload;
317 - }
318 -
319 - /**
320 - * Handles PAE packets (supplicant).
321 - *
322 - * @param inPacket Ethernet packet coming from the supplicant
323 - */
324 - private void handleSupplicantPacket(InboundPacket inPacket) throws StateMachineException {
325 - Ethernet ethPkt = inPacket.parsed();
326 - // Where does it come from?
327 - MacAddress srcMac = ethPkt.getSourceMAC();
328 -
329 - DeviceId deviceId = inPacket.receivedFrom().deviceId();
330 - PortNumber portNumber = inPacket.receivedFrom().port();
331 - String sessionId = deviceId.toString() + portNumber.toString();
332 - StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
333 - if (stateMachine == null) {
334 - stateMachine = new StateMachine(sessionId);
335 - }
336 -
337 -
338 - EAPOL eapol = (EAPOL) ethPkt.getPayload();
339 -
340 - switch (eapol.getEapolType()) {
341 - case EAPOL.EAPOL_START:
342 - stateMachine.start();
343 - stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
344 -
345 - //send an EAP Request/Identify to the supplicant
346 - EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
347 - Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
348 - ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
349 - eapPayload);
350 - stateMachine.setSupplicantAddress(srcMac);
351 - stateMachine.setVlanId(ethPkt.getVlanID());
352 -
353 - sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
354 -
355 - break;
356 - case EAPOL.EAPOL_LOGOFF:
357 - if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
358 - stateMachine.logoff();
359 - }
360 -
361 - break;
362 - case EAPOL.EAPOL_PACKET:
363 - RADIUS radiusPayload;
364 - // check if this is a Response/Identify or a Response/TLS
365 - EAP eapPacket = (EAP) eapol.getPayload();
366 -
367 - byte dataType = eapPacket.getDataType();
368 - switch (dataType) {
369 -
370 - case EAP.ATTR_IDENTITY:
371 - // request id access to RADIUS
372 - stateMachine.setUsername(eapPacket.getData());
373 -
374 - radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
375 - radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
376 -
377 - sendRadiusPacket(radiusPayload);
378 -
379 - // change the state to "PENDING"
380 - stateMachine.requestAccess();
381 - break;
382 - case EAP.ATTR_MD5:
383 - // verify if the EAP identifier corresponds to the
384 - // challenge identifier from the client state
385 - // machine.
386 - if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
387 - //send the RADIUS challenge response
388 - radiusPayload =
389 - getRadiusPayload(stateMachine,
390 - stateMachine.identifier(),
391 - eapPacket);
392 -
393 - if (stateMachine.challengeState() != null) {
394 - radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
395 - stateMachine.challengeState());
396 - }
397 - radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
398 - sendRadiusPacket(radiusPayload);
399 - }
400 - break;
401 - case EAP.ATTR_TLS:
402 - // request id access to RADIUS
403 - radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
404 -
405 - if (stateMachine.challengeState() != null) {
406 - radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
407 - stateMachine.challengeState());
408 - }
409 - stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
410 -
411 - radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
412 - sendRadiusPacket(radiusPayload);
413 -
414 - if (stateMachine.state() != StateMachine.STATE_PENDING) {
415 - stateMachine.requestAccess();
416 - }
417 -
418 - break;
419 - default:
420 - return;
421 - }
422 - break;
423 - default:
424 - log.trace("Skipping EAPOL message {}", eapol.getEapolType());
425 - }
426 -
427 - }
428 - }
429 -
430 - class RadiusListener implements Runnable {
431 -
432 - /**
433 - * Handles RADIUS packets.
434 - *
435 - * @param radiusPacket RADIUS packet coming from the RADIUS server.
436 - * @throws StateMachineException if an illegal state transition is triggered
437 - */
438 - protected void handleRadiusPacket(RADIUS radiusPacket) throws StateMachineException {
439 - StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
440 - if (stateMachine == null) {
441 - log.error("Invalid session identifier, exiting...");
442 - return;
443 - }
444 -
445 - EAP eapPayload;
446 - Ethernet eth;
447 - switch (radiusPacket.getCode()) {
448 - case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
449 - RADIUSAttribute radiusAttrState = radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE);
450 - byte[] challengeState = null;
451 - if (radiusAttrState != null) {
452 - challengeState = radiusAttrState.getValue();
453 - }
454 - eapPayload = radiusPacket.decapsulateMessage();
455 - stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
456 - eth = buildEapolResponse(stateMachine.supplicantAddress(),
457 - MacAddress.valueOf(nasMacAddress),
458 - stateMachine.vlanId(),
459 - EAPOL.EAPOL_PACKET,
460 - eapPayload);
461 - sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
462 - break;
463 - case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
464 - //send an EAPOL - Success to the supplicant.
465 - byte[] eapMessage =
466 - radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
467 - eapPayload = new EAP();
468 - eapPayload = (EAP) eapPayload.deserialize(eapMessage, 0, eapMessage.length);
469 - eth = buildEapolResponse(stateMachine.supplicantAddress(),
470 - MacAddress.valueOf(nasMacAddress),
471 - stateMachine.vlanId(),
472 - EAPOL.EAPOL_PACKET,
473 - eapPayload);
474 - sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
475 -
476 - stateMachine.authorizeAccess();
477 - break;
478 - case RADIUS.RADIUS_CODE_ACCESS_REJECT:
479 - stateMachine.denyAccess();
480 - break;
481 - default:
482 - log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
483 - }
484 - }
485 -
486 -
487 - @Override
488 - public void run() {
489 - boolean done = false;
490 - int packetNumber = 1;
491 -
492 - log.info("UDP listener thread starting up");
493 - RADIUS inboundRadiusPacket;
494 - while (!done) {
495 - try {
496 - byte[] packetBuffer = new byte[RADIUS.RADIUS_MAX_LENGTH];
497 - DatagramPacket inboundBasePacket =
498 - new DatagramPacket(packetBuffer, packetBuffer.length);
499 - DatagramSocket socket = radiusSocket;
500 - socket.receive(inboundBasePacket);
501 - log.info("Packet #{} received", packetNumber++);
502 - try {
503 - inboundRadiusPacket =
504 - RADIUS.deserializer()
505 - .deserialize(inboundBasePacket.getData(),
506 - 0,
507 - inboundBasePacket.getLength());
508 - handleRadiusPacket(inboundRadiusPacket);
509 - } catch (DeserializationException dex) {
510 - log.error("Cannot deserialize packet", dex);
511 - } catch (StateMachineException sme) {
512 - log.error("Illegal state machine operation", sme);
513 - }
514 -
515 - } catch (IOException e) {
516 - log.info("Socket was closed, exiting listener thread");
517 - done = true;
518 - }
519 - }
520 - }
521 - }
522 -
523 - RadiusListener radiusListener = new RadiusListener();
524 -
525 - private class InternalConfigListener implements NetworkConfigListener {
526 -
527 - /**
528 - * Reconfigures the AAA application according to the
529 - * configuration parameters passed.
530 - *
531 - * @param cfg configuration object
532 - */
533 - private void reconfigureNetwork(AaaConfig cfg) {
534 - AaaConfig newCfg;
535 - if (cfg == null) {
536 - newCfg = new AaaConfig();
537 - } else {
538 - newCfg = cfg;
539 - }
540 - if (newCfg.nasIp() != null) {
541 - nasIpAddress = newCfg.nasIp();
542 - }
543 - if (newCfg.radiusIp() != null) {
544 - radiusIpAddress = newCfg.radiusIp();
545 - }
546 - if (newCfg.radiusMac() != null) {
547 - radiusMacAddress = newCfg.radiusMac();
548 - }
549 - if (newCfg.nasMac() != null) {
550 - nasMacAddress = newCfg.nasMac();
551 - }
552 - if (newCfg.radiusSecret() != null) {
553 - radiusSecret = newCfg.radiusSecret();
554 - }
555 - if (newCfg.radiusSwitch() != null) {
556 - radiusSwitch = newCfg.radiusSwitch();
557 - }
558 - if (newCfg.radiusPort() != -1) {
559 - radiusPort = newCfg.radiusPort();
560 - }
561 - if (newCfg.radiusServerUdpPort() != -1) {
562 - radiusServerPort = newCfg.radiusServerUdpPort();
563 - }
564 - }
565 -
566 - @Override
567 - public void event(NetworkConfigEvent event) {
568 -
569 - if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
570 - event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
571 - event.configClass().equals(AaaConfig.class)) {
572 -
573 - AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
574 - reconfigureNetwork(cfg);
575 - radiusSocket.close();
576 - executor.shutdownNow();
577 - initializeLocalState();
578 - log.info("Reconfigured");
579 - }
580 - }
581 - }
582 -
583 -
584 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.aaa;
17 -
18 -import org.apache.karaf.shell.commands.Command;
19 -import org.onosproject.cli.AbstractShellCommand;
20 -
21 -/**
22 - * Shows the users in the aaa.
23 - */
24 -@Command(scope = "onos", name = "aaa-users",
25 - description = "Shows the aaa users")
26 -public class AaaShowUsersCommand extends AbstractShellCommand {
27 - @Override
28 - protected void execute() {
29 - String[] state = {
30 - "IDLE",
31 - "STARTED",
32 - "PENDING",
33 - "AUTHORIZED",
34 - "UNAUTHORIZED"
35 - };
36 - for (StateMachine stateMachine : StateMachine.sessionIdMap().values()) {
37 - String deviceId = stateMachine.supplicantConnectpoint().deviceId().toString();
38 - String portNum = stateMachine.supplicantConnectpoint().port().toString();
39 - String username = new String(stateMachine.username());
40 - print("UserName=%s,CurrentState=%s,DeviceId=%s,PortNumber=%s",
41 - username, state[stateMachine.state()], deviceId, portNum);
42 - }
43 - }
44 -}
1 -/*
2 - *
3 - * Copyright 2015 AT&T Foundry
4 - *
5 - * Licensed under the Apache License, Version 2.0 (the "License");
6 - * you may not use this file except in compliance with the License.
7 - * You may obtain a copy of the License at
8 - *
9 - * http://www.apache.org/licenses/LICENSE-2.0
10 - *
11 - * Unless required by applicable law or agreed to in writing, software
12 - * distributed under the License is distributed on an "AS IS" BASIS,
13 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - * See the License for the specific language governing permissions and
15 - * limitations under the License.
16 - *
17 - */
18 -
19 -package org.onosproject.aaa;
20 -
21 -import java.util.BitSet;
22 -import java.util.Map;
23 -
24 -import org.onlab.packet.MacAddress;
25 -import org.onosproject.net.ConnectPoint;
26 -import org.slf4j.Logger;
27 -
28 -import com.google.common.collect.Maps;
29 -
30 -import static org.slf4j.LoggerFactory.getLogger;
31 -
32 -/**
33 - * AAA Finite State Machine.
34 - */
35 -
36 -class StateMachine {
37 - //INDEX to identify the state in the transition table
38 - static final int STATE_IDLE = 0;
39 - static final int STATE_STARTED = 1;
40 - static final int STATE_PENDING = 2;
41 - static final int STATE_AUTHORIZED = 3;
42 - static final int STATE_UNAUTHORIZED = 4;
43 -
44 - //INDEX to identify the transition in the transition table
45 - static final int TRANSITION_START = 0; // --> started
46 - static final int TRANSITION_REQUEST_ACCESS = 1;
47 - static final int TRANSITION_AUTHORIZE_ACCESS = 2;
48 - static final int TRANSITION_DENY_ACCESS = 3;
49 - static final int TRANSITION_LOGOFF = 4;
50 -
51 - //map of access identifiers (issued at EAPOL START)
52 - static BitSet bitSet = new BitSet();
53 -
54 - private int identifier = -1;
55 - private byte challengeIdentifier;
56 - private byte[] challengeState;
57 - private byte[] username;
58 - private byte[] requestAuthenticator;
59 -
60 - // Supplicant connectivity info
61 - private ConnectPoint supplicantConnectpoint;
62 - private MacAddress supplicantAddress;
63 - private short vlanId;
64 -
65 - private String sessionId = null;
66 -
67 - private final Logger log = getLogger(getClass());
68 -
69 -
70 - private State[] states = {
71 - new Idle(), new Started(), new Pending(), new Authorized(), new Unauthorized()
72 - };
73 -
74 -
75 - //State transition table
76 - /*
77 -
78 - state IDLE | STARTED | PENDING | AUTHORIZED | UNAUTHORIZED
79 - ////
80 - input
81 - ----------------------------------------------------------------------------------------------------
82 -
83 - START STARTED | _ | _ | STARTED | _
84 -
85 - REQUEST_ACCESS _ | PENDING | _ | _ | _
86 -
87 - AUTHORIZE_ACCESS _ | _ | AUTHORIZED | _ | _
88 -
89 - DENY_ACCESS _ | - | UNAUTHORIZED | _ | _
90 -
91 - LOGOFF _ | _ | _ | IDLE | IDLE
92 - */
93 -
94 - private int[] idleTransition =
95 - {STATE_STARTED, STATE_IDLE, STATE_IDLE, STATE_IDLE, STATE_IDLE};
96 - private int[] startedTransition =
97 - {STATE_STARTED, STATE_PENDING, STATE_STARTED, STATE_STARTED, STATE_STARTED};
98 - private int[] pendingTransition =
99 - {STATE_PENDING, STATE_PENDING, STATE_AUTHORIZED, STATE_UNAUTHORIZED, STATE_PENDING};
100 - private int[] authorizedTransition =
101 - {STATE_STARTED, STATE_AUTHORIZED, STATE_AUTHORIZED, STATE_AUTHORIZED, STATE_IDLE};
102 - private int[] unauthorizedTransition =
103 - {STATE_UNAUTHORIZED, STATE_UNAUTHORIZED, STATE_UNAUTHORIZED, STATE_UNAUTHORIZED, STATE_IDLE};
104 -
105 - //THE TRANSITION TABLE
106 - private int[][] transition =
107 - {idleTransition, startedTransition, pendingTransition, authorizedTransition,
108 - unauthorizedTransition};
109 -
110 - private int currentState = STATE_IDLE;
111 -
112 - // Maps of state machines. Each state machine is represented by an
113 - // unique identifier on the switch: dpid + port number
114 - private static Map<String, StateMachine> sessionIdMap;
115 - private static Map<Integer, StateMachine> identifierMap;
116 -
117 - public static void initializeMaps() {
118 - sessionIdMap = Maps.newConcurrentMap();
119 - identifierMap = Maps.newConcurrentMap();
120 - }
121 -
122 - public static void destroyMaps() {
123 - sessionIdMap = null;
124 - identifierMap = null;
125 - }
126 -
127 - public static Map<String, StateMachine> sessionIdMap() {
128 - return sessionIdMap;
129 - }
130 -
131 - public static StateMachine lookupStateMachineById(byte identifier) {
132 - return identifierMap.get((int) identifier);
133 - }
134 -
135 - public static StateMachine lookupStateMachineBySessionId(String sessionId) {
136 - return sessionIdMap.get(sessionId);
137 - } /**
138 - * State Machine Constructor.
139 - *
140 - * @param sessionId session Id represented by the switch dpid + port number
141 - */
142 - public StateMachine(String sessionId) {
143 - log.info("Creating a new state machine for {}", sessionId);
144 - this.sessionId = sessionId;
145 - sessionIdMap.put(sessionId, this);
146 - }
147 -
148 - /**
149 - * Gets the connect point for the supplicant side.
150 - *
151 - * @return supplicant connect point
152 - */
153 - public ConnectPoint supplicantConnectpoint() {
154 - return supplicantConnectpoint;
155 - }
156 -
157 - /**
158 - * Sets the supplicant side connect point.
159 - *
160 - * @param supplicantConnectpoint supplicant select point.
161 - */
162 - public void setSupplicantConnectpoint(ConnectPoint supplicantConnectpoint) {
163 - this.supplicantConnectpoint = supplicantConnectpoint;
164 - }
165 -
166 - /**
167 - * Gets the MAC address of the supplicant.
168 - *
169 - * @return supplicant MAC address
170 - */
171 - public MacAddress supplicantAddress() {
172 - return supplicantAddress;
173 - }
174 -
175 - /**
176 - * Sets the supplicant MAC address.
177 - *
178 - * @param supplicantAddress new supplicant MAC address
179 - */
180 - public void setSupplicantAddress(MacAddress supplicantAddress) {
181 - this.supplicantAddress = supplicantAddress;
182 - }
183 -
184 - /**
185 - * Gets the client's Vlan ID.
186 - *
187 - * @return client vlan ID
188 - */
189 - public short vlanId() {
190 - return vlanId;
191 - }
192 -
193 - /**
194 - * Sets the client's vlan ID.
195 - *
196 - * @param vlanId new client vlan ID
197 - */
198 - public void setVlanId(short vlanId) {
199 - this.vlanId = vlanId;
200 - }
201 -
202 - /**
203 - * Gets the client id that is requesting for access.
204 - *
205 - * @return The client id.
206 - */
207 - public String sessionId() {
208 - return this.sessionId;
209 - }
210 -
211 - /**
212 - * Create the identifier for the state machine (happens when goes to STARTED state).
213 - */
214 - private void createIdentifier() throws StateMachineException {
215 - log.debug("Creating Identifier.");
216 - int index;
217 -
218 - try {
219 - //find the first available spot for identifier assignment
220 - index = StateMachine.bitSet.nextClearBit(0);
221 -
222 - //there is a limit of 256 identifiers
223 - if (index == 256) {
224 - throw new StateMachineException("Cannot handle any new identifier. Limit is 256.");
225 - }
226 - } catch (IndexOutOfBoundsException e) {
227 - throw new StateMachineException(e.getMessage());
228 - }
229 -
230 - log.info("Assigning identifier {}", index);
231 - StateMachine.bitSet.set(index);
232 - this.identifier = index;
233 - }
234 -
235 - /**
236 - * Set the challenge identifier and the state issued by the RADIUS.
237 - *
238 - * @param challengeIdentifier The challenge identifier set into the EAP packet from the RADIUS message.
239 - * @param challengeState The challenge state from the RADIUS.
240 - */
241 - protected void setChallengeInfo(byte challengeIdentifier, byte[] challengeState) {
242 - this.challengeIdentifier = challengeIdentifier;
243 - this.challengeState = challengeState;
244 - }
245 -
246 - /**
247 - * Set the challenge identifier issued by the RADIUS on the access challenge request.
248 - *
249 - * @param challengeIdentifier The challenge identifier set into the EAP packet from the RADIUS message.
250 - */
251 - protected void setChallengeIdentifier(byte challengeIdentifier) {
252 - log.info("Set Challenge Identifier to {}", challengeIdentifier);
253 - this.challengeIdentifier = challengeIdentifier;
254 - }
255 -
256 - /**
257 - * Gets the challenge EAP identifier set by the RADIUS.
258 - *
259 - * @return The challenge EAP identifier.
260 - */
261 - protected byte challengeIdentifier() {
262 - return this.challengeIdentifier;
263 - }
264 -
265 -
266 - /**
267 - * Set the challenge state info issued by the RADIUS.
268 - *
269 - * @param challengeState The challenge state from the RADIUS.
270 - */
271 - protected void setChallengeState(byte[] challengeState) {
272 - log.info("Set Challenge State");
273 - this.challengeState = challengeState;
274 - }
275 -
276 - /**
277 - * Gets the challenge state set by the RADIUS.
278 - *
279 - * @return The challenge state.
280 - */
281 - protected byte[] challengeState() {
282 - return this.challengeState;
283 - }
284 -
285 - /**
286 - * Set the username.
287 - *
288 - * @param username The username sent to the RADIUS upon access request.
289 - */
290 - protected void setUsername(byte[] username) {
291 - this.username = username;
292 - }
293 -
294 -
295 - /**
296 - * Gets the username.
297 - *
298 - * @return The requestAuthenticator.
299 - */
300 - protected byte[] requestAuthenticator() {
301 - return this.requestAuthenticator;
302 - }
303 -
304 - /**
305 - * Sets the authenticator.
306 - *
307 - * @param authenticator The username sent to the RADIUS upon access request.
308 - */
309 - protected void setRequestAuthenticator(byte[] authenticator) {
310 - this.requestAuthenticator = authenticator;
311 - }
312 -
313 -
314 - /**
315 - * Gets the username.
316 - *
317 - * @return The username.
318 - */
319 - protected byte[] username() {
320 - return this.username;
321 - }
322 -
323 - /**
324 - * Return the identifier of the state machine.
325 - *
326 - * @return The state machine identifier.
327 - */
328 - public byte identifier() {
329 - return (byte) this.identifier;
330 - }
331 -
332 -
333 - protected void deleteIdentifier() {
334 - if (this.identifier != -1) {
335 - log.info("Freeing up " + this.identifier);
336 - //this state machine should be deleted and free up the identifier
337 - StateMachine.bitSet.clear(this.identifier);
338 - this.identifier = -1;
339 - }
340 - }
341 -
342 -
343 - /**
344 - * Move to the next state.
345 - *
346 - * @param msg message
347 - */
348 - private void next(int msg) {
349 - currentState = transition[currentState][msg];
350 - log.info("Current State " + currentState);
351 - }
352 -
353 - /**
354 - * Client has requested the start action to allow network access.
355 - *
356 - * @throws StateMachineException if authentication protocol is violated
357 - */
358 - public void start() throws StateMachineException {
359 - states[currentState].start();
360 - //move to the next state
361 - next(TRANSITION_START);
362 - createIdentifier();
363 - identifierMap.put(identifier, this);
364 - }
365 -
366 - /**
367 - * An Identification information has been sent by the supplicant.
368 - * Move to the next state if possible.
369 - *
370 - * @throws StateMachineException if authentication protocol is violated
371 - */
372 - public void requestAccess() throws StateMachineException {
373 - states[currentState].requestAccess();
374 - //move to the next state
375 - next(TRANSITION_REQUEST_ACCESS);
376 - }
377 -
378 - /**
379 - * RADIUS has accepted the identification.
380 - * Move to the next state if possible.
381 - *
382 - * @throws StateMachineException if authentication protocol is violated
383 - */
384 - public void authorizeAccess() throws StateMachineException {
385 - states[currentState].radiusAccepted();
386 - //move to the next state
387 - next(TRANSITION_AUTHORIZE_ACCESS);
388 -
389 - // TODO: put in calls to launch vSG here
390 -
391 - deleteIdentifier();
392 - }
393 -
394 - /**
395 - * RADIUS has denied the identification.
396 - * Move to the next state if possible.
397 - *
398 - * @throws StateMachineException if authentication protocol is violated
399 - */
400 - public void denyAccess() throws StateMachineException {
401 - states[currentState].radiusDenied();
402 - //move to the next state
403 - next(TRANSITION_DENY_ACCESS);
404 - deleteIdentifier();
405 - }
406 -
407 - /**
408 - * Logoff request has been requested.
409 - * Move to the next state if possible.
410 - *
411 - * @throws StateMachineException if authentication protocol is violated
412 - */
413 - public void logoff() throws StateMachineException {
414 - states[currentState].logoff();
415 - //move to the next state
416 - next(TRANSITION_LOGOFF);
417 - }
418 -
419 - /**
420 - * Gets the current state.
421 - *
422 - * @return The current state. Could be STATE_IDLE, STATE_STARTED, STATE_PENDING, STATE_AUTHORIZED,
423 - * STATE_UNAUTHORIZED.
424 - */
425 - public int state() {
426 - return currentState;
427 - }
428 -
429 - @Override
430 - public String toString() {
431 - return ("sessionId: " + this.sessionId) + "\t" + ("identifier: " + this.identifier) + "\t" +
432 - ("state: " + this.currentState);
433 - }
434 -
435 - abstract class State {
436 - private final Logger log = getLogger(getClass());
437 -
438 - private String name = "State";
439 -
440 - public void start() throws StateMachineInvalidTransitionException {
441 - log.warn("START transition from this state is not allowed.");
442 - }
443 -
444 - public void requestAccess() throws StateMachineInvalidTransitionException {
445 - log.warn("REQUEST ACCESS transition from this state is not allowed.");
446 - }
447 -
448 - public void radiusAccepted() throws StateMachineInvalidTransitionException {
449 - log.warn("AUTHORIZE ACCESS transition from this state is not allowed.");
450 - }
451 -
452 - public void radiusDenied() throws StateMachineInvalidTransitionException {
453 - log.warn("DENY ACCESS transition from this state is not allowed.");
454 - }
455 -
456 - public void logoff() throws StateMachineInvalidTransitionException {
457 - log.warn("LOGOFF transition from this state is not allowed.");
458 - }
459 - }
460 -
461 - /**
462 - * Idle state: supplicant is logged of from the network.
463 - */
464 - class Idle extends State {
465 - private final Logger log = getLogger(getClass());
466 - private String name = "IDLE_STATE";
467 -
468 - public void start() {
469 - log.info("Moving from IDLE state to STARTED state.");
470 - }
471 - }
472 -
473 - /**
474 - * Started state: supplicant has entered the network and informed the authenticator.
475 - */
476 - class Started extends State {
477 - private final Logger log = getLogger(getClass());
478 - private String name = "STARTED_STATE";
479 -
480 - public void requestAccess() {
481 - log.info("Moving from STARTED state to PENDING state.");
482 - }
483 - }
484 -
485 - /**
486 - * Pending state: supplicant has been identified by the authenticator but has not access yet.
487 - */
488 - class Pending extends State {
489 - private final Logger log = getLogger(getClass());
490 - private String name = "PENDING_STATE";
491 -
492 - public void radiusAccepted() {
493 - log.info("Moving from PENDING state to AUTHORIZED state.");
494 - }
495 -
496 - public void radiusDenied() {
497 - log.info("Moving from PENDING state to UNAUTHORIZED state.");
498 - }
499 - }
500 -
501 - /**
502 - * Authorized state: supplicant port has been accepted, access is granted.
503 - */
504 - class Authorized extends State {
505 - private final Logger log = getLogger(getClass());
506 - private String name = "AUTHORIZED_STATE";
507 -
508 - public void start() {
509 - log.info("Moving from AUTHORIZED state to STARTED state.");
510 - }
511 -
512 - public void logoff() {
513 -
514 - log.info("Moving from AUTHORIZED state to IDLE state.");
515 - }
516 - }
517 -
518 - /**
519 - * Unauthorized state: supplicant port has been rejected, access is denied.
520 - */
521 - class Unauthorized extends State {
522 - private final Logger log = getLogger(getClass());
523 - private String name = "UNAUTHORIZED_STATE";
524 -
525 - public void logoff() {
526 - log.info("Moving from UNAUTHORIZED state to IDLE state.");
527 - }
528 - }
529 -
530 -
531 -}
1 -/*
2 - *
3 - * Copyright 2015 AT&T Foundry
4 - *
5 - * Licensed under the Apache License, Version 2.0 (the "License");
6 - * you may not use this file except in compliance with the License.
7 - * You may obtain a copy of the License at
8 - *
9 - * http://www.apache.org/licenses/LICENSE-2.0
10 - *
11 - * Unless required by applicable law or agreed to in writing, software
12 - * distributed under the License is distributed on an "AS IS" BASIS,
13 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - * See the License for the specific language governing permissions and
15 - * limitations under the License.
16 - *
17 - */
18 -package org.onosproject.aaa;
19 -
20 -/**
21 - * Exception for the State Machine.
22 - */
23 -class StateMachineException extends Exception {
24 - public StateMachineException(String message) {
25 - super(message);
26 -
27 - }
28 -}
1 -/*
2 - *
3 - * Copyright 2015 AT&T Foundry
4 - *
5 - * Licensed under the Apache License, Version 2.0 (the "License");
6 - * you may not use this file except in compliance with the License.
7 - * You may obtain a copy of the License at
8 - *
9 - * http://www.apache.org/licenses/LICENSE-2.0
10 - *
11 - * Unless required by applicable law or agreed to in writing, software
12 - * distributed under the License is distributed on an "AS IS" BASIS,
13 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - * See the License for the specific language governing permissions and
15 - * limitations under the License.
16 - *
17 - */
18 -package org.onosproject.aaa;
19 -
20 -/**
21 - * Exception raised when the transition from one state to another is invalid.
22 - */
23 -class StateMachineInvalidTransitionException extends StateMachineException {
24 - public StateMachineInvalidTransitionException(String message) {
25 - super(message);
26 - }
27 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * AAA implmentation.
19 - */
20 -package org.onosproject.aaa;
1 -<!--
2 - ~ Copyright 2016-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
17 -
18 - <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
19 - <command>
20 - <action class="org.onosproject.aaa.AaaShowUsersCommand"/>
21 - </command>
22 - </command-bundle>
23 -</blueprint>
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.aaa;
17 -
18 -import org.junit.Before;
19 -import org.junit.Ignore;
20 -import org.junit.Test;
21 -import org.onlab.packet.EAP;
22 -import org.onlab.packet.EAPOL;
23 -import org.onlab.packet.Ethernet;
24 -import org.onosproject.core.CoreServiceAdapter;
25 -import org.onosproject.net.config.Config;
26 -import org.onosproject.net.config.NetworkConfigRegistryAdapter;
27 -
28 -import static org.hamcrest.Matchers.is;
29 -import static org.hamcrest.Matchers.notNullValue;
30 -import static org.junit.Assert.assertThat;
31 -
32 -/**
33 - * Set of tests of the ONOS application component. These use an existing RADIUS
34 - * server and sends live packets over the network to it.
35 - */
36 -@Ignore ("This should not be run as part of the standard build")
37 -public class AaaIntegrationTest extends AaaTestBase {
38 -
39 - private AaaManager aaa;
40 -
41 - /**
42 - * Mocks the network config registry.
43 - */
44 - @SuppressWarnings("unchecked")
45 - static final class TestNetworkConfigRegistry
46 - extends NetworkConfigRegistryAdapter {
47 - @Override
48 - public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
49 - return (C) new AaaConfig();
50 - }
51 - }
52 -
53 - /**
54 - * Sets up the services required by the AAA application.
55 - */
56 - @Before
57 - public void setUp() {
58 - aaa = new AaaManager();
59 - aaa.netCfgService = new TestNetworkConfigRegistry();
60 - aaa.coreService = new CoreServiceAdapter();
61 - aaa.packetService = new MockPacketService();
62 - aaa.activate();
63 - }
64 -
65 - /**
66 - * Fetches the sent packet at the given index. The requested packet
67 - * must be the last packet on the list.
68 - *
69 - * @param index index into sent packets array
70 - * @return packet
71 - */
72 - private Ethernet fetchPacket(int index) {
73 - for (int iteration = 0; iteration < 20; iteration++) {
74 - if (savedPackets.size() > index) {
75 - return (Ethernet) savedPackets.get(index);
76 - } else {
77 - try {
78 - Thread.sleep(250);
79 - } catch (Exception ex) {
80 - return null;
81 - }
82 - }
83 - }
84 - return null;
85 - }
86 -
87 - /**
88 - * Tests the authentication path through the AAA application by sending
89 - * packets to the RADIUS server and checking the state machine
90 - * transitions.
91 - *
92 - * @throws Exception when an unhandled error occurs
93 - */
94 - @Test
95 - public void testAuthentication() throws Exception {
96 -
97 - // (1) Supplicant start up
98 -
99 - Ethernet startPacket = constructSupplicantStartPacket();
100 - sendPacket(startPacket);
101 -
102 - Ethernet responsePacket = fetchPacket(0);
103 - assertThat(responsePacket, notNullValue());
104 - checkRadiusPacket(aaa, responsePacket, EAP.REQUEST);
105 -
106 - // (2) Supplicant identify
107 -
108 - Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
109 - sendPacket(identifyPacket);
110 -
111 - // State machine should have been created by now
112 -
113 - StateMachine stateMachine =
114 - StateMachine.lookupStateMachineBySessionId(SESSION_ID);
115 - assertThat(stateMachine, notNullValue());
116 - assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
117 -
118 - // (3) RADIUS MD5 challenge
119 -
120 - Ethernet radiusChallengeMD5Packet = fetchPacket(1);
121 - assertThat(radiusChallengeMD5Packet, notNullValue());
122 - checkRadiusPacket(aaa, radiusChallengeMD5Packet, EAP.REQUEST);
123 -
124 -
125 - // (4) Supplicant MD5 response
126 -
127 - Ethernet md5RadiusPacket =
128 - constructSupplicantIdentifyPacket(stateMachine,
129 - EAP.ATTR_MD5,
130 - stateMachine.challengeIdentifier(),
131 - radiusChallengeMD5Packet);
132 - sendPacket(md5RadiusPacket);
133 -
134 -
135 - // (5) RADIUS Success
136 -
137 - Ethernet successRadiusPacket = fetchPacket(2);
138 - assertThat(successRadiusPacket, notNullValue());
139 - EAPOL successEapol = (EAPOL) successRadiusPacket.getPayload();
140 - EAP successEap = (EAP) successEapol.getPayload();
141 - assertThat(successEap.getCode(), is(EAP.SUCCESS));
142 -
143 - // State machine should be in authorized state
144 -
145 - assertThat(stateMachine, notNullValue());
146 - assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
147 -
148 - }
149 -
150 -}
151 -
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.aaa;
17 -
18 -import com.google.common.base.Charsets;
19 -import org.junit.After;
20 -import org.junit.Before;
21 -import org.junit.Test;
22 -import org.onlab.packet.BasePacket;
23 -import org.onlab.packet.DeserializationException;
24 -import org.onlab.packet.EAP;
25 -import org.onlab.packet.Ethernet;
26 -import org.onlab.packet.IpAddress;
27 -import org.onlab.packet.RADIUS;
28 -import org.onlab.packet.RADIUSAttribute;
29 -import org.onosproject.core.CoreServiceAdapter;
30 -import org.onosproject.net.config.Config;
31 -import org.onosproject.net.config.NetworkConfigRegistryAdapter;
32 -
33 -import java.net.InetAddress;
34 -import java.net.UnknownHostException;
35 -
36 -import static org.hamcrest.Matchers.is;
37 -import static org.hamcrest.Matchers.notNullValue;
38 -import static org.junit.Assert.assertThat;
39 -
40 -/**
41 - * Set of tests of the ONOS application component.
42 - */
43 -public class AaaManagerTest extends AaaTestBase {
44 -
45 - static final String BAD_IP_ADDRESS = "198.51.100.0";
46 -
47 - private AaaManager aaaManager;
48 -
49 - class AaaManagerWithoutRadiusServer extends AaaManager {
50 - protected void sendRadiusPacket(RADIUS radiusPacket) {
51 - savePacket(radiusPacket);
52 - }
53 - }
54 -
55 - /**
56 - * Mocks the AAAConfig class to force usage of an unroutable address for the
57 - * RADIUS server.
58 - */
59 - static class MockAaaConfig extends AaaConfig {
60 - @Override
61 - public InetAddress radiusIp() {
62 - try {
63 - return InetAddress.getByName(BAD_IP_ADDRESS);
64 - } catch (UnknownHostException ex) {
65 - // can't happen
66 - throw new IllegalStateException(ex);
67 - }
68 - }
69 - }
70 -
71 - /**
72 - * Mocks the network config registry.
73 - */
74 - @SuppressWarnings("unchecked")
75 - private static final class TestNetworkConfigRegistry
76 - extends NetworkConfigRegistryAdapter {
77 - @Override
78 - public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
79 - AaaConfig aaaConfig = new MockAaaConfig();
80 - return (C) aaaConfig;
81 - }
82 - }
83 -
84 - /**
85 - * Constructs an Ethernet packet containing a RADIUS challenge
86 - * packet.
87 - *
88 - * @param challengeCode code to use in challenge packet
89 - * @param challengeType type to use in challenge packet
90 - * @return Ethernet packet
91 - */
92 - private RADIUS constructRadiusCodeAccessChallengePacket(byte challengeCode, byte challengeType) {
93 -
94 - String challenge = "12345678901234567";
95 -
96 - EAP eap = new EAP(challengeType, (byte) 1, challengeType,
97 - challenge.getBytes(Charsets.US_ASCII));
98 - eap.setIdentifier((byte) 1);
99 -
100 - RADIUS radius = new RADIUS();
101 - radius.setCode(challengeCode);
102 -
103 - radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
104 - challenge.getBytes(Charsets.US_ASCII));
105 -
106 - radius.setPayload(eap);
107 - radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
108 - eap.serialize());
109 -
110 - return radius;
111 - }
112 -
113 - /**
114 - * Sets up the services required by the AAA application.
115 - */
116 - @Before
117 - public void setUp() {
118 - aaaManager = new AaaManagerWithoutRadiusServer();
119 - aaaManager.netCfgService = new TestNetworkConfigRegistry();
120 - aaaManager.coreService = new CoreServiceAdapter();
121 - aaaManager.packetService = new MockPacketService();
122 - aaaManager.activate();
123 - }
124 -
125 - /**
126 - * Tears down the AAA application.
127 - */
128 - @After
129 - public void tearDown() {
130 - aaaManager.deactivate();
131 - }
132 -
133 - /**
134 - * Extracts the RADIUS packet from a packet sent by the supplicant.
135 - *
136 - * @param radius RADIUS packet sent by the supplicant
137 - * @throws DeserializationException if deserialization of the packet contents
138 - * fails.
139 - */
140 - private void checkRadiusPacketFromSupplicant(RADIUS radius)
141 - throws DeserializationException {
142 - assertThat(radius, notNullValue());
143 -
144 - EAP eap = radius.decapsulateMessage();
145 - assertThat(eap, notNullValue());
146 - }
147 -
148 - /**
149 - * Fetches the sent packet at the given index. The requested packet
150 - * must be the last packet on the list.
151 - *
152 - * @param index index into sent packets array
153 - * @return packet
154 - */
155 - private BasePacket fetchPacket(int index) {
156 - BasePacket packet = savedPackets.get(index);
157 - assertThat(packet, notNullValue());
158 - return packet;
159 - }
160 -
161 - /**
162 - * Tests the authentication path through the AAA application.
163 - *
164 - * @throws DeserializationException if packed deserialization fails.
165 - */
166 - @Test
167 - public void testAuthentication() throws Exception {
168 -
169 - // (1) Supplicant start up
170 -
171 - Ethernet startPacket = constructSupplicantStartPacket();
172 - sendPacket(startPacket);
173 -
174 - Ethernet responsePacket = (Ethernet) fetchPacket(0);
175 - checkRadiusPacket(aaaManager, responsePacket, EAP.ATTR_IDENTITY);
176 -
177 - // (2) Supplicant identify
178 -
179 - Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
180 - sendPacket(identifyPacket);
181 -
182 - RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
183 -
184 - checkRadiusPacketFromSupplicant(radiusIdentifyPacket);
185 -
186 - assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
187 - assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
188 - is("testuser"));
189 -
190 - IpAddress nasIp =
191 - IpAddress.valueOf(IpAddress.Version.INET,
192 - radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
193 - .getValue());
194 - assertThat(nasIp.toString(), is(aaaManager.nasIpAddress.getHostAddress()));
195 -
196 - // State machine should have been created by now
197 -
198 - StateMachine stateMachine =
199 - StateMachine.lookupStateMachineBySessionId(SESSION_ID);
200 - assertThat(stateMachine, notNullValue());
201 - assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
202 -
203 - // (3) RADIUS MD5 challenge
204 -
205 - RADIUS radiusCodeAccessChallengePacket =
206 - constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5);
207 - aaaManager.radiusListener.handleRadiusPacket(radiusCodeAccessChallengePacket);
208 -
209 - Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
210 - checkRadiusPacket(aaaManager, radiusChallengeMD5Packet, EAP.ATTR_MD5);
211 -
212 - // (4) Supplicant MD5 response
213 -
214 - Ethernet md5RadiusPacket =
215 - constructSupplicantIdentifyPacket(stateMachine,
216 - EAP.ATTR_MD5,
217 - stateMachine.challengeIdentifier(),
218 - radiusChallengeMD5Packet);
219 - sendPacket(md5RadiusPacket);
220 -
221 - RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
222 -
223 - checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
224 - assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 0));
225 - assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
226 -
227 - // State machine should be in pending state
228 -
229 - assertThat(stateMachine, notNullValue());
230 - assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
231 -
232 - // (5) RADIUS Success
233 -
234 - RADIUS successPacket =
235 - constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT, EAP.SUCCESS);
236 - aaaManager.radiusListener.handleRadiusPacket((successPacket));
237 - Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);
238 -
239 - checkRadiusPacket(aaaManager, supplicantSuccessPacket, EAP.SUCCESS);
240 -
241 - // State machine should be in authorized state
242 -
243 - assertThat(stateMachine, notNullValue());
244 - assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
245 -
246 - }
247 -
248 - /**
249 - * Tests the default configuration.
250 - */
251 - @Test
252 - public void testConfig() {
253 - assertThat(aaaManager.nasIpAddress.getHostAddress(), is(AaaConfig.DEFAULT_NAS_IP));
254 - assertThat(aaaManager.nasMacAddress, is(AaaConfig.DEFAULT_NAS_MAC));
255 - assertThat(aaaManager.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
256 - assertThat(aaaManager.radiusMacAddress, is(AaaConfig.DEFAULT_RADIUS_MAC));
257 - }
258 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.aaa;
17 -
18 -import org.onlab.packet.BasePacket;
19 -import org.onlab.packet.EAP;
20 -import org.onlab.packet.EAPOL;
21 -import org.onlab.packet.EthType;
22 -import org.onlab.packet.Ethernet;
23 -import org.onlab.packet.MacAddress;
24 -import org.onosproject.net.packet.DefaultInboundPacket;
25 -import org.onosproject.net.packet.DefaultPacketContext;
26 -import org.onosproject.net.packet.InboundPacket;
27 -import org.onosproject.net.packet.OutboundPacket;
28 -import org.onosproject.net.packet.PacketContext;
29 -import org.onosproject.net.packet.PacketProcessor;
30 -import org.onosproject.net.packet.PacketServiceAdapter;
31 -
32 -import java.nio.ByteBuffer;
33 -import java.security.MessageDigest;
34 -import java.util.LinkedList;
35 -import java.util.List;
36 -
37 -import static org.hamcrest.Matchers.instanceOf;
38 -import static org.hamcrest.Matchers.is;
39 -import static org.hamcrest.Matchers.notNullValue;
40 -import static org.junit.Assert.assertThat;
41 -import static org.junit.Assert.fail;
42 -import static org.onosproject.net.NetTestTools.connectPoint;
43 -
44 -/**
45 - * Common methods for AAA app testing.
46 - */
47 -public class AaaTestBase {
48 -
49 - MacAddress clientMac = MacAddress.valueOf("1a:1a:1a:1a:1a:1a");
50 - MacAddress serverMac = MacAddress.valueOf("2a:2a:2a:2a:2a:2a");
51 -
52 - // Our session id will be the device ID ("of:1") with the port ("1") concatenated
53 - static final String SESSION_ID = "of:11";
54 -
55 - List<BasePacket> savedPackets = new LinkedList<>();
56 - PacketProcessor packetProcessor;
57 -
58 - /**
59 - * Saves the given packet onto the saved packets list.
60 - *
61 - * @param packet packet to save
62 - */
63 - void savePacket(BasePacket packet) {
64 - savedPackets.add(packet);
65 - }
66 -
67 - /**
68 - * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
69 - */
70 - class MockPacketService extends PacketServiceAdapter {
71 -
72 - @Override
73 - public void addProcessor(PacketProcessor processor, int priority) {
74 - packetProcessor = processor;
75 - }
76 -
77 - @Override
78 - public void emit(OutboundPacket packet) {
79 - try {
80 - Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
81 - 0, packet.data().array().length);
82 - savePacket(eth);
83 - } catch (Exception e) {
84 - fail(e.getMessage());
85 - }
86 - }
87 - }
88 -
89 - /**
90 - * Mocks the DefaultPacketContext.
91 - */
92 - final class TestPacketContext extends DefaultPacketContext {
93 -
94 - private TestPacketContext(long time, InboundPacket inPkt,
95 - OutboundPacket outPkt, boolean block) {
96 - super(time, inPkt, outPkt, block);
97 - }
98 -
99 - @Override
100 - public void send() {
101 - // We don't send anything out.
102 - }
103 - }
104 -
105 - /**
106 - * Sends an Ethernet packet to the process method of the Packet Processor.
107 - *
108 - * @param reply Ethernet packet
109 - */
110 - void sendPacket(Ethernet reply) {
111 - final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());
112 - InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1),
113 - reply,
114 - byteBuffer);
115 -
116 - PacketContext context = new TestPacketContext(127L, inPacket, null, false);
117 - packetProcessor.process(context);
118 - }
119 -
120 - /**
121 - * Constructs an Ethernet packet containing identification payload.
122 - *
123 - * @return Ethernet packet
124 - */
125 - Ethernet constructSupplicantIdentifyPacket(StateMachine stateMachine,
126 - byte type,
127 - byte id,
128 - Ethernet radiusChallenge)
129 - throws Exception {
130 - Ethernet eth = new Ethernet();
131 - eth.setDestinationMACAddress(clientMac.toBytes());
132 - eth.setSourceMACAddress(serverMac.toBytes());
133 - eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
134 - eth.setVlanID((short) 2);
135 -
136 - String username = "testuser";
137 - byte[] data = username.getBytes();
138 -
139 -
140 - if (type == EAP.ATTR_MD5) {
141 - String password = "testpassword";
142 - EAPOL eapol = (EAPOL) radiusChallenge.getPayload();
143 - EAP eap = (EAP) eapol.getPayload();
144 -
145 - byte[] identifier = new byte[password.length() + eap.getData().length];
146 -
147 - identifier[0] = stateMachine.challengeIdentifier();
148 - System.arraycopy(password.getBytes(), 0, identifier, 1, password.length());
149 - System.arraycopy(eap.getData(), 1, identifier, 1 + password.length(), 16);
150 -
151 - MessageDigest md = MessageDigest.getInstance("MD5");
152 - byte[] hash = md.digest(identifier);
153 - data = new byte[17];
154 - data[0] = (byte) 16;
155 - System.arraycopy(hash, 0, data, 1, 16);
156 - }
157 - EAP eap = new EAP(EAP.RESPONSE, (byte) 1, type,
158 - data);
159 - eap.setIdentifier(id);
160 -
161 - // eapol header
162 - EAPOL eapol = new EAPOL();
163 - eapol.setEapolType(EAPOL.EAPOL_PACKET);
164 - eapol.setPacketLength(eap.getLength());
165 -
166 - // eap part
167 - eapol.setPayload(eap);
168 -
169 - eth.setPayload(eapol);
170 - eth.setPad(true);
171 - return eth;
172 - }
173 -
174 - /**
175 - * Constructs an Ethernet packet containing a EAPOL_START Payload.
176 - *
177 - * @return Ethernet packet
178 - */
179 - Ethernet constructSupplicantStartPacket() {
180 - Ethernet eth = new Ethernet();
181 - eth.setDestinationMACAddress(clientMac.toBytes());
182 - eth.setSourceMACAddress(serverMac.toBytes());
183 - eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
184 - eth.setVlanID((short) 2);
185 -
186 - EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 2, EAPOL.EAPOL_START, null);
187 -
188 - // eapol header
189 - EAPOL eapol = new EAPOL();
190 - eapol.setEapolType(EAPOL.EAPOL_START);
191 - eapol.setPacketLength(eap.getLength());
192 -
193 - // eap part
194 - eapol.setPayload(eap);
195 -
196 - eth.setPayload(eapol);
197 - eth.setPad(true);
198 - return eth;
199 - }
200 -
201 - /**
202 - * Checks the contents of a RADIUS packet being sent to the RADIUS server.
203 - *
204 - * @param radiusPacket packet to check
205 - * @param code expected code
206 - */
207 - void checkRadiusPacket(AaaManager aaaManager, Ethernet radiusPacket, byte code) {
208 -
209 - assertThat(radiusPacket.getSourceMAC(),
210 - is(MacAddress.valueOf(aaaManager.nasMacAddress)));
211 - assertThat(radiusPacket.getDestinationMAC(), is(serverMac));
212 -
213 - assertThat(radiusPacket.getPayload(), instanceOf(EAPOL.class));
214 - EAPOL eapol = (EAPOL) radiusPacket.getPayload();
215 - assertThat(eapol, notNullValue());
216 -
217 - assertThat(eapol.getEapolType(), is(EAPOL.EAPOL_PACKET));
218 - assertThat(eapol.getPayload(), instanceOf(EAP.class));
219 - EAP eap = (EAP) eapol.getPayload();
220 - assertThat(eap, notNullValue());
221 -
222 - assertThat(eap.getCode(), is(code));
223 - }
224 -}
1 -/*
2 - *
3 - * Copyright 2015 AT&T Foundry
4 - *
5 - * Licensed under the Apache License, Version 2.0 (the "License");
6 - * you may not use this file except in compliance with the License.
7 - * You may obtain a copy of the License at
8 - *
9 - * http://www.apache.org/licenses/LICENSE-2.0
10 - *
11 - * Unless required by applicable law or agreed to in writing, software
12 - * distributed under the License is distributed on an "AS IS" BASIS,
13 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - * See the License for the specific language governing permissions and
15 - * limitations under the License.
16 - *
17 - */
18 -package org.onosproject.aaa;
19 -
20 -import org.junit.After;
21 -import org.junit.Assert;
22 -import org.junit.Before;
23 -import org.junit.Test;
24 -
25 -import static org.junit.Assert.assertEquals;
26 -import static org.junit.Assert.assertNull;
27 -
28 -
29 -public class StateMachineTest {
30 - StateMachine stateMachine = null;
31 -
32 - @Before
33 - public void setUp() {
34 - System.out.println("Set Up.");
35 - StateMachine.bitSet.clear();
36 - StateMachine.initializeMaps();
37 - stateMachine = new StateMachine("session0");
38 - }
39 -
40 - @After
41 - public void tearDown() {
42 - System.out.println("Tear Down.");
43 - StateMachine.bitSet.clear();
44 - StateMachine.destroyMaps();
45 - stateMachine = null;
46 - }
47 -
48 - @Test
49 - /**
50 - * Test all the basic inputs from state to state: IDLE -> STARTED -> PENDING -> AUTHORIZED -> IDLE
51 - */
52 - public void basic() throws StateMachineException {
53 - System.out.println("======= BASIC =======.");
54 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
55 -
56 - stateMachine.start();
57 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_STARTED);
58 -
59 - stateMachine.requestAccess();
60 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
61 -
62 - stateMachine.authorizeAccess();
63 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_AUTHORIZED);
64 -
65 - stateMachine.logoff();
66 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
67 - }
68 -
69 - @Test
70 - /**
71 - * Test all inputs from an IDLE state (starting with the ones that are not impacting the current state)
72 - */
73 - public void testIdleState() throws StateMachineException {
74 - System.out.println("======= IDLE STATE TEST =======.");
75 - stateMachine.requestAccess();
76 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
77 -
78 - stateMachine.authorizeAccess();
79 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
80 -
81 - stateMachine.denyAccess();
82 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
83 -
84 - stateMachine.logoff();
85 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
86 -
87 - stateMachine.start();
88 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_STARTED);
89 - }
90 -
91 - @Test
92 - /**
93 - * Test all inputs from an STARTED state (starting with the ones that are not impacting the current state)
94 - */
95 - public void testStartedState() throws StateMachineException {
96 - System.out.println("======= STARTED STATE TEST =======.");
97 - stateMachine.start();
98 -
99 - stateMachine.authorizeAccess();
100 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_STARTED);
101 -
102 - stateMachine.denyAccess();
103 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_STARTED);
104 -
105 - stateMachine.logoff();
106 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_STARTED);
107 -
108 - stateMachine.start();
109 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_STARTED);
110 -
111 - stateMachine.requestAccess();
112 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
113 - }
114 -
115 - @Test
116 - /**
117 - * Test all inputs from a PENDING state (starting with the ones that are not impacting the current state).
118 - * The next valid state for this test is AUTHORIZED
119 - */
120 - public void testPendingStateToAuthorized() throws StateMachineException {
121 - System.out.println("======= PENDING STATE TEST (AUTHORIZED) =======.");
122 - stateMachine.start();
123 - stateMachine.requestAccess();
124 -
125 - stateMachine.logoff();
126 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
127 -
128 - stateMachine.start();
129 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
130 -
131 - stateMachine.requestAccess();
132 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
133 -
134 - stateMachine.authorizeAccess();
135 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_AUTHORIZED);
136 -
137 - stateMachine.denyAccess();
138 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_AUTHORIZED);
139 - }
140 -
141 - @Test
142 - /**
143 - * Test all inputs from an PENDING state (starting with the ones that are not impacting the current state).
144 - * The next valid state for this test is UNAUTHORIZED
145 - */
146 - public void testPendingStateToUnauthorized() throws StateMachineException {
147 - System.out.println("======= PENDING STATE TEST (DENIED) =======.");
148 - stateMachine.start();
149 - stateMachine.requestAccess();
150 -
151 - stateMachine.logoff();
152 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
153 -
154 - stateMachine.start();
155 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
156 -
157 - stateMachine.requestAccess();
158 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
159 -
160 - stateMachine.denyAccess();
161 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_UNAUTHORIZED);
162 -
163 - stateMachine.authorizeAccess();
164 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_UNAUTHORIZED);
165 - }
166 -
167 - @Test
168 - /**
169 - * Test all inputs from an AUTHORIZED state (starting with the ones that are not impacting the current state).
170 - */
171 - public void testAuthorizedState() throws StateMachineException {
172 - System.out.println("======= AUTHORIZED STATE TEST =======.");
173 - stateMachine.start();
174 - stateMachine.requestAccess();
175 - stateMachine.authorizeAccess();
176 -
177 - stateMachine.start();
178 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_STARTED);
179 -
180 - stateMachine.requestAccess();
181 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_PENDING);
182 -
183 - stateMachine.authorizeAccess();
184 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_AUTHORIZED);
185 -
186 - stateMachine.denyAccess();
187 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_AUTHORIZED);
188 -
189 - stateMachine.logoff();
190 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
191 - }
192 -
193 - @Test
194 - /**
195 - * Test all inputs from an UNAUTHORIZED state (starting with the ones that are not impacting the current state).
196 - */
197 - public void testUnauthorizedState() throws StateMachineException {
198 - System.out.println("======= UNAUTHORIZED STATE TEST =======.");
199 - stateMachine.start();
200 - stateMachine.requestAccess();
201 - stateMachine.denyAccess();
202 -
203 - stateMachine.start();
204 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_UNAUTHORIZED);
205 -
206 - stateMachine.requestAccess();
207 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_UNAUTHORIZED);
208 -
209 - stateMachine.authorizeAccess();
210 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_UNAUTHORIZED);
211 -
212 - stateMachine.denyAccess();
213 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_UNAUTHORIZED);
214 -
215 - stateMachine.logoff();
216 - Assert.assertEquals(stateMachine.state(), StateMachine.STATE_IDLE);
217 - }
218 -
219 -
220 - @Test
221 - public void testIdentifierAvailability() throws StateMachineException {
222 - System.out.println("======= IDENTIFIER TEST =======.");
223 - byte identifier = stateMachine.identifier();
224 - System.out.println("State: " + stateMachine.state());
225 - System.out.println("Identifier: " + Byte.toUnsignedInt(identifier));
226 - Assert.assertEquals(-1, identifier);
227 - stateMachine.start();
228 -
229 -
230 - StateMachine sm247 = null;
231 - StateMachine sm3 = null;
232 -
233 -
234 - //create 255 others state machines
235 - for (int i = 1; i <= 255; i++) {
236 - StateMachine sm = new StateMachine("session" + i);
237 - sm.start();
238 - byte id = sm.identifier();
239 - Assert.assertEquals(i, Byte.toUnsignedInt(id));
240 - if (i == 3) {
241 - sm3 = sm;
242 - System.out.println("SM3: " + sm3.toString());
243 - }
244 - if (i == 247) {
245 - sm247 = sm;
246 - System.out.println("SM247: " + sm247.toString());
247 - }
248 - }
249 -
250 - //simulate the state machine for a specific session and logoff so we can free up a spot for an identifier
251 - //let's choose identifier 247 then we free up 3
252 - Assert.assertNotNull(sm247);
253 - sm247.requestAccess();
254 - sm247.authorizeAccess();
255 - sm247.logoff();
256 -
257 - Assert.assertNotNull(sm3);
258 - sm3.requestAccess();
259 - sm3.authorizeAccess();
260 - sm3.logoff();
261 -
262 - StateMachine otherSM3 = new StateMachine("session3b");
263 - otherSM3.start();
264 - otherSM3.requestAccess();
265 - byte id3 = otherSM3.identifier();
266 - Assert.assertEquals(3, Byte.toUnsignedInt(id3));
267 -
268 - StateMachine otherSM247 = new StateMachine("session247b");
269 - otherSM247.start();
270 - otherSM247.requestAccess();
271 - byte id247 = otherSM247.identifier();
272 - Assert.assertEquals(247, Byte.toUnsignedInt(id247));
273 - }
274 -
275 - @Test
276 - public void testSessionIdLookups() {
277 - String sessionId1 = "session1";
278 - String sessionId2 = "session2";
279 - String sessionId3 = "session3";
280 -
281 - StateMachine machine1ShouldBeNull =
282 - StateMachine.lookupStateMachineBySessionId(sessionId1);
283 - assertNull(machine1ShouldBeNull);
284 - StateMachine machine2ShouldBeNull =
285 - StateMachine.lookupStateMachineBySessionId(sessionId2);
286 - assertNull(machine2ShouldBeNull);
287 -
288 - StateMachine stateMachine1 = new StateMachine(sessionId1);
289 - StateMachine stateMachine2 = new StateMachine(sessionId2);
290 -
291 - assertEquals(stateMachine1,
292 - StateMachine.lookupStateMachineBySessionId(sessionId1));
293 - assertEquals(stateMachine2,
294 - StateMachine.lookupStateMachineBySessionId(sessionId2));
295 - assertNull(StateMachine.lookupStateMachineBySessionId(sessionId3));
296 - }
297 -
298 - @Test
299 - public void testIdentifierLookups() throws StateMachineException {
300 - String sessionId1 = "session1";
301 - String sessionId2 = "session2";
302 -
303 - StateMachine machine1ShouldBeNull =
304 - StateMachine.lookupStateMachineById((byte) 1);
305 - assertNull(machine1ShouldBeNull);
306 - StateMachine machine2ShouldBeNull =
307 - StateMachine.lookupStateMachineById((byte) 2);
308 - assertNull(machine2ShouldBeNull);
309 -
310 - StateMachine stateMachine1 = new StateMachine(sessionId1);
311 - stateMachine1.start();
312 - StateMachine stateMachine2 = new StateMachine(sessionId2);
313 - stateMachine2.start();
314 -
315 - assertEquals(stateMachine1,
316 - StateMachine.lookupStateMachineById(stateMachine1.identifier()));
317 - assertEquals(stateMachine2,
318 - StateMachine.lookupStateMachineById(stateMachine2.identifier()));
319 - }
320 -}
1 -COMPILE_DEPS = [
2 - '//lib:CORE_DEPS',
3 -]
4 -
5 -osgi_jar_with_tests (
6 - deps = COMPILE_DEPS,
7 -)
8 -
9 -onos_app (
10 - title = 'CORD Configuration',
11 - category = 'Utility',
12 - url = 'http://onosproject.org',
13 - description = 'CORD configuration meta application.',
14 -)
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onos-apps</artifactId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 -
30 - <artifactId>onos-cord-config</artifactId>
31 - <packaging>bundle</packaging>
32 -
33 - <description>Cord configuration meta applications </description>
34 -
35 - <properties>
36 - <onos.app.name>org.onosproject.cord-config</onos.app.name>
37 - <onos.app.title>Cord Configuratuon Meta Application</onos.app.title>
38 - <onos.app.category>Utility</onos.app.category>
39 - <onos.app.url>http://opencord.org</onos.app.url>
40 - </properties>
41 -
42 - <dependencies>
43 - <dependency>
44 - <groupId>org.onosproject</groupId>
45 - <artifactId>onos-api</artifactId>
46 - </dependency>
47 - </dependencies>
48 -
49 -
50 -</project>
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordconfig.access;
18 -
19 -import com.fasterxml.jackson.databind.JsonNode;
20 -import com.fasterxml.jackson.databind.node.ObjectNode;
21 -import com.google.common.collect.Iterators;
22 -import com.google.common.collect.Maps;
23 -import org.apache.commons.lang.StringUtils;
24 -import org.onlab.packet.MacAddress;
25 -import org.onosproject.net.ConnectPoint;
26 -import org.onosproject.net.DeviceId;
27 -import org.onosproject.net.PortNumber;
28 -import org.onosproject.net.config.Config;
29 -
30 -import java.util.Map;
31 -import java.util.Optional;
32 -
33 -import static org.onosproject.net.config.Config.FieldPresence.MANDATORY;
34 -import static org.onosproject.net.config.Config.FieldPresence.OPTIONAL;
35 -
36 -/**
37 - * Represents configuration for an OLT agent.
38 - */
39 -public class AccessAgentConfig extends Config<DeviceId> {
40 -
41 - private static final String OLTS = "olts";
42 - private static final String AGENT_MAC = "mac";
43 -
44 - // TODO: Remove this, it is only useful as long as XOS doesn't manage this.
45 - private static final String VTN_LOCATION = "vtn-location";
46 -
47 - @Override
48 - public boolean isValid() {
49 - return hasOnlyFields(OLTS, AGENT_MAC, VTN_LOCATION) &&
50 - isMacAddress(AGENT_MAC, MANDATORY) &&
51 - isConnectPoint(VTN_LOCATION, OPTIONAL) &&
52 - isValidOlts();
53 - }
54 -
55 - /**
56 - * Gets the access agent configuration for this device.
57 - *
58 - * @return access agent configuration
59 - */
60 - public AccessAgentData getAgent() {
61 - JsonNode olts = node.get(OLTS);
62 - Map<ConnectPoint, MacAddress> oltMacInfo = Maps.newHashMap();
63 - olts.fields().forEachRemaining(item -> oltMacInfo.put(
64 - new ConnectPoint(subject(), PortNumber.fromString(item.getKey())),
65 - MacAddress.valueOf(item.getValue().asText())));
66 -
67 - MacAddress agentMac = MacAddress.valueOf(node.path(AGENT_MAC).asText());
68 -
69 - JsonNode vtn = node.path(VTN_LOCATION);
70 - Optional<ConnectPoint> vtnLocation;
71 - if (vtn.isMissingNode()) {
72 - vtnLocation = Optional.empty();
73 - } else {
74 - vtnLocation = Optional.of(ConnectPoint.deviceConnectPoint(vtn.asText()));
75 - }
76 -
77 - return new AccessAgentData(subject(), oltMacInfo, agentMac, vtnLocation);
78 - }
79 -
80 - private boolean isValidOlts() {
81 - JsonNode olts = node.get(OLTS);
82 - if (!olts.isObject()) {
83 - return false;
84 - }
85 - return !Iterators.any(olts.fields(), item -> !StringUtils.isNumeric(item.getKey()) ||
86 - !isMacAddress((ObjectNode) olts, item.getKey(), MANDATORY));
87 - }
88 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordconfig.access;
18 -
19 -import com.google.common.collect.ImmutableMap;
20 -import org.onlab.packet.MacAddress;
21 -import org.onosproject.net.ConnectPoint;
22 -import org.onosproject.net.DeviceId;
23 -
24 -import java.util.Map;
25 -import java.util.Optional;
26 -
27 -import static com.google.common.base.Preconditions.checkNotNull;
28 -
29 -/**
30 - * Information about an access agent.
31 - */
32 -public class AccessAgentData {
33 - private static final String DEVICE_ID_MISSING = "Device ID cannot be null";
34 - private static final String OLT_INFO_MISSING = "OLT information cannot be null";
35 - private static final String AGENT_MAC_MISSING = "Agent mac cannot be null";
36 - private static final String VTN_MISSING = "VTN location cannot be null";
37 -
38 -
39 - private final Map<ConnectPoint, MacAddress> oltMacInfo;
40 - private final MacAddress agentMac;
41 - private final Optional<ConnectPoint> vtnLocation;
42 - private final DeviceId deviceId;
43 -
44 -
45 - /**
46 - * Constucts an agent configuration for a given device.
47 - *
48 - * @param deviceId access device id
49 - * @param oltMacInfo a map of olt chips and their mac address
50 - * @param agentMac the mac address of the agent
51 - * @param vtnLocation the location of the agent
52 - */
53 - public AccessAgentData(DeviceId deviceId, Map<ConnectPoint, MacAddress> oltMacInfo,
54 - MacAddress agentMac, Optional<ConnectPoint> vtnLocation) {
55 - this.deviceId = checkNotNull(deviceId, DEVICE_ID_MISSING);
56 - this.oltMacInfo = checkNotNull(oltMacInfo, OLT_INFO_MISSING);
57 - this.agentMac = checkNotNull(agentMac, AGENT_MAC_MISSING);
58 - this.vtnLocation = checkNotNull(vtnLocation, VTN_MISSING);
59 - }
60 -
61 - /**
62 - * Retrieves the access device ID.
63 - *
64 - * @return device ID
65 - */
66 - public DeviceId deviceId() {
67 - return deviceId;
68 - }
69 -
70 - /**
71 - * Returns the mapping of olt chips to mac addresses. Each chip is
72 - * symbolized by a connect point.
73 - *
74 - * @return a mapping of chips (as connect points) to mac addresses
75 - */
76 - public Map<ConnectPoint, MacAddress> getOltMacInfo() {
77 - return ImmutableMap.copyOf(oltMacInfo);
78 - }
79 -
80 - /**
81 - * Reuturns the agents mac address.
82 - *
83 - * @return a mac address
84 - */
85 - public MacAddress getAgentMac() {
86 - return agentMac;
87 - }
88 -
89 - /**
90 - * Returns the location of the agent.
91 - *
92 - * @return a connection point
93 - */
94 - public Optional<ConnectPoint> getVtnLocation() {
95 - return vtnLocation;
96 - }
97 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordconfig.access;
18 -
19 -import org.onosproject.net.DeviceId;
20 -import com.fasterxml.jackson.databind.JsonNode;
21 -import org.onlab.packet.VlanId;
22 -
23 -import org.onosproject.net.PortNumber;
24 -import org.onosproject.net.config.Config;
25 -
26 -import java.util.Optional;
27 -
28 -/**
29 - * Config object for access device data.
30 - */
31 -public class AccessDeviceConfig extends Config<DeviceId> {
32 -
33 - private static final String UPLINK = "uplink";
34 - private static final String VLAN = "vlan";
35 - private static final String DEFAULT_VLAN = "defaultVlan";
36 -
37 - /**
38 - * Gets the access device configuration for this device.
39 - *
40 - * @return access device configuration
41 - */
42 - public AccessDeviceData getOlt() {
43 - PortNumber uplink = PortNumber.portNumber(node.path(UPLINK).asText());
44 - VlanId vlan = VlanId.vlanId(Short.parseShort(node.path(VLAN).asText()));
45 - JsonNode defaultVlanNode = node.path(DEFAULT_VLAN);
46 -
47 - Optional<VlanId> defaultVlan;
48 - if (defaultVlanNode.isMissingNode()) {
49 - defaultVlan = Optional.empty();
50 - } else {
51 - defaultVlan = Optional.of(VlanId.vlanId(Short.parseShort(defaultVlanNode.asText())));
52 - }
53 -
54 - return new AccessDeviceData(subject(), uplink, vlan, defaultVlan);
55 - }
56 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordconfig.access;
18 -
19 -import org.onlab.packet.VlanId;
20 -import org.onosproject.net.DeviceId;
21 -import org.onosproject.net.PortNumber;
22 -
23 -import java.util.Optional;
24 -
25 -import static com.google.common.base.Preconditions.checkNotNull;
26 -
27 -/**
28 - * Information about an access device.
29 - */
30 -public class AccessDeviceData {
31 - private static final String DEVICE_ID_MISSING = "Device ID cannot be null";
32 - private static final String UPLINK_MISSING = "Uplink cannot be null";
33 - private static final String VLAN_MISSING = "VLAN ID cannot be null";
34 -
35 - private final DeviceId deviceId;
36 - private final PortNumber uplink;
37 - private final VlanId vlan;
38 - private final Optional<VlanId> defaultVlan;
39 -
40 - /**
41 - * Class constructor.
42 - *
43 - * @param deviceId access device ID
44 - * @param uplink uplink port number
45 - * @param vlan device VLAN ID
46 - * @param defaultVlan default device VLAN ID
47 - */
48 - public AccessDeviceData(DeviceId deviceId, PortNumber uplink, VlanId vlan,
49 - Optional<VlanId> defaultVlan) {
50 - this.deviceId = checkNotNull(deviceId, DEVICE_ID_MISSING);
51 - this.uplink = checkNotNull(uplink, UPLINK_MISSING);
52 - this.vlan = checkNotNull(vlan, VLAN_MISSING);
53 - this.defaultVlan = checkNotNull(defaultVlan);
54 - }
55 -
56 - /**
57 - * Retrieves the access device ID.
58 - *
59 - * @return device ID
60 - */
61 - public DeviceId deviceId() {
62 - return deviceId;
63 - }
64 -
65 - /**
66 - * Retrieves the uplink port number.
67 - *
68 - * @return port number
69 - */
70 - public PortNumber uplink() {
71 - return uplink;
72 - }
73 -
74 - /**
75 - * Retrieves the VLAN ID assigned to the device.
76 - *
77 - * @return VLAN ID
78 - */
79 - public VlanId vlan() {
80 - return vlan;
81 - }
82 -
83 - /**
84 - * Retrieves the default VLAN ID that will be used for this device.
85 - *
86 - * @return default VLAN ID
87 - */
88 - public Optional<VlanId> defaultVlan() {
89 - return defaultVlan;
90 - }
91 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * Meta Application for hosting common cord configuration classes.
19 - */
20 -package org.onosproject.cordconfig.access;
...\ No newline at end of file ...\ No newline at end of file
1 -COMPILE_DEPS = [
2 - '//lib:CORE_DEPS',
3 - '//lib:javax.ws.rs-api',
4 - '//lib:jersey-client',
5 - '//lib:jersey-common',
6 - '//utils/rest:onlab-rest',
7 - '//apps/olt:onos-apps-olt-api',
8 - '//apps/cordconfig:onos-apps-cordconfig',
9 -]
10 -
11 -BUNDLES = [
12 - '//apps/olt:onos-apps-olt-api',
13 - '//apps/cordmcast:onos-apps-cordmcast',
14 -]
15 -
16 -osgi_jar_with_tests (
17 - deps = COMPILE_DEPS,
18 -)
19 -
20 -onos_app (
21 - title = 'CORD Multicast App',
22 - category = 'Traffic Steering',
23 - url = 'http://onosproject.org',
24 - description = 'CORD Multicast application',
25 - included_bundles = BUNDLES,
26 -)
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onos-apps</artifactId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 - <artifactId>onos-app-cord-mcast</artifactId>
30 - <packaging>bundle</packaging>
31 -
32 - <description>CORD Multicast application</description>
33 -
34 - <properties>
35 - <onos.app.name>org.onosproject.cordmcast</onos.app.name>
36 - <onos.app.category>Traffic Steering</onos.app.category>
37 - <onos.app.title>CORD Multicast App</onos.app.title>
38 - <onos.app.url>http://opencord.org</onos.app.url>
39 - <onos.app.requires>org.onosproject.cord-config</onos.app.requires>
40 - </properties>
41 -
42 - <dependencies>
43 - <dependency>
44 - <groupId>org.onosproject</groupId>
45 - <artifactId>onos-cli</artifactId>
46 - <version>${project.version}</version>
47 - </dependency>
48 - <dependency>
49 - <groupId>org.onosproject</groupId>
50 - <artifactId>onos-cord-config</artifactId>
51 - <version>${project.version}</version>
52 - </dependency>
53 - <dependency>
54 - <groupId>org.apache.karaf.shell</groupId>
55 - <artifactId>org.apache.karaf.shell.console</artifactId>
56 - </dependency>
57 - <dependency>
58 - <groupId>com.google.guava</groupId>
59 - <artifactId>guava</artifactId>
60 - </dependency>
61 - <dependency>
62 - <groupId>org.onosproject</groupId>
63 - <artifactId>onlab-misc</artifactId>
64 - </dependency>
65 - <dependency>
66 - <groupId>org.apache.felix</groupId>
67 - <artifactId>org.apache.felix.scr</artifactId>
68 - <version>1.8.2</version>
69 - </dependency>
70 - <dependency>
71 - <groupId>org.osgi</groupId>
72 - <artifactId>org.osgi.compendium</artifactId>
73 - <version>5.0.0</version>
74 - </dependency>
75 - <dependency>
76 - <groupId>org.glassfish.jersey.core</groupId>
77 - <artifactId>jersey-client</artifactId>
78 - <version>2.22.2</version>
79 - </dependency>
80 - <dependency>
81 - <groupId>org.onosproject</groupId>
82 - <artifactId>onos-app-olt-api</artifactId>
83 - <version>${project.version}</version>
84 - </dependency>
85 - </dependencies>
86 -</project>
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordmcast;
17 -
18 -import com.fasterxml.jackson.databind.ObjectMapper;
19 -import com.fasterxml.jackson.databind.node.ArrayNode;
20 -import com.fasterxml.jackson.databind.node.ObjectNode;
21 -import com.google.common.collect.Lists;
22 -import com.google.common.collect.Maps;
23 -import org.apache.commons.lang3.tuple.ImmutablePair;
24 -import org.apache.felix.scr.annotations.Activate;
25 -import org.apache.felix.scr.annotations.Component;
26 -import org.apache.felix.scr.annotations.Deactivate;
27 -import org.apache.felix.scr.annotations.Modified;
28 -import org.apache.felix.scr.annotations.Property;
29 -import org.apache.felix.scr.annotations.Reference;
30 -import org.apache.felix.scr.annotations.ReferenceCardinality;
31 -import org.glassfish.jersey.client.ClientConfig;
32 -import org.glassfish.jersey.client.ClientProperties;
33 -import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
34 -import org.onlab.packet.Ethernet;
35 -import org.onlab.packet.IpAddress;
36 -import org.onlab.packet.VlanId;
37 -import org.onosproject.cfg.ComponentConfigService;
38 -import org.onosproject.codec.CodecService;
39 -import org.onosproject.codec.JsonCodec;
40 -import org.onosproject.cordconfig.access.AccessDeviceConfig;
41 -import org.onosproject.cordconfig.access.AccessDeviceData;
42 -import org.onosproject.core.ApplicationId;
43 -import org.onosproject.core.CoreService;
44 -import org.onosproject.net.ConnectPoint;
45 -import org.onosproject.net.DeviceId;
46 -import org.onosproject.net.config.ConfigFactory;
47 -import org.onosproject.net.config.NetworkConfigEvent;
48 -import org.onosproject.net.config.NetworkConfigListener;
49 -import org.onosproject.net.config.NetworkConfigRegistry;
50 -import org.onosproject.net.config.basics.SubjectFactories;
51 -import org.onosproject.net.flow.DefaultTrafficSelector;
52 -import org.onosproject.net.flow.DefaultTrafficTreatment;
53 -import org.onosproject.net.flow.TrafficSelector;
54 -import org.onosproject.net.flowobjective.DefaultForwardingObjective;
55 -import org.onosproject.net.flowobjective.DefaultNextObjective;
56 -import org.onosproject.net.flowobjective.FlowObjectiveService;
57 -import org.onosproject.net.flowobjective.ForwardingObjective;
58 -import org.onosproject.net.flowobjective.NextObjective;
59 -import org.onosproject.net.flowobjective.Objective;
60 -import org.onosproject.net.flowobjective.ObjectiveContext;
61 -import org.onosproject.net.flowobjective.ObjectiveError;
62 -import org.onosproject.net.mcast.McastEvent;
63 -import org.onosproject.net.mcast.McastListener;
64 -import org.onosproject.net.mcast.McastRoute;
65 -import org.onosproject.net.mcast.McastRouteInfo;
66 -import org.onosproject.net.mcast.MulticastRouteService;
67 -
68 -import org.onosproject.rest.AbstractWebResource;
69 -import org.osgi.service.component.ComponentContext;
70 -import org.slf4j.Logger;
71 -
72 -import javax.ws.rs.ProcessingException;
73 -import javax.ws.rs.client.Client;
74 -import javax.ws.rs.client.ClientBuilder;
75 -import javax.ws.rs.client.Entity;
76 -import javax.ws.rs.client.Invocation;
77 -import javax.ws.rs.client.WebTarget;
78 -import javax.ws.rs.core.MediaType;
79 -import java.io.IOException;
80 -import java.util.Dictionary;
81 -import java.util.List;
82 -import java.util.Map;
83 -import java.util.Properties;
84 -import java.util.concurrent.ConcurrentHashMap;
85 -import java.util.concurrent.atomic.AtomicBoolean;
86 -
87 -import static com.google.common.base.Preconditions.checkNotNull;
88 -import static com.google.common.base.Strings.isNullOrEmpty;
89 -import static com.google.common.net.MediaType.JSON_UTF_8;
90 -import static org.onlab.util.Tools.get;
91 -import static org.slf4j.LoggerFactory.getLogger;
92 -
93 -/**
94 - * CORD multicast provisioning application. Operates by listening to
95 - * events on the multicast rib and provisioning groups to program multicast
96 - * flows on the dataplane.
97 - */
98 -@Component(immediate = true)
99 -public class CordMcast {
100 -
101 -
102 - private static final int DEFAULT_REST_TIMEOUT_MS = 2000;
103 - private static final int DEFAULT_PRIORITY = 500;
104 - private static final short DEFAULT_MCAST_VLAN = 4000;
105 - private static final String DEFAULT_SYNC_HOST = "10.90.0.8:8181";
106 - private static final String DEFAULT_USER = "karaf";
107 - private static final String DEFAULT_PASSWORD = "karaf";
108 - private static final boolean DEFAULT_VLAN_ENABLED = true;
109 -
110 - private final Logger log = getLogger(getClass());
111 -
112 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 - protected MulticastRouteService mcastService;
114 -
115 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 - protected FlowObjectiveService flowObjectiveService;
117 -
118 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 - protected CoreService coreService;
120 -
121 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
122 - protected CodecService codecService;
123 -
124 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
125 - protected ComponentConfigService componentConfigService;
126 -
127 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
128 - protected NetworkConfigRegistry networkConfig;
129 -
130 - protected McastListener listener = new InternalMulticastListener();
131 - private InternalNetworkConfigListener configListener =
132 - new InternalNetworkConfigListener();
133 -
134 - //TODO: move this to a ec map
135 - private Map<IpAddress, Integer> groups = Maps.newConcurrentMap();
136 -
137 - private ApplicationId appId;
138 -
139 - @Property(name = "mcastVlan", intValue = DEFAULT_MCAST_VLAN,
140 - label = "VLAN for multicast traffic")
141 - private int mcastVlan = DEFAULT_MCAST_VLAN;
142 -
143 - @Property(name = "vlanEnabled", boolValue = DEFAULT_VLAN_ENABLED,
144 - label = "Use vlan for multicast traffic?")
145 - private boolean vlanEnabled = DEFAULT_VLAN_ENABLED;
146 -
147 - @Property(name = "priority", intValue = DEFAULT_PRIORITY,
148 - label = "Priority for multicast rules")
149 - private int priority = DEFAULT_PRIORITY;
150 -
151 - @Property(name = "syncHost", value = DEFAULT_SYNC_HOST,
152 - label = "host:port to synchronize routes to")
153 - private String syncHost = DEFAULT_SYNC_HOST;
154 -
155 - @Property(name = "username", value = DEFAULT_USER,
156 - label = "Username for REST password authentication")
157 - private String user = DEFAULT_USER;
158 -
159 - @Property(name = "password", value = DEFAULT_PASSWORD,
160 - label = "Password for REST authentication")
161 - private String password = DEFAULT_PASSWORD;
162 -
163 - private String fabricOnosUrl;
164 -
165 - private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
166 -
167 - private static final Class<AccessDeviceConfig> CONFIG_CLASS =
168 - AccessDeviceConfig.class;
169 -
170 - private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
171 - new ConfigFactory<DeviceId, AccessDeviceConfig>(
172 - SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
173 - @Override
174 - public AccessDeviceConfig createConfig() {
175 - return new AccessDeviceConfig();
176 - }
177 - };
178 -
179 - @Activate
180 - public void activate(ComponentContext context) {
181 - componentConfigService.registerProperties(getClass());
182 - modified(context);
183 -
184 - appId = coreService.registerApplication("org.onosproject.cordmcast");
185 -
186 -
187 - clearRemoteRoutes();
188 -
189 - networkConfig.registerConfigFactory(configFactory);
190 - networkConfig.addListener(configListener);
191 -
192 - networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
193 - subject -> {
194 - AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
195 - if (config != null) {
196 - AccessDeviceData data = config.getOlt();
197 - oltData.put(data.deviceId(), data);
198 - }
199 - }
200 - );
201 -
202 -
203 - mcastService.addListener(listener);
204 -
205 - mcastService.getRoutes().stream()
206 - .map(r -> new ImmutablePair<>(r, mcastService.fetchSinks(r)))
207 - .filter(pair -> pair.getRight() != null && !pair.getRight().isEmpty())
208 - .forEach(pair -> pair.getRight().forEach(sink -> provisionGroup(pair.getLeft(),
209 - sink)));
210 -
211 - log.info("Started");
212 - }
213 -
214 - @Deactivate
215 - public void deactivate() {
216 - componentConfigService.unregisterProperties(getClass(), false);
217 - mcastService.removeListener(listener);
218 - networkConfig.unregisterConfigFactory(configFactory);
219 - networkConfig.removeListener(configListener);
220 - log.info("Stopped");
221 - }
222 -
223 - @Modified
224 - public void modified(ComponentContext context) {
225 - Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
226 -
227 - try {
228 - String s = get(properties, "username");
229 - user = isNullOrEmpty(s) ? DEFAULT_USER : s.trim();
230 -
231 - s = get(properties, "password");
232 - password = isNullOrEmpty(s) ? DEFAULT_PASSWORD : s.trim();
233 -
234 - s = get(properties, "mcastVlan");
235 - mcastVlan = isNullOrEmpty(s) ? DEFAULT_MCAST_VLAN : Short.parseShort(s.trim());
236 -
237 - s = get(properties, "vlanEnabled");
238 - vlanEnabled = isNullOrEmpty(s) ? DEFAULT_VLAN_ENABLED : Boolean.parseBoolean(s.trim());
239 -
240 - s = get(properties, "priority");
241 - priority = isNullOrEmpty(s) ? DEFAULT_PRIORITY : Integer.parseInt(s.trim());
242 -
243 - s = get(properties, "syncHost");
244 - syncHost = isNullOrEmpty(s) ? DEFAULT_SYNC_HOST : s.trim();
245 - } catch (Exception e) {
246 - user = DEFAULT_USER;
247 - password = DEFAULT_PASSWORD;
248 - syncHost = DEFAULT_SYNC_HOST;
249 - mcastVlan = DEFAULT_MCAST_VLAN;
250 - vlanEnabled = false;
251 - priority = DEFAULT_PRIORITY;
252 - }
253 - fabricOnosUrl = createRemoteUrl(syncHost);
254 - }
255 -
256 - private static String createRemoteUrl(String remoteHost) {
257 - return "http://" + remoteHost + "/onos/v1/mcast";
258 - }
259 -
260 - private class InternalMulticastListener implements McastListener {
261 - @Override
262 - public void event(McastEvent event) {
263 - McastRouteInfo info = event.subject();
264 - switch (event.type()) {
265 - case ROUTE_ADDED:
266 - break;
267 - case ROUTE_REMOVED:
268 - break;
269 - case SOURCE_ADDED:
270 - break;
271 - case SINK_ADDED:
272 - if (!info.sink().isPresent()) {
273 - log.warn("No sink given after sink added event: {}", info);
274 - return;
275 - }
276 - provisionGroup(info.route(), info.sink().get());
277 - break;
278 - case SINK_REMOVED:
279 - unprovisionGroup(event.subject());
280 - break;
281 - default:
282 - log.warn("Unknown mcast event {}", event.type());
283 - }
284 - }
285 - }
286 -
287 - private void unprovisionGroup(McastRouteInfo info) {
288 - if (info.sinks().isEmpty()) {
289 - removeRemoteRoute(info.route());
290 - }
291 -
292 - if (!info.sink().isPresent()) {
293 - log.warn("No sink given after sink removed event: {}", info);
294 - return;
295 - }
296 - ConnectPoint loc = info.sink().get();
297 -
298 - NextObjective next = DefaultNextObjective.builder()
299 - .fromApp(appId)
300 - .addTreatment(DefaultTrafficTreatment.builder().setOutput(loc.port()).build())
301 - .withType(NextObjective.Type.BROADCAST)
302 - .withId(groups.get(info.route().group()))
303 - .removeFromExisting(new ObjectiveContext() {
304 - @Override
305 - public void onSuccess(Objective objective) {
306 - //TODO: change to debug
307 - log.info("Next Objective {} installed", objective.id());
308 - }
309 -
310 - @Override
311 - public void onError(Objective objective, ObjectiveError error) {
312 - //TODO: change to debug
313 - log.info("Next Objective {} failed, because {}",
314 - objective.id(),
315 - error);
316 - }
317 - });
318 -
319 - flowObjectiveService.next(loc.deviceId(), next);
320 - }
321 -
322 - private void provisionGroup(McastRoute route, ConnectPoint sink) {
323 - checkNotNull(route, "Route cannot be null");
324 - checkNotNull(sink, "Sink cannot be null");
325 -
326 - AccessDeviceData oltInfo = oltData.get(sink.deviceId());
327 -
328 - if (oltInfo == null) {
329 - log.warn("Unknown OLT device : {}", sink.deviceId());
330 - return;
331 - }
332 -
333 - final AtomicBoolean sync = new AtomicBoolean(false);
334 -
335 - Integer nextId = groups.computeIfAbsent(route.group(), (g) -> {
336 - Integer id = flowObjectiveService.allocateNextId();
337 -
338 - NextObjective next = DefaultNextObjective.builder()
339 - .fromApp(appId)
340 - .addTreatment(DefaultTrafficTreatment.builder().setOutput(sink.port()).build())
341 - .withType(NextObjective.Type.BROADCAST)
342 - .withId(id)
343 - .add(new ObjectiveContext() {
344 - @Override
345 - public void onSuccess(Objective objective) {
346 - //TODO: change to debug
347 - log.info("Next Objective {} installed", objective.id());
348 - }
349 -
350 - @Override
351 - public void onError(Objective objective, ObjectiveError error) {
352 - //TODO: change to debug
353 - log.info("Next Objective {} failed, because {}",
354 - objective.id(),
355 - error);
356 - }
357 - });
358 -
359 - flowObjectiveService.next(sink.deviceId(), next);
360 -
361 - TrafficSelector.Builder mcast = DefaultTrafficSelector.builder()
362 - .matchInPort(oltInfo.uplink())
363 - .matchEthType(Ethernet.TYPE_IPV4)
364 - .matchIPDst(g.toIpPrefix());
365 -
366 - if (vlanEnabled) {
367 - mcast.matchVlanId(VlanId.vlanId((short) mcastVlan));
368 - }
369 -
370 - ForwardingObjective fwd = DefaultForwardingObjective.builder()
371 - .fromApp(appId)
372 - .nextStep(id)
373 - .makePermanent()
374 - .withFlag(ForwardingObjective.Flag.VERSATILE)
375 - .withPriority(priority)
376 - .withSelector(mcast.build())
377 - .add(new ObjectiveContext() {
378 - @Override
379 - public void onSuccess(Objective objective) {
380 - //TODO: change to debug
381 - log.info("Forwarding objective installed {}", objective);
382 - }
383 -
384 - @Override
385 - public void onError(Objective objective, ObjectiveError error) {
386 - //TODO: change to debug
387 - log.info("Forwarding objective failed {}", objective);
388 - }
389 - });
390 -
391 - flowObjectiveService.forward(sink.deviceId(), fwd);
392 -
393 - sync.set(true);
394 -
395 - return id;
396 - });
397 -
398 - if (!sync.get()) {
399 - NextObjective next = DefaultNextObjective.builder()
400 - .fromApp(appId)
401 - .addTreatment(DefaultTrafficTreatment.builder().setOutput(sink.port()).build())
402 - .withType(NextObjective.Type.BROADCAST)
403 - .withId(nextId)
404 - .addToExisting(new ObjectiveContext() {
405 - @Override
406 - public void onSuccess(Objective objective) {
407 - //TODO: change to debug
408 - log.info("Next Objective {} installed", objective.id());
409 - }
410 -
411 - @Override
412 - public void onError(Objective objective, ObjectiveError error) {
413 - //TODO: change to debug
414 - log.info("Next Objective {} failed, because {}",
415 - objective.id(),
416 - error);
417 - }
418 - });
419 -
420 - flowObjectiveService.next(sink.deviceId(), next);
421 - }
422 -
423 -
424 - addRemoteRoute(route);
425 - }
426 -
427 - private void addRemoteRoute(McastRoute route) {
428 - checkNotNull(route);
429 - if (syncHost == null) {
430 - log.warn("No host configured for synchronization; route will be dropped");
431 - return;
432 - }
433 -
434 - log.debug("Sending route {} to other ONOS {}", route, fabricOnosUrl);
435 -
436 - Invocation.Builder builder = getClientBuilder(fabricOnosUrl);
437 -
438 - ObjectNode json = codecService.getCodec(McastRoute.class)
439 - .encode(route, new AbstractWebResource());
440 -
441 - try {
442 - builder.post(Entity.json(json.toString()));
443 - } catch (ProcessingException e) {
444 - log.warn("Unable to send route to remote controller: {}", e.getMessage());
445 - }
446 - }
447 -
448 - private void removeRemoteRoute(McastRoute route) {
449 - if (syncHost == null) {
450 - log.warn("No host configured for synchronization; route will be dropped");
451 - return;
452 - }
453 -
454 - log.debug("Removing route {} from other ONOS {}", route, fabricOnosUrl);
455 -
456 - Invocation.Builder builder = getClientBuilder(fabricOnosUrl)
457 - .property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
458 -
459 - ObjectNode json = codecService.getCodec(McastRoute.class)
460 - .encode(route, new AbstractWebResource());
461 -
462 - builder.method("DELETE", Entity.entity(json.asText(),
463 - MediaType.APPLICATION_OCTET_STREAM));
464 - }
465 -
466 - private void clearRemoteRoutes() {
467 - if (syncHost == null) {
468 - log.warn("No host configured for synchronization");
469 - return;
470 - }
471 -
472 - log.debug("Clearing remote multicast routes from {}", fabricOnosUrl);
473 -
474 - Invocation.Builder builder = getClientBuilder(fabricOnosUrl);
475 - List<McastRoute> mcastRoutes = Lists.newArrayList();
476 -
477 - try {
478 - String response = builder
479 - .accept(MediaType.APPLICATION_JSON_TYPE)
480 - .get(String.class);
481 -
482 - JsonCodec<McastRoute> routeCodec = codecService.getCodec(McastRoute.class);
483 - ObjectMapper mapper = new ObjectMapper();
484 -
485 -
486 - ObjectNode node = (ObjectNode) mapper.readTree(response);
487 - ArrayNode list = (ArrayNode) node.path("routes");
488 -
489 - list.forEach(n -> mcastRoutes.add(
490 - routeCodec.decode((ObjectNode) n, new AbstractWebResource())));
491 -
492 - } catch (IOException e) {
493 - log.warn("Error clearing remote routes", e);
494 - }
495 -
496 - mcastRoutes.forEach(this::removeRemoteRoute);
497 - }
498 -
499 - private Invocation.Builder getClientBuilder(String uri) {
500 - ClientConfig config = new ClientConfig();
501 - Client client = ClientBuilder.newClient(config);
502 -
503 - client.property(ClientProperties.CONNECT_TIMEOUT, DEFAULT_REST_TIMEOUT_MS);
504 - client.property(ClientProperties.READ_TIMEOUT, DEFAULT_REST_TIMEOUT_MS);
505 - client.register(HttpAuthenticationFeature.basic(user, password));
506 -
507 - WebTarget wt = client.target(uri);
508 - return wt.request(JSON_UTF_8.toString());
509 - }
510 -
511 - private class InternalNetworkConfigListener implements NetworkConfigListener {
512 - @Override
513 - public void event(NetworkConfigEvent event) {
514 - switch (event.type()) {
515 -
516 - case CONFIG_ADDED:
517 - case CONFIG_UPDATED:
518 - AccessDeviceConfig config =
519 - networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
520 - if (config != null) {
521 - oltData.put(config.getOlt().deviceId(), config.getOlt());
522 - }
523 -
524 - break;
525 - case CONFIG_REGISTERED:
526 - case CONFIG_UNREGISTERED:
527 - break;
528 - case CONFIG_REMOVED:
529 - oltData.remove(event.subject());
530 - break;
531 - default:
532 - break;
533 - }
534 - }
535 -
536 - @Override
537 - public boolean isRelevant(NetworkConfigEvent event) {
538 - return event.configClass().equals(CONFIG_CLASS);
539 - }
540 - }
541 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * Application for provisioning multicast streams in the context of cord.
19 - */
20 -package org.onosproject.cordmcast;
...\ No newline at end of file ...\ No newline at end of file
1 -# app builds but is currently non functional. It needs transitive runtime
2 -# dependencies.
3 -
4 -COMPILE_DEPS = [
5 - '//lib:CORE_DEPS',
6 - '//lib:org.apache.karaf.shell.console',
7 - '//lib:javax.ws.rs-api',
8 - '//lib:jsch',
9 - '//utils/rest:onlab-rest',
10 - '//cli:onos-cli',
11 - '//core/store/serializers:onos-core-serializers',
12 - '//apps/dhcp/api:onos-apps-dhcp-api',
13 - '//apps/xosclient:onos-apps-xosclient',
14 - '//apps/cordconfig:onos-apps-cordconfig',
15 - '//protocols/ovsdb/api:onos-protocols-ovsdb-api',
16 - '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc',
17 -]
18 -
19 -BUNDLES = [
20 - '//apps/cordvtn:onos-apps-cordvtn',
21 -]
22 -
23 -EXCLUDED_BUNDLES = [
24 - '//lib:jsch',
25 -]
26 -
27 -osgi_jar_with_tests (
28 - deps = COMPILE_DEPS,
29 - web_context = '/onos/cordvtn',
30 -)
31 -
32 -onos_app (
33 - title = 'CORD VTN REST API',
34 - category = 'Traffic Steering',
35 - url = 'http://onosproject.org',
36 - included_bundles = BUNDLES,
37 - excluded_bundles = EXCLUDED_BUNDLES,
38 - description = 'APIs for interacting with the CORD VTN application.',
39 - required_apps = [ 'org.onosproject.cord-config', 'org.onosproject.xosclient', 'org.onosproject.dhcp', 'org.onosproject.ovsdb' ],
40 -)
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<app name="org.onosproject.cordvtn" origin="ON.Lab" version="${project.version}"
18 - category="Traffic Steering" url="http://onosproject.org" title="CORD Virtual Tenant Network"
19 - featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
20 - features="${project.artifactId}"
21 - apps="org.onosproject.ovsdb-base,org.onosproject.dhcp,org.onosproject.xosclient,org.onosproject.cord-config">
22 - <description>${project.description}</description>
23 - <artifact>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</artifact>
24 -</app>
1 -<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
18 - <feature name="${project.artifactId}" version="${project.version}" description="${project.description}">
19 - <feature>onos-api</feature>
20 - <bundle>mvn:${project.groupId}/onos-app-cordvtn/${project.version}</bundle>
21 - <bundle>wrap:mvn:com.jcraft/jsch/0.1.53$Bundle-SymbolicName=jsch&amp;Bundle-Version=0.1.53</bundle>
22 - </feature>
23 -</features>
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onos-apps</artifactId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 - <artifactId>onos-app-cordvtn</artifactId>
30 - <packaging>bundle</packaging>
31 -
32 - <description>Virtual tenant network service for CORD</description>
33 -
34 - <properties>
35 - <web.context>/onos/cordvtn</web.context>
36 - <api.version>1.0.0</api.version>
37 - <api.title>CORD VTN REST API</api.title>
38 - <api.description>
39 - APIs for interacting with the CORD VTN application.
40 - </api.description>
41 - <api.package>org.onosproject.cordvtn.rest</api.package>
42 - </properties>
43 -
44 - <dependencies>
45 - <dependency>
46 - <groupId>org.osgi</groupId>
47 - <artifactId>org.osgi.compendium</artifactId>
48 - </dependency>
49 - <dependency>
50 - <groupId>org.onosproject</groupId>
51 - <artifactId>onos-api</artifactId>
52 - </dependency>
53 - <dependency>
54 - <groupId>org.onosproject</groupId>
55 - <artifactId>onos-core-serializers</artifactId>
56 - <version>${project.version}</version>
57 - </dependency>
58 - <dependency>
59 - <groupId>org.onosproject</groupId>
60 - <artifactId>onos-ovsdb-api</artifactId>
61 - <version>${project.version}</version>
62 - </dependency>
63 - <dependency>
64 - <groupId>org.onosproject</groupId>
65 - <artifactId>onos-cli</artifactId>
66 - <version>${project.version}</version>
67 - </dependency>
68 - <dependency>
69 - <groupId>org.apache.karaf.shell</groupId>
70 - <artifactId>org.apache.karaf.shell.console</artifactId>
71 - <version>3.0.5</version>
72 - </dependency>
73 - <dependency>
74 - <groupId>org.onosproject</groupId>
75 - <artifactId>onos-rest</artifactId>
76 - <version>${project.version}</version>
77 - </dependency>
78 - <dependency>
79 - <groupId>org.onosproject</groupId>
80 - <artifactId>onlab-rest</artifactId>
81 - <version>${project.version}</version>
82 - </dependency>
83 - <dependency>
84 - <groupId>javax.ws.rs</groupId>
85 - <artifactId>javax.ws.rs-api</artifactId>
86 - <version>2.0.1</version>
87 - </dependency>
88 - <dependency>
89 - <groupId>org.glassfish.jersey.containers</groupId>
90 - <artifactId>jersey-container-servlet</artifactId>
91 - </dependency>
92 - <dependency>
93 - <groupId>com.fasterxml.jackson.core</groupId>
94 - <artifactId>jackson-databind</artifactId>
95 - </dependency>
96 - <dependency>
97 - <groupId>com.fasterxml.jackson.core</groupId>
98 - <artifactId>jackson-annotations</artifactId>
99 - </dependency>
100 - <dependency>
101 - <groupId>org.onosproject</groupId>
102 - <artifactId>onos-app-dhcp-api</artifactId>
103 - <version>${project.version}</version>
104 - </dependency>
105 - <dependency>
106 - <groupId>org.onosproject</groupId>
107 - <artifactId>onos-app-xos-client</artifactId>
108 - <version>${project.version}</version>
109 - </dependency>
110 - <dependency>
111 - <groupId>org.onosproject</groupId>
112 - <artifactId>onos-cord-config</artifactId>
113 - <version>${project.version}</version>
114 - </dependency>
115 - <dependency>
116 - <groupId>com.jcraft</groupId>
117 - <artifactId>jsch</artifactId>
118 - <version>0.1.53</version>
119 - </dependency>
120 - </dependencies>
121 -
122 - <build>
123 - <plugins>
124 - <plugin>
125 - <groupId>org.apache.felix</groupId>
126 - <artifactId>maven-bundle-plugin</artifactId>
127 - <extensions>true</extensions>
128 - <configuration>
129 - <instructions>
130 - <_wab>src/main/webapp/</_wab>
131 - <Include-Resource>
132 - WEB-INF/classes/apidoc/swagger.json=target/swagger.json,
133 - {maven-resources}
134 - </Include-Resource>
135 - <Bundle-SymbolicName>
136 - ${project.groupId}.${project.artifactId}
137 - </Bundle-SymbolicName>
138 - <Import-Package>
139 - *,org.glassfish.jersey.servlet
140 - </Import-Package>
141 - <Web-ContextPath>${web.context}</Web-ContextPath>
142 - </instructions>
143 - </configuration>
144 - </plugin>
145 - </plugins>
146 - </build>
147 -
148 -</project>
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -/**
19 - * Entity capable of handling a subject connected and disconnected situation.
20 - */
21 -public interface ConnectionHandler<T> {
22 -
23 - /**
24 - * Processes the connected subject.
25 - *
26 - * @param subject subject
27 - */
28 - void connected(T subject);
29 -
30 - /**
31 - * Processes the disconnected subject.
32 - *
33 - * @param subject subject.
34 - */
35 - void disconnected(T subject);
36 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -import com.fasterxml.jackson.databind.JsonNode;
19 -import com.google.common.collect.Maps;
20 -import com.google.common.collect.Sets;
21 -import org.onlab.packet.Ip4Address;
22 -import org.onlab.packet.IpAddress;
23 -import org.onlab.packet.IpPrefix;
24 -import org.onlab.packet.MacAddress;
25 -import org.onlab.packet.TpPort;
26 -import org.onosproject.core.ApplicationId;
27 -import org.onosproject.net.DeviceId;
28 -import org.onosproject.net.config.Config;
29 -import org.onosproject.xosclient.api.OpenStackAccess;
30 -import org.onosproject.xosclient.api.XosAccess;
31 -import org.slf4j.Logger;
32 -
33 -import java.util.Map;
34 -import java.util.Set;
35 -
36 -import static org.slf4j.LoggerFactory.getLogger;
37 -
38 -/**
39 - * Configuration object for CordVtn service.
40 - */
41 -public class CordVtnConfig extends Config<ApplicationId> {
42 -
43 - protected final Logger log = getLogger(getClass());
44 -
45 - public static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";
46 - public static final String PUBLIC_GATEWAYS = "publicGateways";
47 - public static final String GATEWAY_IP = "gatewayIp";
48 - public static final String GATEWAY_MAC = "gatewayMac";
49 - public static final String LOCAL_MANAGEMENT_IP = "localManagementIp";
50 - public static final String MANAGEMENT_IP = "managementIpRange";
51 - public static final String OVSDB_PORT = "ovsdbPort";
52 -
53 - public static final String CORDVTN_NODES = "nodes";
54 - public static final String HOSTNAME = "hostname";
55 - public static final String HOST_MANAGEMENT_IP = "hostManagementIp";
56 - public static final String DATA_PLANE_IP = "dataPlaneIp";
57 - public static final String DATA_PLANE_INTF = "dataPlaneIntf";
58 - public static final String BRIDGE_ID = "bridgeId";
59 -
60 - public static final String SSH = "ssh";
61 - public static final String SSH_PORT = "sshPort";
62 - public static final String SSH_USER = "sshUser";
63 - public static final String SSH_KEY_FILE = "sshKeyFile";
64 -
65 - public static final String OPENSTACK = "openstack";
66 - public static final String XOS = "xos";
67 -
68 - public static final String ENDPOINT = "endpoint";
69 - public static final String TENANT = "tenant";
70 - public static final String USER = "user";
71 - public static final String PASSWORD = "password";
72 -
73 - /**
74 - * Returns the set of nodes read from network config.
75 - *
76 - * @return set of CordVtnNodeConfig or empty set
77 - */
78 - public Set<CordVtnNode> cordVtnNodes() {
79 -
80 - Set<CordVtnNode> nodes = Sets.newHashSet();
81 -
82 - JsonNode cordvtnNodes = object.get(CORDVTN_NODES);
83 - if (cordvtnNodes == null) {
84 - log.debug("No CORD VTN nodes found");
85 - return nodes;
86 - }
87 -
88 - JsonNode sshNode = object.get(SSH);
89 - if (sshNode == null) {
90 - log.warn("SSH information not found");
91 - return nodes;
92 - }
93 -
94 - for (JsonNode cordvtnNode : cordvtnNodes) {
95 - try {
96 - NetworkAddress hostMgmt = NetworkAddress.valueOf(getConfig(cordvtnNode, HOST_MANAGEMENT_IP));
97 - NetworkAddress localMgmt = NetworkAddress.valueOf(getConfig(object, LOCAL_MANAGEMENT_IP));
98 - if (hostMgmt.prefix().contains(localMgmt.prefix()) ||
99 - localMgmt.prefix().contains(hostMgmt.prefix())) {
100 - log.error("hostMamt and localMgmt cannot be overlapped, skip this node");
101 - continue;
102 - }
103 -
104 - Ip4Address hostMgmtIp = hostMgmt.ip().getIp4Address();
105 - SshAccessInfo sshInfo = new SshAccessInfo(
106 - hostMgmtIp,
107 - TpPort.tpPort(Integer.parseInt(getConfig(sshNode, SSH_PORT))),
108 - getConfig(sshNode, SSH_USER), getConfig(sshNode, SSH_KEY_FILE));
109 -
110 - String hostname = getConfig(cordvtnNode, HOSTNAME);
111 - CordVtnNode newNode = new CordVtnNode(
112 - hostname, hostMgmt, localMgmt,
113 - NetworkAddress.valueOf(getConfig(cordvtnNode, DATA_PLANE_IP)),
114 - TpPort.tpPort(Integer.parseInt(getConfig(object, OVSDB_PORT))),
115 - sshInfo,
116 - DeviceId.deviceId(getConfig(cordvtnNode, BRIDGE_ID)),
117 - getConfig(cordvtnNode, DATA_PLANE_INTF),
118 - CordVtnNodeState.noState());
119 -
120 - nodes.add(newNode);
121 - } catch (IllegalArgumentException | NullPointerException e) {
122 - log.error("{}", e);
123 - }
124 - }
125 -
126 - return nodes;
127 - }
128 -
129 - /**
130 - * Returns value of a given path. If the path is missing, show log and return
131 - * null.
132 - *
133 - * @param path path
134 - * @return value or null
135 - */
136 - private String getConfig(JsonNode jsonNode, String path) {
137 - jsonNode = jsonNode.path(path);
138 -
139 - if (jsonNode.isMissingNode()) {
140 - log.error("{} is not configured", path);
141 - return null;
142 - } else {
143 - return jsonNode.asText();
144 - }
145 - }
146 -
147 - /**
148 - * Returns private network gateway MAC address.
149 - *
150 - * @return mac address, or null
151 - */
152 - public MacAddress privateGatewayMac() {
153 - JsonNode jsonNode = object.get(PRIVATE_GATEWAY_MAC);
154 - if (jsonNode == null) {
155 - return null;
156 - }
157 -
158 - try {
159 - return MacAddress.valueOf(jsonNode.asText());
160 - } catch (IllegalArgumentException e) {
161 - log.error("Wrong MAC address format {}", jsonNode.asText());
162 - return null;
163 - }
164 - }
165 -
166 - /**
167 - * Returns public network gateway IP and MAC address pairs.
168 - *
169 - * @return map of ip and mac address
170 - */
171 - public Map<IpAddress, MacAddress> publicGateways() {
172 - JsonNode jsonNodes = object.get(PUBLIC_GATEWAYS);
173 - if (jsonNodes == null) {
174 - return Maps.newHashMap();
175 - }
176 -
177 - Map<IpAddress, MacAddress> publicGateways = Maps.newHashMap();
178 - jsonNodes.forEach(jsonNode -> {
179 - try {
180 - publicGateways.put(
181 - IpAddress.valueOf(jsonNode.path(GATEWAY_IP).asText()),
182 - MacAddress.valueOf(jsonNode.path(GATEWAY_MAC).asText()));
183 - } catch (IllegalArgumentException | NullPointerException e) {
184 - log.error("Wrong address format {}", e.toString());
185 - }
186 - });
187 -
188 - return publicGateways;
189 - }
190 -
191 - /**
192 - * Returns management IP address range.
193 - *
194 - * @return management network ip prefix, or null
195 - */
196 - public IpPrefix managementIpRange() {
197 - JsonNode jsonNode = object.get(MANAGEMENT_IP);
198 - if (jsonNode == null) {
199 - return null;
200 - }
201 -
202 - try {
203 - return IpPrefix.valueOf(jsonNode.asText());
204 - } catch (IllegalArgumentException e) {
205 - log.error("{}:{} wrong address format", MANAGEMENT_IP, jsonNode);
206 - return null;
207 - }
208 - }
209 -
210 - /**
211 - * Returns XOS access information.
212 - *
213 - * @return XOS access, or null
214 - */
215 - public XosAccess xosAccess() {
216 - JsonNode jsonNode = object.get(XOS);
217 - if (jsonNode == null) {
218 - return null;
219 - }
220 -
221 - try {
222 - return new XosAccess(getConfig(jsonNode, ENDPOINT),
223 - getConfig(jsonNode, USER),
224 - getConfig(jsonNode, PASSWORD));
225 - } catch (NullPointerException e) {
226 - log.error("Failed to get XOS access");
227 - return null;
228 - }
229 - }
230 -
231 - /**
232 - * Returns OpenStack API access information.
233 - *
234 - * @return openstack access
235 - */
236 - public OpenStackAccess openstackAccess() {
237 - JsonNode jsonNode = object.get(OPENSTACK);
238 - if (jsonNode == null) {
239 - log.error("Failed to get OpenStack configurations");
240 - return null;
241 - }
242 -
243 - try {
244 - return new OpenStackAccess(
245 - jsonNode.path(ENDPOINT).asText(),
246 - jsonNode.path(TENANT).asText(),
247 - jsonNode.path(USER).asText(),
248 - jsonNode.path(PASSWORD).asText());
249 - } catch (IllegalArgumentException | NullPointerException e) {
250 - log.error("Failed to get OpenStack configurations");
251 - return null;
252 - }
253 - }
254 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -import com.google.common.base.MoreObjects;
19 -import org.onlab.packet.TpPort;
20 -import org.onosproject.net.DeviceId;
21 -
22 -import java.util.Comparator;
23 -import java.util.Objects;
24 -
25 -import static com.google.common.base.Preconditions.checkNotNull;
26 -
27 -/**
28 - * Representation of a compute infrastructure node for CORD VTN service.
29 - */
30 -public final class CordVtnNode {
31 -
32 - private final String hostname;
33 - private final NetworkAddress hostMgmtIp;
34 - private final NetworkAddress localMgmtIp;
35 - private final NetworkAddress dpIp;
36 - private final TpPort ovsdbPort;
37 - private final SshAccessInfo sshInfo;
38 - private final DeviceId bridgeId;
39 - private final String dpIntf;
40 - private final CordVtnNodeState state;
41 -
42 - public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR =
43 - (node1, node2) -> node1.hostname().compareTo(node2.hostname());
44 -
45 - /**
46 - * Creates a new node.
47 - *
48 - * @param hostname hostname
49 - * @param hostMgmtIp host management network address
50 - * @param localMgmtIp local management network address
51 - * @param dpIp data plane network address
52 - * @param ovsdbPort port number for OVSDB connection
53 - * @param sshInfo SSH access information
54 - * @param bridgeId integration bridge identifier
55 - * @param dpIntf data plane interface name
56 - * @param state cordvtn node state
57 - */
58 - public CordVtnNode(String hostname, NetworkAddress hostMgmtIp, NetworkAddress localMgmtIp,
59 - NetworkAddress dpIp, TpPort ovsdbPort, SshAccessInfo sshInfo,
60 - DeviceId bridgeId, String dpIntf, CordVtnNodeState state) {
61 - this.hostname = checkNotNull(hostname, "hostname cannot be null");
62 - this.hostMgmtIp = checkNotNull(hostMgmtIp, "hostMgmtIp cannot be null");
63 - this.localMgmtIp = checkNotNull(localMgmtIp, "localMgmtIp cannot be null");
64 - this.dpIp = checkNotNull(dpIp, "dpIp cannot be null");
65 - this.ovsdbPort = checkNotNull(ovsdbPort, "ovsdbPort cannot be null");
66 - this.sshInfo = checkNotNull(sshInfo, "sshInfo cannot be null");
67 - this.bridgeId = checkNotNull(bridgeId, "bridgeId cannot be null");
68 - this.dpIntf = checkNotNull(dpIntf, "dpIntf cannot be null");
69 - this.state = state;
70 - }
71 -
72 - /**
73 - * Returns cordvtn node with new state.
74 - *
75 - * @param node cordvtn node
76 - * @param state cordvtn node init state
77 - * @return cordvtn node
78 - */
79 - public static CordVtnNode getUpdatedNode(CordVtnNode node, CordVtnNodeState state) {
80 - return new CordVtnNode(node.hostname,
81 - node.hostMgmtIp, node.localMgmtIp, node.dpIp,
82 - node.ovsdbPort,
83 - node.sshInfo,
84 - node.bridgeId,
85 - node.dpIntf, state);
86 - }
87 -
88 - /**
89 - * Returns the hostname.
90 - *
91 - * @return hostname
92 - */
93 - public String hostname() {
94 - return this.hostname;
95 - }
96 -
97 - /**
98 - * Returns the host management network address.
99 - *
100 - * @return network address
101 - */
102 - public NetworkAddress hostMgmtIp() {
103 - return this.hostMgmtIp;
104 - }
105 -
106 - /**
107 - * Returns the local management network address.
108 - *
109 - * @return network address
110 - */
111 - public NetworkAddress localMgmtIp() {
112 - return this.localMgmtIp;
113 - }
114 -
115 - /**
116 - * Returns the data plane network address.
117 - *
118 - * @return network address
119 - */
120 - public NetworkAddress dpIp() {
121 - return this.dpIp;
122 - }
123 -
124 - /**
125 - * Returns the port number used for OVSDB connection.
126 - *
127 - * @return port number
128 - */
129 - public TpPort ovsdbPort() {
130 - return this.ovsdbPort;
131 - }
132 -
133 - /**
134 - * Returns the SSH access information.
135 - *
136 - * @return ssh access information
137 - */
138 - public SshAccessInfo sshInfo() {
139 - return this.sshInfo;
140 - }
141 -
142 - /**
143 - * Returns the identifier of the integration bridge.
144 - *
145 - * @return device id
146 - */
147 - public DeviceId intBrId() {
148 - return this.bridgeId;
149 - }
150 -
151 - /**
152 - * Returns the identifier of the OVSDB device.
153 - *
154 - * @return device id
155 - */
156 - public DeviceId ovsdbId() {
157 - return DeviceId.deviceId("ovsdb:" + this.hostMgmtIp.ip().toString());
158 - }
159 -
160 - /**
161 - * Returns data plane interface name.
162 - *
163 - * @return data plane interface name
164 - */
165 - public String dpIntf() {
166 - return this.dpIntf;
167 - }
168 -
169 - /**
170 - * Returns the state of the node.
171 - *
172 - * @return state
173 - */
174 - public CordVtnNodeState state() {
175 - return this.state;
176 - }
177 -
178 - @Override
179 - public boolean equals(Object obj) {
180 - if (this == obj) {
181 - return true;
182 - }
183 -
184 - if (obj instanceof CordVtnNode) {
185 - CordVtnNode that = (CordVtnNode) obj;
186 - if (Objects.equals(hostname, that.hostname) &&
187 - Objects.equals(hostMgmtIp, that.hostMgmtIp) &&
188 - Objects.equals(localMgmtIp, that.localMgmtIp) &&
189 - Objects.equals(dpIp, that.dpIp) &&
190 - Objects.equals(ovsdbPort, that.ovsdbPort) &&
191 - Objects.equals(sshInfo, that.sshInfo) &&
192 - Objects.equals(bridgeId, that.bridgeId) &&
193 - Objects.equals(dpIntf, that.dpIntf)) {
194 - return true;
195 - }
196 - }
197 - return false;
198 - }
199 -
200 - @Override
201 - public int hashCode() {
202 - return Objects.hash(hostname, hostMgmtIp, localMgmtIp, dpIp,
203 - ovsdbPort, sshInfo, bridgeId, dpIntf);
204 - }
205 -
206 - @Override
207 - public String toString() {
208 - return MoreObjects.toStringHelper(getClass())
209 - .add("hostname", hostname)
210 - .add("hostMgmtIp", hostMgmtIp)
211 - .add("localMgmtIp", localMgmtIp)
212 - .add("dpIp", dpIp)
213 - .add("port", ovsdbPort)
214 - .add("sshInfo", sshInfo)
215 - .add("bridgeId", bridgeId)
216 - .add("dpIntf", dpIntf)
217 - .add("state", state)
218 - .toString();
219 - }
220 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -/**
19 - * Entity that defines possible init state of the cordvtn node.
20 - */
21 -public interface CordVtnNodeState {
22 - /**
23 - * Returns null for no state.
24 - *
25 - * @return null
26 - */
27 - static CordVtnNodeState noState() {
28 - return null;
29 - }
30 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -import org.onosproject.xosclient.api.VtnServiceId;
19 -
20 -/**
21 - * Service for provisioning overlay virtual networks on compute nodes.
22 - */
23 -public interface CordVtnService {
24 -
25 - String CORDVTN_APP_ID = "org.onosproject.cordvtn";
26 -
27 - /**
28 - * Creates dependencies for a given tenant service.
29 - *
30 - * @param tServiceId id of the service which has a dependency
31 - * @param pServiceId id of the service which provide dependency
32 - * @param isBidirectional true to enable bidirectional connectivity between two services
33 - */
34 - void createServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
35 - boolean isBidirectional);
36 -
37 - /**
38 - * Removes all dependencies from a given tenant service.
39 - *
40 - * @param tServiceId id of the service which has a dependency
41 - * @param pServiceId id of the service which provide dependency
42 - */
43 - void removeServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId);
44 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -import com.google.common.base.Strings;
19 -import org.onlab.packet.Ip4Address;
20 -import org.onlab.packet.MacAddress;
21 -import org.onosproject.net.DeviceId;
22 -import org.onosproject.net.Host;
23 -import org.onosproject.net.PortNumber;
24 -import org.onosproject.xosclient.api.VtnPortId;
25 -import org.onosproject.xosclient.api.VtnService;
26 -import org.onosproject.xosclient.api.VtnServiceId;
27 -
28 -import static com.google.common.base.Preconditions.checkArgument;
29 -import static com.google.common.base.Preconditions.checkNotNull;
30 -
31 -/**
32 - * Provides methods to help to handle network service instance.
33 - */
34 -public final class Instance {
35 -
36 - public static final String SERVICE_ID = "serviceId";
37 - public static final String SERVICE_TYPE = "serviceType";
38 - public static final String PORT_ID = "vtnPortId";
39 - public static final String CREATE_TIME = "createTime";
40 - public static final String NESTED_INSTANCE = "nestedInstance";
41 - public static final String TRUE = "true";
42 -
43 - private final Host host;
44 -
45 - /**
46 - * Default constructor.
47 - *
48 - * @param instance host object of this instance
49 - */
50 - private Instance(Host instance) {
51 - this.host = instance;
52 - }
53 -
54 - /**
55 - * Returns host object of this instance.
56 - *
57 - * @return host
58 - */
59 - public Host host() {
60 - return this.host;
61 - }
62 -
63 - /**
64 - * Returns new instance.
65 - *
66 - * @param host host object of this instance
67 - * @return instance
68 - */
69 - public static Instance of(Host host) {
70 - checkNotNull(host);
71 - checkArgument(!Strings.isNullOrEmpty(host.annotations().value(SERVICE_ID)));
72 - checkArgument(!Strings.isNullOrEmpty(host.annotations().value(SERVICE_TYPE)));
73 - checkArgument(!Strings.isNullOrEmpty(host.annotations().value(PORT_ID)));
74 - checkArgument(!Strings.isNullOrEmpty(host.annotations().value(CREATE_TIME)));
75 -
76 - return new Instance(host);
77 - }
78 -
79 - /**
80 - * Returns service ID of a given host.
81 - *
82 - * @return vtn service id
83 - */
84 - public VtnServiceId serviceId() {
85 - String serviceId = host.annotations().value(SERVICE_ID);
86 - return VtnServiceId.of(serviceId);
87 - }
88 -
89 - /**
90 - * Returns service type of a given host.
91 - *
92 - * @return vtn service type
93 - */
94 - public VtnService.ServiceType serviceType() {
95 - String serviceType = host.annotations().value(SERVICE_TYPE);
96 - return VtnService.ServiceType.valueOf(serviceType);
97 - }
98 -
99 - /**
100 - * Returns port ID of a given host.
101 - *
102 - * @return vtn port id
103 - */
104 - public VtnPortId portId() {
105 - String portId = host.annotations().value(PORT_ID);
106 - return VtnPortId.of(portId);
107 - }
108 -
109 - /**
110 - * Returns if the instance is nested container or not.
111 - *
112 - * @return true if it's nested container; false otherwise
113 - */
114 - public boolean isNestedInstance() {
115 - return host.annotations().value(NESTED_INSTANCE) != null;
116 - }
117 -
118 - /**
119 - * Returns MAC address of this instance.
120 - *
121 - * @return mac address
122 - */
123 - public MacAddress mac() {
124 - return host.mac();
125 - }
126 -
127 - /**
128 - * Returns IP address of this instance.
129 - *
130 - * @return ip address
131 - */
132 - public Ip4Address ipAddress() {
133 - // assume all instance has only one IP address, and only IP4 is supported now
134 - return host.ipAddresses().stream().findFirst().get().getIp4Address();
135 - }
136 -
137 - /**
138 - * Returns device ID of this host.
139 - *
140 - * @return device id
141 - */
142 - public DeviceId deviceId() {
143 - return host.location().deviceId();
144 - }
145 -
146 - /**
147 - * Returns the port number where this host is.
148 - *
149 - * @return port number
150 - */
151 - public PortNumber portNumber() {
152 - return host.location().port();
153 - }
154 -
155 - /**
156 - * Returns annotation value with a given key.
157 - *
158 - * @param annotationKey annotation key
159 - * @return annotation value
160 - */
161 - public String getAnnotation(String annotationKey) {
162 - return host.annotations().value(annotationKey);
163 - }
164 -
165 - @Override
166 - public String toString() {
167 - return host.toString();
168 - }
169 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -/**
19 - * Handles service instance detection and removal.
20 - */
21 -public interface InstanceHandler {
22 -
23 - /**
24 - * Handles newly detected instance.
25 - *
26 - * @param instance instance
27 - */
28 - void instanceDetected(Instance instance);
29 -
30 - /**
31 - * Handles removed instance.
32 - *
33 - * @param instance instance
34 - */
35 - void instanceRemoved(Instance instance);
36 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -import com.google.common.base.MoreObjects;
19 -import org.onlab.packet.IpAddress;
20 -import org.onlab.packet.IpPrefix;
21 -
22 -import java.util.Objects;
23 -
24 -import static com.google.common.base.Preconditions.checkArgument;
25 -
26 -/**
27 - * Representation of a network address, which consists of IP address and prefix.
28 - */
29 -public final class NetworkAddress {
30 - private final IpAddress ip;
31 - private final IpPrefix prefix;
32 -
33 - /**
34 - * Constructor for a given IP address and prefix.
35 - *
36 - * @param ip ip address
37 - * @param prefix ip prefix
38 - */
39 - public NetworkAddress(IpAddress ip, IpPrefix prefix) {
40 - this.ip = ip;
41 - this.prefix = prefix;
42 - }
43 -
44 - /**
45 - * Converts a CIDR notation string into a network address.
46 - *
47 - * @param cidr cidr
48 - * @return network address
49 - * @throws IllegalArgumentException if the cidr is not valid
50 - */
51 - public static NetworkAddress valueOf(String cidr) {
52 - checkArgument(cidr.contains("/"));
53 -
54 - IpAddress ipAddress = IpAddress.valueOf(cidr.split("/")[0]);
55 - IpPrefix ipPrefix = IpPrefix.valueOf(cidr);
56 -
57 - return new NetworkAddress(ipAddress, ipPrefix);
58 - }
59 -
60 - /**
61 - * Returns the IP address value of the network address.
62 - *
63 - * @return ip address
64 - */
65 - public IpAddress ip() {
66 - return this.ip;
67 - }
68 -
69 - /**
70 - * Returns the IP prefix value of the network address.
71 - *
72 - * @return ip prefix
73 - */
74 - public IpPrefix prefix() {
75 - return this.prefix;
76 - }
77 -
78 - /**
79 - * Converts a network address to a CIDR notation.
80 - *
81 - * @return cidr notation string
82 - */
83 - public String cidr() {
84 - return ip.toString() + "/" + prefix.prefixLength();
85 - }
86 -
87 - @Override
88 - public boolean equals(Object obj) {
89 - if (this == obj) {
90 - return true;
91 - }
92 -
93 - if (obj instanceof NetworkAddress) {
94 - NetworkAddress that = (NetworkAddress) obj;
95 - if (Objects.equals(ip, that.ip) && Objects.equals(prefix, that.prefix)) {
96 - return true;
97 - }
98 - }
99 - return false;
100 - }
101 -
102 - @Override
103 - public int hashCode() {
104 - return Objects.hash(ip, prefix);
105 - }
106 -
107 - @Override
108 - public String toString() {
109 - return MoreObjects.toStringHelper(getClass())
110 - .add("IpAddress", ip)
111 - .add("IpPrefix", prefix)
112 - .toString();
113 - }
114 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.api;
17 -
18 -import com.google.common.base.MoreObjects;
19 -import org.onlab.packet.Ip4Address;
20 -import org.onlab.packet.TpPort;
21 -
22 -import java.util.Objects;
23 -
24 -import static com.google.common.base.Preconditions.checkNotNull;
25 -
26 -/**
27 - * Representation of SSH access information.
28 - */
29 -public final class SshAccessInfo {
30 -
31 - private final Ip4Address remoteIp;
32 - private final TpPort port;
33 - private final String user;
34 - private final String privateKey;
35 -
36 - /**
37 - * Creates a new SSH access information.
38 - *
39 - * @param remoteIp ssh remote ip address
40 - * @param port ssh port number
41 - * @param user user name
42 - * @param privateKey path of ssh private key
43 - */
44 - public SshAccessInfo(Ip4Address remoteIp, TpPort port, String user, String privateKey) {
45 - this.remoteIp = checkNotNull(remoteIp);
46 - this.port = checkNotNull(port);
47 - this.user = checkNotNull(user);
48 - this.privateKey = checkNotNull(privateKey);
49 - }
50 -
51 - /**
52 - * Returns the remote IP address.
53 - *
54 - * @return ip address
55 - */
56 - public Ip4Address remoteIp() {
57 - return this.remoteIp;
58 - }
59 -
60 - /**
61 - * Returns the port number.
62 - *
63 - * @return ssh port
64 - */
65 - public TpPort port() {
66 - return this.port;
67 - }
68 -
69 - /**
70 - * Returns the user name.
71 - *
72 - * @return user name
73 - */
74 - public String user() {
75 - return this.user;
76 - }
77 -
78 - /**
79 - * Returns the private key path.
80 - *
81 - * @return privateKey
82 - */
83 - public String privateKey() {
84 - return privateKey;
85 - }
86 -
87 - @Override
88 - public boolean equals(Object obj) {
89 - if (this == obj) {
90 - return true;
91 - }
92 -
93 - if (obj instanceof SshAccessInfo) {
94 - SshAccessInfo that = (SshAccessInfo) obj;
95 - if (Objects.equals(remoteIp, that.remoteIp) &&
96 - Objects.equals(port, that.port) &&
97 - Objects.equals(user, that.user) &&
98 - Objects.equals(privateKey, that.privateKey)) {
99 - return true;
100 - }
101 - }
102 - return false;
103 - }
104 -
105 - @Override
106 - public int hashCode() {
107 - return Objects.hash(remoteIp, port, user, privateKey);
108 - }
109 -
110 - @Override
111 - public String toString() {
112 - return MoreObjects.toStringHelper(getClass())
113 - .add("remoteIp", remoteIp)
114 - .add("port", port)
115 - .add("user", user)
116 - .add("privateKey", privateKey)
117 - .toString();
118 - }
119 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * API for CORD VTN application.
19 - */
20 -package org.onosproject.cordvtn.api;
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordvtn.cli;
18 -
19 -import org.apache.karaf.shell.commands.Command;
20 -import org.onosproject.cli.AbstractShellCommand;
21 -import org.onosproject.cordvtn.impl.CordVtnPipeline;
22 -
23 -/**
24 - * Deletes nodes from the service.
25 - */
26 -@Command(scope = "onos", name = "cordvtn-flush-rules",
27 - description = "Flush flow rules installed by CORD VTN")
28 -public class CordVtnFlushRules extends AbstractShellCommand {
29 -
30 - @Override
31 - protected void execute() {
32 - CordVtnPipeline pipeline = AbstractShellCommand.get(CordVtnPipeline.class);
33 - pipeline.flushRules();
34 - print("Successfully flushed");
35 - }
36 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordvtn.cli;
18 -
19 -import org.apache.karaf.shell.commands.Argument;
20 -import org.apache.karaf.shell.commands.Command;
21 -import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.cordvtn.api.CordVtnNode;
23 -import org.onosproject.cordvtn.impl.CordVtnNodeManager;
24 -import org.onosproject.net.Device;
25 -import org.onosproject.net.device.DeviceService;
26 -import org.onosproject.net.driver.DriverService;
27 -
28 -/**
29 - * Checks detailed node init state.
30 - */
31 -@Command(scope = "onos", name = "cordvtn-node-check",
32 - description = "Shows detailed node init state")
33 -public class CordVtnNodeCheckCommand extends AbstractShellCommand {
34 -
35 - @Argument(index = 0, name = "hostname", description = "Hostname",
36 - required = true, multiValued = false)
37 - private String hostname = null;
38 -
39 - @Override
40 - protected void execute() {
41 - CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
42 - DeviceService deviceService = AbstractShellCommand.get(DeviceService.class);
43 -
44 - CordVtnNode node = nodeManager.getNodes()
45 - .stream()
46 - .filter(n -> n.hostname().equals(hostname))
47 - .findFirst()
48 - .orElse(null);
49 -
50 - if (node == null) {
51 - print("Cannot find %s from registered nodes", hostname);
52 - return;
53 - }
54 -
55 - print(nodeManager.checkNodeInitState(node));
56 -
57 - print("%n[DEBUG]");
58 - Device device = deviceService.getDevice(node.intBrId());
59 - String driver = get(DriverService.class).getDriver(device.id()).name();
60 - print("%s available=%s driver=%s %s",
61 - device.id(),
62 - deviceService.isAvailable(device.id()),
63 - driver,
64 - device.annotations());
65 -
66 - deviceService.getPorts(node.intBrId()).forEach(port -> {
67 - Object portIsEnabled = port.isEnabled() ? "enabled" : "disabled";
68 - print("port=%s state=%s %s",
69 - port.number(),
70 - portIsEnabled,
71 - port.annotations());
72 - });
73 - }
74 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordvtn.cli;
18 -
19 -import org.apache.karaf.shell.commands.Argument;
20 -import org.apache.karaf.shell.commands.Command;
21 -import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.cordvtn.impl.CordVtnNodeManager;
23 -import org.onosproject.cordvtn.api.CordVtnNode;
24 -
25 -import java.util.NoSuchElementException;
26 -
27 -/**
28 - * Deletes nodes from the service.
29 - */
30 -@Command(scope = "onos", name = "cordvtn-node-delete",
31 - description = "Deletes nodes from CORD VTN service")
32 -public class CordVtnNodeDeleteCommand extends AbstractShellCommand {
33 -
34 - @Argument(index = 0, name = "hostnames", description = "Hostname(s)",
35 - required = true, multiValued = true)
36 - private String[] hostnames = null;
37 -
38 - @Override
39 - protected void execute() {
40 - CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
41 -
42 - for (String hostname : hostnames) {
43 - CordVtnNode node;
44 - try {
45 - node = nodeManager.getNodes()
46 - .stream()
47 - .filter(n -> n.hostname().equals(hostname))
48 - .findFirst().get();
49 - } catch (NoSuchElementException e) {
50 - print("Unable to find %s", hostname);
51 - continue;
52 - }
53 -
54 - nodeManager.deleteNode(node);
55 - }
56 - }
57 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordvtn.cli;
18 -
19 -import org.apache.karaf.shell.commands.Argument;
20 -import org.apache.karaf.shell.commands.Command;
21 -import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.cordvtn.impl.CordVtnNodeManager;
23 -import org.onosproject.cordvtn.api.CordVtnNode;
24 -
25 -import java.util.NoSuchElementException;
26 -
27 -/**
28 - * Initializes nodes for CordVtn service.
29 - */
30 -@Command(scope = "onos", name = "cordvtn-node-init",
31 - description = "Initializes nodes for CORD VTN service")
32 -public class CordVtnNodeInitCommand extends AbstractShellCommand {
33 -
34 - @Argument(index = 0, name = "hostnames", description = "Hostname(s)",
35 - required = true, multiValued = true)
36 - private String[] hostnames = null;
37 -
38 - @Override
39 - protected void execute() {
40 - CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
41 -
42 - for (String hostname : hostnames) {
43 - CordVtnNode node;
44 - try {
45 - node = nodeManager.getNodes()
46 - .stream()
47 - .filter(n -> n.hostname().equals(hostname))
48 - .findFirst().get();
49 - } catch (NoSuchElementException e) {
50 - print("Unable to find %s", hostname);
51 - continue;
52 - }
53 -
54 - nodeManager.addOrUpdateNode(node);
55 - }
56 - }
57 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordvtn.cli;
18 -
19 -import com.fasterxml.jackson.databind.JsonNode;
20 -import com.fasterxml.jackson.databind.ObjectMapper;
21 -import com.fasterxml.jackson.databind.node.ArrayNode;
22 -import org.apache.karaf.shell.commands.Command;
23 -import org.onosproject.cli.AbstractShellCommand;
24 -import org.onosproject.cordvtn.impl.CordVtnNodeManager;
25 -import org.onosproject.cordvtn.api.CordVtnNode;
26 -
27 -import java.util.Collections;
28 -import java.util.List;
29 -
30 -/**
31 - * Lists all nodes registered to the service.
32 - */
33 -@Command(scope = "onos", name = "cordvtn-nodes",
34 - description = "Lists all nodes registered in CORD VTN service")
35 -public class CordVtnNodeListCommand extends AbstractShellCommand {
36 -
37 - private static final String COMPLETE = "COMPLETE";
38 - private static final String INCOMPLETE = "INCOMPLETE";
39 -
40 - @Override
41 - protected void execute() {
42 - CordVtnNodeManager nodeManager = AbstractShellCommand.get(CordVtnNodeManager.class);
43 - List<CordVtnNode> nodes = nodeManager.getNodes();
44 - Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR);
45 -
46 - if (outputJson()) {
47 - print("%s", json(nodeManager, nodes));
48 - } else {
49 - for (CordVtnNode node : nodes) {
50 - print("hostname=%s, hostMgmtIp=%s, dpIp=%s, br-int=%s, dpIntf=%s, init=%s",
51 - node.hostname(),
52 - node.hostMgmtIp().cidr(),
53 - node.dpIp().cidr(),
54 - node.intBrId().toString(),
55 - node.dpIntf(),
56 - getState(nodeManager, node));
57 - }
58 - print("Total %s nodes", nodeManager.getNodeCount());
59 - }
60 - }
61 -
62 - private JsonNode json(CordVtnNodeManager nodeManager, List<CordVtnNode> nodes) {
63 - ObjectMapper mapper = new ObjectMapper();
64 - ArrayNode result = mapper.createArrayNode();
65 - for (CordVtnNode node : nodes) {
66 - result.add(mapper.createObjectNode()
67 - .put("hostname", node.hostname())
68 - .put("hostManagementIp", node.hostMgmtIp().cidr())
69 - .put("dataPlaneIp", node.dpIp().cidr())
70 - .put("bridgeId", node.intBrId().toString())
71 - .put("dataPlaneInterface", node.dpIntf())
72 - .put("init", getState(nodeManager, node)));
73 - }
74 - return result;
75 - }
76 -
77 - private String getState(CordVtnNodeManager nodeManager, CordVtnNode node) {
78 - return nodeManager.isNodeInitComplete(node) ? COMPLETE : INCOMPLETE;
79 - }
80 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * Console commands to manage OVSDB nodes for cordvtn.
19 - */
20 -package org.onosproject.cordvtn.cli;
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl;
17 -
18 -import com.google.common.collect.Lists;
19 -import com.google.common.collect.Maps;
20 -import com.google.common.collect.Sets;
21 -import org.apache.felix.scr.annotations.Activate;
22 -import org.apache.felix.scr.annotations.Component;
23 -import org.apache.felix.scr.annotations.Deactivate;
24 -import org.apache.felix.scr.annotations.Reference;
25 -import org.apache.felix.scr.annotations.ReferenceCardinality;
26 -import org.apache.felix.scr.annotations.Service;
27 -import org.onlab.packet.Ethernet;
28 -import org.onlab.packet.Ip4Address;
29 -import org.onlab.packet.Ip4Prefix;
30 -import org.onosproject.cordvtn.api.CordVtnNode;
31 -import org.onosproject.cordvtn.api.CordVtnService;
32 -import org.onosproject.cordvtn.api.Instance;
33 -import org.onosproject.core.DefaultGroupId;
34 -import org.onosproject.core.GroupId;
35 -import org.onosproject.net.DeviceId;
36 -import org.onosproject.net.Host;
37 -import org.onosproject.net.PortNumber;
38 -import org.onosproject.net.flow.DefaultFlowRule;
39 -import org.onosproject.net.flow.DefaultTrafficSelector;
40 -import org.onosproject.net.flow.DefaultTrafficTreatment;
41 -import org.onosproject.net.flow.FlowRule;
42 -import org.onosproject.net.flow.TrafficSelector;
43 -import org.onosproject.net.flow.TrafficTreatment;
44 -import org.onosproject.net.flow.instructions.ExtensionTreatment;
45 -import org.onosproject.net.group.DefaultGroupDescription;
46 -import org.onosproject.net.group.DefaultGroupKey;
47 -import org.onosproject.net.group.Group;
48 -import org.onosproject.net.group.GroupBucket;
49 -import org.onosproject.net.group.GroupBuckets;
50 -import org.onosproject.net.group.GroupDescription;
51 -import org.onosproject.net.group.GroupKey;
52 -import org.onosproject.net.group.GroupService;
53 -import org.onosproject.net.host.HostEvent;
54 -import org.onosproject.net.host.HostListener;
55 -import org.onosproject.xosclient.api.VtnService;
56 -import org.onosproject.xosclient.api.VtnServiceId;
57 -import org.slf4j.Logger;
58 -
59 -import java.util.List;
60 -import java.util.Map;
61 -import java.util.Objects;
62 -import java.util.Set;
63 -import java.util.stream.Collectors;
64 -
65 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
66 -import static org.onlab.util.Tools.groupedThreads;
67 -import static org.onosproject.cordvtn.impl.CordVtnPipeline.*;
68 -import static org.onosproject.net.group.DefaultGroupBucket.createSelectGroupBucket;
69 -import static org.slf4j.LoggerFactory.getLogger;
70 -
71 -/**
72 - * Provisions service dependency capabilities between network services.
73 - */
74 -@Component(immediate = true)
75 -@Service
76 -public class CordVtn extends CordVtnInstanceHandler implements CordVtnService {
77 -
78 - protected final Logger log = getLogger(getClass());
79 -
80 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 - protected GroupService groupService;
82 -
83 - @Activate
84 - protected void activate() {
85 - eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn", "event-handler"));
86 - hostListener = new InternalHostListener();
87 - super.activate();
88 - }
89 -
90 - @Deactivate
91 - protected void deactivate() {
92 - super.deactivate();
93 - }
94 -
95 - @Override
96 - public void createServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId,
97 - boolean isBidirectional) {
98 - VtnService tService = getVtnService(tServiceId);
99 - VtnService pService = getVtnService(pServiceId);
100 -
101 - if (tService == null || pService == null) {
102 - log.error("Failed to create dependency between {} and {}",
103 - tServiceId, pServiceId);
104 - return;
105 - }
106 -
107 - log.info("Created dependency between {} and {}", tService.name(), pService.name());
108 - serviceDependencyRules(tService, pService, isBidirectional, true);
109 - }
110 -
111 - @Override
112 - public void removeServiceDependency(VtnServiceId tServiceId, VtnServiceId pServiceId) {
113 - VtnService tService = getVtnService(tServiceId);
114 - VtnService pService = getVtnService(pServiceId);
115 -
116 - if (tService == null || pService == null) {
117 - log.error("Failed to remove dependency between {} and {}",
118 - tServiceId, pServiceId);
119 - return;
120 - }
121 -
122 - log.info("Removed dependency between {} and {}", tService.name(), pService.name());
123 - serviceDependencyRules(tService, pService, true, false);
124 - }
125 -
126 - @Override
127 - public void instanceDetected(Instance instance) {
128 - VtnService service = getVtnService(instance.serviceId());
129 - if (service == null) {
130 - return;
131 - }
132 -
133 - // TODO get bidirectional information from XOS once XOS supports
134 - service.tenantServices().stream().forEach(
135 - tServiceId -> createServiceDependency(tServiceId, service.id(), true));
136 - service.providerServices().stream().forEach(
137 - pServiceId -> createServiceDependency(service.id(), pServiceId, true));
138 -
139 - updateProviderServiceInstances(service);
140 - }
141 -
142 - @Override
143 - public void instanceRemoved(Instance instance) {
144 - VtnService service = getVtnService(instance.serviceId());
145 - if (service == null) {
146 - return;
147 - }
148 -
149 - if (!service.providerServices().isEmpty()) {
150 - removeInstanceFromTenantService(instance, service);
151 - }
152 - if (!service.tenantServices().isEmpty()) {
153 - updateProviderServiceInstances(service);
154 - }
155 - }
156 -
157 - private void updateProviderServiceInstances(VtnService service) {
158 - GroupKey groupKey = getGroupKey(service.id());
159 -
160 - Set<DeviceId> devices = nodeManager.completeNodes().stream()
161 - .map(CordVtnNode::intBrId)
162 - .collect(Collectors.toSet());
163 -
164 - for (DeviceId deviceId : devices) {
165 - Group group = groupService.getGroup(deviceId, groupKey);
166 - if (group == null) {
167 - log.trace("No group exists for service {} in {}", service.id(), deviceId);
168 - continue;
169 - }
170 -
171 - List<GroupBucket> oldBuckets = group.buckets().buckets();
172 - List<GroupBucket> newBuckets = getServiceGroupBuckets(
173 - deviceId, service.vni(), getInstances(service.id())).buckets();
174 -
175 - if (oldBuckets.equals(newBuckets)) {
176 - continue;
177 - }
178 -
179 - List<GroupBucket> bucketsToRemove = Lists.newArrayList(oldBuckets);
180 - bucketsToRemove.removeAll(newBuckets);
181 - if (!bucketsToRemove.isEmpty()) {
182 - groupService.removeBucketsFromGroup(
183 - deviceId,
184 - groupKey,
185 - new GroupBuckets(bucketsToRemove),
186 - groupKey, appId);
187 - }
188 -
189 - List<GroupBucket> bucketsToAdd = Lists.newArrayList(newBuckets);
190 - bucketsToAdd.removeAll(oldBuckets);
191 - if (!bucketsToAdd.isEmpty()) {
192 - groupService.addBucketsToGroup(
193 - deviceId,
194 - groupKey,
195 - new GroupBuckets(bucketsToAdd),
196 - groupKey, appId);
197 - }
198 - }
199 - }
200 -
201 - private void removeInstanceFromTenantService(Instance instance, VtnService service) {
202 - service.providerServices().stream().forEach(pServiceId -> {
203 - Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
204 - Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
205 -
206 - inPorts.put(instance.deviceId(), Sets.newHashSet(instance.portNumber()));
207 - outGroups.put(instance.deviceId(), getGroupId(pServiceId, instance.deviceId()));
208 -
209 - inServiceRule(inPorts, outGroups, false);
210 - });
211 - }
212 -
213 - private void serviceDependencyRules(VtnService tService, VtnService pService,
214 - boolean isBidirectional, boolean install) {
215 - Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
216 - Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
217 -
218 - nodeManager.completeNodes().stream().forEach(node -> {
219 - DeviceId deviceId = node.intBrId();
220 - GroupId groupId = createServiceGroup(deviceId, pService);
221 - outGroups.put(deviceId, groupId);
222 -
223 - Set<PortNumber> tServiceInstances = getInstances(tService.id())
224 - .stream()
225 - .filter(instance -> instance.deviceId().equals(deviceId))
226 - .map(Instance::portNumber)
227 - .collect(Collectors.toSet());
228 - inPorts.put(deviceId, tServiceInstances);
229 - });
230 -
231 - Ip4Prefix srcRange = tService.subnet().getIp4Prefix();
232 - Ip4Prefix dstRange = pService.subnet().getIp4Prefix();
233 -
234 - indirectAccessRule(srcRange, pService.serviceIp().getIp4Address(), outGroups, install);
235 - directAccessRule(srcRange, dstRange, install);
236 - if (isBidirectional) {
237 - directAccessRule(dstRange, srcRange, install);
238 - }
239 - inServiceRule(inPorts, outGroups, install);
240 - }
241 -
242 - private void indirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
243 - Map<DeviceId, GroupId> outGroups, boolean install) {
244 - TrafficSelector selector = DefaultTrafficSelector.builder()
245 - .matchEthType(Ethernet.TYPE_IPV4)
246 - .matchIPSrc(srcRange)
247 - .matchIPDst(serviceIp.toIpPrefix())
248 - .build();
249 -
250 - for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
251 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
252 - .group(outGroup.getValue())
253 - .build();
254 -
255 - FlowRule flowRule = DefaultFlowRule.builder()
256 - .fromApp(appId)
257 - .withSelector(selector)
258 - .withTreatment(treatment)
259 - .withPriority(PRIORITY_HIGH)
260 - .forDevice(outGroup.getKey())
261 - .forTable(TABLE_ACCESS_TYPE)
262 - .makePermanent()
263 - .build();
264 -
265 - pipeline.processFlowRule(install, flowRule);
266 - }
267 - }
268 -
269 - private void directAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange, boolean install) {
270 - TrafficSelector selector = DefaultTrafficSelector.builder()
271 - .matchEthType(Ethernet.TYPE_IPV4)
272 - .matchIPSrc(srcRange)
273 - .matchIPDst(dstRange)
274 - .build();
275 -
276 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
277 - .transition(TABLE_DST_IP)
278 - .build();
279 -
280 - nodeManager.completeNodes().stream().forEach(node -> {
281 - DeviceId deviceId = node.intBrId();
282 - FlowRule flowRuleDirect = DefaultFlowRule.builder()
283 - .fromApp(appId)
284 - .withSelector(selector)
285 - .withTreatment(treatment)
286 - .withPriority(PRIORITY_DEFAULT)
287 - .forDevice(deviceId)
288 - .forTable(TABLE_ACCESS_TYPE)
289 - .makePermanent()
290 - .build();
291 -
292 - pipeline.processFlowRule(install, flowRuleDirect);
293 - });
294 - }
295 -
296 - private void inServiceRule(Map<DeviceId, Set<PortNumber>> inPorts,
297 - Map<DeviceId, GroupId> outGroups, boolean install) {
298 - for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
299 - Set<PortNumber> ports = entry.getValue();
300 - DeviceId deviceId = entry.getKey();
301 -
302 - GroupId groupId = outGroups.get(deviceId);
303 - if (groupId == null) {
304 - continue;
305 - }
306 -
307 - ports.stream().forEach(port -> {
308 - TrafficSelector selector = DefaultTrafficSelector.builder()
309 - .matchInPort(port)
310 - .build();
311 -
312 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
313 - .group(groupId)
314 - .build();
315 -
316 - FlowRule flowRule = DefaultFlowRule.builder()
317 - .fromApp(appId)
318 - .withSelector(selector)
319 - .withTreatment(treatment)
320 - .withPriority(PRIORITY_DEFAULT)
321 - .forDevice(deviceId)
322 - .forTable(TABLE_IN_SERVICE)
323 - .makePermanent()
324 - .build();
325 -
326 - pipeline.processFlowRule(install, flowRule);
327 - });
328 - }
329 - }
330 -
331 - private GroupId getGroupId(VtnServiceId serviceId, DeviceId deviceId) {
332 - return new DefaultGroupId(Objects.hash(serviceId, deviceId));
333 - }
334 -
335 - private GroupKey getGroupKey(VtnServiceId serviceId) {
336 - return new DefaultGroupKey(serviceId.id().getBytes());
337 - }
338 -
339 - private GroupId createServiceGroup(DeviceId deviceId, VtnService service) {
340 - GroupKey groupKey = getGroupKey(service.id());
341 - Group group = groupService.getGroup(deviceId, groupKey);
342 - GroupId groupId = getGroupId(service.id(), deviceId);
343 -
344 - if (group != null) {
345 - log.debug("Group {} is already exist in {}", service.id(), deviceId);
346 - return groupId;
347 - }
348 -
349 - GroupBuckets buckets = getServiceGroupBuckets(
350 - deviceId, service.vni(), getInstances(service.id()));
351 - GroupDescription groupDescription = new DefaultGroupDescription(
352 - deviceId,
353 - GroupDescription.Type.SELECT,
354 - buckets,
355 - groupKey,
356 - groupId.id(),
357 - appId);
358 -
359 - groupService.addGroup(groupDescription);
360 - return groupId;
361 - }
362 -
363 - private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId,
364 - Set<Instance> instances) {
365 - List<GroupBucket> buckets = Lists.newArrayList();
366 - instances.stream().forEach(instance -> {
367 - Ip4Address tunnelIp = nodeManager.dpIp(instance.deviceId()).getIp4Address();
368 - TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
369 -
370 - if (deviceId.equals(instance.deviceId())) {
371 - tBuilder.setEthDst(instance.mac())
372 - .setOutput(instance.portNumber());
373 - } else {
374 - ExtensionTreatment tunnelDst =
375 - pipeline.tunnelDstTreatment(deviceId, tunnelIp);
376 - tBuilder.setEthDst(instance.mac())
377 - .extension(tunnelDst, deviceId)
378 - .setTunnelId(tunnelId)
379 - .setOutput(nodeManager.tunnelPort(instance.deviceId()));
380 - }
381 - buckets.add(createSelectGroupBucket(tBuilder.build()));
382 - });
383 - return new GroupBuckets(buckets);
384 - }
385 -
386 - private class InternalHostListener implements HostListener {
387 -
388 - @Override
389 - public void event(HostEvent event) {
390 - Host host = event.subject();
391 - if (!mastershipService.isLocalMaster(host.location().deviceId())) {
392 - // do not allow to proceed without mastership
393 - return;
394 - }
395 -
396 - Instance instance = Instance.of(host);
397 - switch (event.type()) {
398 - case HOST_UPDATED:
399 - case HOST_ADDED:
400 - eventExecutor.execute(() -> instanceDetected(instance));
401 - break;
402 - case HOST_REMOVED:
403 - eventExecutor.execute(() -> instanceRemoved(instance));
404 - break;
405 - default:
406 - break;
407 - }
408 - }
409 - }
410 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl;
17 -
18 -import com.google.common.collect.Maps;
19 -import org.onlab.packet.ARP;
20 -import org.onlab.packet.EthType;
21 -import org.onlab.packet.Ethernet;
22 -import org.onlab.packet.Ip4Address;
23 -import org.onlab.packet.IpAddress;
24 -import org.onlab.packet.MacAddress;
25 -import org.onosproject.cordvtn.api.Instance;
26 -import org.onosproject.core.ApplicationId;
27 -import org.onosproject.net.Host;
28 -import org.onosproject.net.flow.DefaultTrafficSelector;
29 -import org.onosproject.net.flow.DefaultTrafficTreatment;
30 -import org.onosproject.net.flow.TrafficSelector;
31 -import org.onosproject.net.flow.TrafficTreatment;
32 -import org.onosproject.net.host.HostService;
33 -import org.onosproject.net.packet.DefaultOutboundPacket;
34 -import org.onosproject.net.packet.PacketContext;
35 -import org.onosproject.net.packet.PacketPriority;
36 -import org.onosproject.net.packet.PacketService;
37 -import org.slf4j.Logger;
38 -
39 -import java.nio.ByteBuffer;
40 -import java.util.Map;
41 -import java.util.Optional;
42 -import java.util.Set;
43 -
44 -import static com.google.common.base.Preconditions.checkNotNull;
45 -import static org.slf4j.LoggerFactory.getLogger;
46 -
47 -/**
48 - * Handles ARP requests for virtual network service IPs.
49 - */
50 -public class CordVtnArpProxy {
51 - protected final Logger log = getLogger(getClass());
52 -
53 - private final ApplicationId appId;
54 - private final PacketService packetService;
55 - private final HostService hostService;
56 -
57 - private final Map<Ip4Address, MacAddress> gateways = Maps.newConcurrentMap();
58 -
59 - /**
60 - * Default constructor.
61 - *
62 - * @param appId application id
63 - * @param packetService packet service
64 - * @param hostService host service reference
65 - */
66 - public CordVtnArpProxy(ApplicationId appId, PacketService packetService, HostService hostService) {
67 - this.appId = appId;
68 - this.packetService = packetService;
69 - this.hostService = hostService;
70 - }
71 -
72 - /**
73 - * Requests ARP packet.
74 - */
75 - public void requestPacket() {
76 - TrafficSelector selector = DefaultTrafficSelector.builder()
77 - .matchEthType(EthType.EtherType.ARP.ethType().toShort())
78 - .build();
79 -
80 - packetService.requestPackets(selector,
81 - PacketPriority.CONTROL,
82 - appId,
83 - Optional.empty());
84 - }
85 -
86 - /**
87 - * Cancels ARP packet.
88 - */
89 - public void cancelPacket() {
90 - TrafficSelector selector = DefaultTrafficSelector.builder()
91 - .matchEthType(EthType.EtherType.ARP.ethType().toShort())
92 - .build();
93 -
94 - packetService.cancelPackets(selector,
95 - PacketPriority.CONTROL,
96 - appId,
97 - Optional.empty());
98 - }
99 -
100 - /**
101 - * Adds a given gateway IP and MAC address to this ARP proxy.
102 - *
103 - * @param gatewayIp gateway ip address
104 - * @param gatewayMac gateway mac address
105 - */
106 - public void addGateway(IpAddress gatewayIp, MacAddress gatewayMac) {
107 - checkNotNull(gatewayIp);
108 - checkNotNull(gatewayMac);
109 - gateways.put(gatewayIp.getIp4Address(), gatewayMac);
110 - }
111 -
112 - /**
113 - * Removes a given service IP address from this ARP proxy.
114 - *
115 - * @param gatewayIp gateway ip address
116 - */
117 - public void removeGateway(IpAddress gatewayIp) {
118 - checkNotNull(gatewayIp);
119 - gateways.remove(gatewayIp.getIp4Address());
120 - }
121 -
122 - /**
123 - * Emits ARP reply with fake MAC address for a given ARP request.
124 - * It only handles requests for the registered service IPs, and the other
125 - * requests can be handled by other ARP handlers like openstackSwitching or
126 - * proxyArp, for example.
127 - *
128 - * @param context packet context
129 - * @param ethPacket ethernet packet
130 - */
131 - public void processArpPacket(PacketContext context, Ethernet ethPacket) {
132 - ARP arpPacket = (ARP) ethPacket.getPayload();
133 - if (arpPacket.getOpCode() != ARP.OP_REQUEST) {
134 - return;
135 - }
136 -
137 - Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());
138 -
139 - MacAddress gatewayMac = gateways.get(targetIp);
140 - MacAddress replyMac = gatewayMac != null ? gatewayMac : getMacFromHostService(targetIp);
141 -
142 - if (replyMac.equals(MacAddress.NONE)) {
143 - log.debug("Failed to find MAC for {}", targetIp.toString());
144 - context.block();
145 - return;
146 - }
147 -
148 - log.trace("Send ARP reply for {} with {}", targetIp.toString(), replyMac.toString());
149 - Ethernet ethReply = ARP.buildArpReply(
150 - targetIp,
151 - replyMac,
152 - ethPacket);
153 -
154 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
155 - .setOutput(context.inPacket().receivedFrom().port())
156 - .build();
157 -
158 - packetService.emit(new DefaultOutboundPacket(
159 - context.inPacket().receivedFrom().deviceId(),
160 - treatment,
161 - ByteBuffer.wrap(ethReply.serialize())));
162 -
163 - context.block();
164 - }
165 -
166 - /**
167 - * Emits gratuitous ARP when a gateway mac address has been changed.
168 - *
169 - * @param gatewayIp gateway ip address to update MAC
170 - * @param instances set of instances to send gratuitous ARP packet
171 - */
172 - public void sendGratuitousArpForGateway(IpAddress gatewayIp, Set<Instance> instances) {
173 - MacAddress gatewayMac = gateways.get(gatewayIp.getIp4Address());
174 - if (gatewayMac == null) {
175 - log.debug("Gateway {} is not registered to ARP proxy", gatewayIp.toString());
176 - return;
177 - }
178 -
179 - Ethernet ethArp = buildGratuitousArp(gatewayIp.getIp4Address(), gatewayMac);
180 - instances.stream().forEach(instance -> {
181 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
182 - .setOutput(instance.portNumber())
183 - .build();
184 -
185 - packetService.emit(new DefaultOutboundPacket(
186 - instance.deviceId(),
187 - treatment,
188 - ByteBuffer.wrap(ethArp.serialize())));
189 - });
190 - }
191 -
192 - /**
193 - * Builds gratuitous ARP packet with a given IP and MAC address.
194 - *
195 - * @param ip ip address for TPA and SPA
196 - * @param mac new mac address
197 - * @return ethernet packet
198 - */
199 - private Ethernet buildGratuitousArp(IpAddress ip, MacAddress mac) {
200 - Ethernet eth = new Ethernet();
201 -
202 - eth.setEtherType(Ethernet.TYPE_ARP);
203 - eth.setSourceMACAddress(mac);
204 - eth.setDestinationMACAddress(MacAddress.BROADCAST);
205 -
206 - ARP arp = new ARP();
207 - arp.setOpCode(ARP.OP_REQUEST);
208 - arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
209 - arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
210 - arp.setProtocolType(ARP.PROTO_TYPE_IP);
211 - arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);
212 -
213 - arp.setSenderHardwareAddress(mac.toBytes());
214 - arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
215 - arp.setSenderProtocolAddress(ip.getIp4Address().toOctets());
216 - arp.setTargetProtocolAddress(ip.getIp4Address().toOctets());
217 -
218 - eth.setPayload(arp);
219 - return eth;
220 - }
221 -
222 - /**
223 - * Returns MAC address of a host with a given target IP address by asking to
224 - * host service. It does not support overlapping IP.
225 - *
226 - * @param targetIp target ip
227 - * @return mac address, or NONE mac address if it fails to find the mac
228 - */
229 - private MacAddress getMacFromHostService(IpAddress targetIp) {
230 - checkNotNull(targetIp);
231 -
232 - Host host = hostService.getHostsByIp(targetIp)
233 - .stream()
234 - .findFirst()
235 - .orElse(null);
236 -
237 - if (host != null) {
238 - log.trace("Found MAC from host service for {}", targetIp.toString());
239 - return host.mac();
240 - } else {
241 - return MacAddress.NONE;
242 - }
243 - }
244 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl;
17 -
18 -import org.apache.felix.scr.annotations.Component;
19 -import org.apache.felix.scr.annotations.Reference;
20 -import org.apache.felix.scr.annotations.ReferenceCardinality;
21 -import org.onlab.packet.Ethernet;
22 -import org.onlab.packet.Ip4Address;
23 -import org.onlab.packet.Ip4Prefix;
24 -import org.onosproject.cordvtn.api.CordVtnConfig;
25 -import org.onosproject.cordvtn.api.CordVtnNode;
26 -import org.onosproject.cordvtn.api.CordVtnService;
27 -import org.onosproject.cordvtn.api.Instance;
28 -import org.onosproject.cordvtn.api.InstanceHandler;
29 -import org.onosproject.core.ApplicationId;
30 -import org.onosproject.core.CoreService;
31 -import org.onosproject.mastership.MastershipService;
32 -import org.onosproject.net.Host;
33 -import org.onosproject.net.PortNumber;
34 -import org.onosproject.net.config.NetworkConfigEvent;
35 -import org.onosproject.net.config.NetworkConfigListener;
36 -import org.onosproject.net.config.NetworkConfigRegistry;
37 -import org.onosproject.net.flow.DefaultFlowRule;
38 -import org.onosproject.net.flow.DefaultTrafficSelector;
39 -import org.onosproject.net.flow.DefaultTrafficTreatment;
40 -import org.onosproject.net.flow.FlowRule;
41 -import org.onosproject.net.flow.TrafficSelector;
42 -import org.onosproject.net.flow.TrafficTreatment;
43 -import org.onosproject.net.flow.instructions.ExtensionTreatment;
44 -import org.onosproject.net.host.HostEvent;
45 -import org.onosproject.net.host.HostListener;
46 -import org.onosproject.net.host.HostService;
47 -import org.onosproject.xosclient.api.OpenStackAccess;
48 -import org.onosproject.xosclient.api.VtnService;
49 -import org.onosproject.xosclient.api.VtnServiceApi;
50 -import org.onosproject.xosclient.api.VtnServiceId;
51 -import org.onosproject.xosclient.api.XosAccess;
52 -import org.onosproject.xosclient.api.XosClientService;
53 -import org.slf4j.Logger;
54 -
55 -import java.util.Objects;
56 -import java.util.Set;
57 -import java.util.concurrent.ExecutorService;
58 -import java.util.stream.Collectors;
59 -import java.util.stream.StreamSupport;
60 -
61 -import static com.google.common.base.Preconditions.checkNotNull;
62 -import static org.onosproject.cordvtn.impl.CordVtnPipeline.*;
63 -import static org.onosproject.xosclient.api.VtnService.NetworkType.MANAGEMENT;
64 -import static org.slf4j.LoggerFactory.getLogger;
65 -
66 -/**
67 - * Provides default virtual network connectivity for service instances.
68 - */
69 -@Component(immediate = true)
70 -public abstract class CordVtnInstanceHandler implements InstanceHandler {
71 -
72 - protected final Logger log = getLogger(getClass());
73 -
74 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
75 - protected CoreService coreService;
76 -
77 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
78 - protected MastershipService mastershipService;
79 -
80 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
81 - protected NetworkConfigRegistry configRegistry;
82 -
83 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 - protected HostService hostService;
85 -
86 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 - protected XosClientService xosClient;
88 -
89 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 - protected CordVtnNodeManager nodeManager;
91 -
92 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 - protected CordVtnPipeline pipeline;
94 -
95 - protected static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
96 - protected static final String XOS_ACCESS_ERROR = "XOS access is not configured";
97 -
98 - protected XosAccess xosAccess = null;
99 - protected OpenStackAccess osAccess = null;
100 - protected ApplicationId appId;
101 - protected VtnService.ServiceType serviceType;
102 - protected ExecutorService eventExecutor;
103 -
104 - protected HostListener hostListener = new InternalHostListener();
105 - protected NetworkConfigListener configListener = new InternalConfigListener();
106 -
107 - protected void activate() {
108 - // sub class should set service type and event executor in its activate method
109 - appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
110 -
111 - hostService.addListener(hostListener);
112 - configRegistry.addListener(configListener);
113 -
114 - log.info("Started");
115 - }
116 -
117 - protected void deactivate() {
118 - hostService.removeListener(hostListener);
119 - configRegistry.removeListener(configListener);
120 - eventExecutor.shutdown();
121 -
122 - log.info("Stopped");
123 - }
124 -
125 - @Override
126 - public void instanceDetected(Instance instance) {
127 - log.info("Instance is detected {}", instance);
128 -
129 - VtnService service = getVtnService(instance.serviceId());
130 - if (service == null) {
131 - log.warn("Failed to get VtnService for {}", instance);
132 - return;
133 - }
134 -
135 - if (service.networkType().equals(MANAGEMENT)) {
136 - managementNetworkRules(instance, service, true);
137 - }
138 -
139 - defaultConnectionRules(instance, service, true);
140 - }
141 -
142 - @Override
143 - public void instanceRemoved(Instance instance) {
144 - log.info("Instance is removed {}", instance);
145 -
146 - VtnService service = getVtnService(instance.serviceId());
147 - if (service == null) {
148 - log.warn("Failed to get VtnService for {}", instance);
149 - return;
150 - }
151 -
152 - if (service.networkType().equals(MANAGEMENT)) {
153 - managementNetworkRules(instance, service, false);
154 - }
155 -
156 - // TODO check if any stale management network rules are
157 - defaultConnectionRules(instance, service, false);
158 - }
159 -
160 - protected VtnService getVtnService(VtnServiceId serviceId) {
161 - checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
162 - checkNotNull(xosAccess, XOS_ACCESS_ERROR);
163 -
164 - // TODO remove openstack access when XOS provides all information
165 - VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
166 - VtnService service = serviceApi.service(serviceId, osAccess);
167 - if (service == null) {
168 - log.warn("Failed to get VtnService for {}", serviceId);
169 - }
170 - return service;
171 - }
172 -
173 - protected Set<Instance> getInstances(VtnServiceId serviceId) {
174 - return StreamSupport.stream(hostService.getHosts().spliterator(), false)
175 - .filter(host -> Objects.equals(
176 - serviceId.id(),
177 - host.annotations().value(Instance.SERVICE_ID)))
178 - .map(Instance::of)
179 - .collect(Collectors.toSet());
180 - }
181 -
182 - private void defaultConnectionRules(Instance instance, VtnService service, boolean install) {
183 - long vni = service.vni();
184 - Ip4Prefix serviceIpRange = service.subnet().getIp4Prefix();
185 -
186 - inPortRule(instance, install);
187 - dstIpRule(instance, vni, install);
188 - tunnelInRule(instance, vni, install);
189 -
190 - if (install) {
191 - directAccessRule(serviceIpRange, serviceIpRange, true);
192 - serviceIsolationRule(serviceIpRange, true);
193 - } else if (getInstances(service.id()).isEmpty()) {
194 - directAccessRule(serviceIpRange, serviceIpRange, false);
195 - serviceIsolationRule(serviceIpRange, false);
196 - }
197 - }
198 -
199 - private void managementNetworkRules(Instance instance, VtnService service, boolean install) {
200 -
201 - managementPerInstanceRule(instance, install);
202 - if (install) {
203 - managementBaseRule(instance, service, true);
204 - } else if (!hostService.getConnectedHosts(instance.deviceId()).stream()
205 - .filter(host -> Instance.of(host).serviceId().equals(service.id()))
206 - .findAny()
207 - .isPresent()) {
208 - managementBaseRule(instance, service, false);
209 - }
210 - }
211 -
212 - private void managementBaseRule(Instance instance, VtnService service, boolean install) {
213 - TrafficSelector selector = DefaultTrafficSelector.builder()
214 - .matchEthType(Ethernet.TYPE_ARP)
215 - .matchArpTpa(service.serviceIp().getIp4Address())
216 - .build();
217 -
218 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
219 - .setOutput(PortNumber.LOCAL)
220 - .build();
221 -
222 - FlowRule flowRule = DefaultFlowRule.builder()
223 - .fromApp(appId)
224 - .withSelector(selector)
225 - .withTreatment(treatment)
226 - .withPriority(PRIORITY_MANAGEMENT)
227 - .forDevice(instance.deviceId())
228 - .forTable(TABLE_ZERO)
229 - .makePermanent()
230 - .build();
231 -
232 - pipeline.processFlowRule(install, flowRule);
233 -
234 - selector = DefaultTrafficSelector.builder()
235 - .matchInPort(PortNumber.LOCAL)
236 - .matchEthType(Ethernet.TYPE_IPV4)
237 - .matchIPDst(service.subnet())
238 - .build();
239 -
240 - treatment = DefaultTrafficTreatment.builder()
241 - .transition(TABLE_DST_IP)
242 - .build();
243 -
244 - flowRule = DefaultFlowRule.builder()
245 - .fromApp(appId)
246 - .withSelector(selector)
247 - .withTreatment(treatment)
248 - .withPriority(PRIORITY_MANAGEMENT)
249 - .forDevice(instance.deviceId())
250 - .forTable(TABLE_ZERO)
251 - .makePermanent()
252 - .build();
253 -
254 - pipeline.processFlowRule(install, flowRule);
255 -
256 - selector = DefaultTrafficSelector.builder()
257 - .matchEthType(Ethernet.TYPE_IPV4)
258 - .matchIPDst(service.serviceIp().toIpPrefix())
259 - .build();
260 -
261 - treatment = DefaultTrafficTreatment.builder()
262 - .setOutput(PortNumber.LOCAL)
263 - .build();
264 -
265 - flowRule = DefaultFlowRule.builder()
266 - .fromApp(appId)
267 - .withSelector(selector)
268 - .withTreatment(treatment)
269 - .withPriority(PRIORITY_MANAGEMENT)
270 - .forDevice(instance.deviceId())
271 - .forTable(TABLE_ACCESS_TYPE)
272 - .makePermanent()
273 - .build();
274 -
275 - pipeline.processFlowRule(install, flowRule);
276 - }
277 -
278 - private void managementPerInstanceRule(Instance instance, boolean install) {
279 - TrafficSelector selector = DefaultTrafficSelector.builder()
280 - .matchInPort(PortNumber.LOCAL)
281 - .matchEthType(Ethernet.TYPE_ARP)
282 - .matchArpTpa(instance.ipAddress().getIp4Address())
283 - .build();
284 -
285 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
286 - .setOutput(instance.portNumber())
287 - .build();
288 -
289 - FlowRule flowRule = DefaultFlowRule.builder()
290 - .fromApp(appId)
291 - .withSelector(selector)
292 - .withTreatment(treatment)
293 - .withPriority(PRIORITY_MANAGEMENT)
294 - .forDevice(instance.deviceId())
295 - .forTable(TABLE_ZERO)
296 - .makePermanent()
297 - .build();
298 -
299 - pipeline.processFlowRule(install, flowRule);
300 - }
301 -
302 - private void inPortRule(Instance instance, boolean install) {
303 - TrafficSelector selector = DefaultTrafficSelector.builder()
304 - .matchInPort(instance.portNumber())
305 - .matchEthType(Ethernet.TYPE_IPV4)
306 - .matchIPSrc(instance.ipAddress().toIpPrefix())
307 - .build();
308 -
309 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
310 - .transition(TABLE_ACCESS_TYPE)
311 - .build();
312 -
313 -
314 - FlowRule flowRule = DefaultFlowRule.builder()
315 - .fromApp(appId)
316 - .withSelector(selector)
317 - .withTreatment(treatment)
318 - .withPriority(PRIORITY_DEFAULT)
319 - .forDevice(instance.deviceId())
320 - .forTable(TABLE_IN_PORT)
321 - .makePermanent()
322 - .build();
323 -
324 - pipeline.processFlowRule(install, flowRule);
325 -
326 - selector = DefaultTrafficSelector.builder()
327 - .matchInPort(instance.portNumber())
328 - .build();
329 -
330 - treatment = DefaultTrafficTreatment.builder()
331 - .transition(TABLE_IN_SERVICE)
332 - .build();
333 -
334 - flowRule = DefaultFlowRule.builder()
335 - .fromApp(appId)
336 - .withSelector(selector)
337 - .withTreatment(treatment)
338 - .withPriority(PRIORITY_LOW)
339 - .forDevice(instance.deviceId())
340 - .forTable(TABLE_IN_PORT)
341 - .makePermanent()
342 - .build();
343 -
344 - pipeline.processFlowRule(install, flowRule);
345 - }
346 -
347 - private void dstIpRule(Instance instance, long vni, boolean install) {
348 - Ip4Address tunnelIp = nodeManager.dpIp(instance.deviceId()).getIp4Address();
349 -
350 - TrafficSelector selector = DefaultTrafficSelector.builder()
351 - .matchEthType(Ethernet.TYPE_IPV4)
352 - .matchIPDst(instance.ipAddress().toIpPrefix())
353 - .build();
354 -
355 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
356 - .setEthDst(instance.mac())
357 - .setOutput(instance.portNumber())
358 - .build();
359 -
360 - FlowRule flowRule = DefaultFlowRule.builder()
361 - .fromApp(appId)
362 - .withSelector(selector)
363 - .withTreatment(treatment)
364 - .withPriority(PRIORITY_DEFAULT)
365 - .forDevice(instance.deviceId())
366 - .forTable(TABLE_DST_IP)
367 - .makePermanent()
368 - .build();
369 -
370 - pipeline.processFlowRule(install, flowRule);
371 -
372 - for (CordVtnNode node : nodeManager.completeNodes()) {
373 - if (node.intBrId().equals(instance.deviceId())) {
374 - continue;
375 - }
376 -
377 - ExtensionTreatment tunnelDst = pipeline.tunnelDstTreatment(node.intBrId(), tunnelIp);
378 - if (tunnelDst == null) {
379 - continue;
380 - }
381 -
382 - treatment = DefaultTrafficTreatment.builder()
383 - .setEthDst(instance.mac())
384 - .setTunnelId(vni)
385 - .extension(tunnelDst, node.intBrId())
386 - .setOutput(nodeManager.tunnelPort(node.intBrId()))
387 - .build();
388 -
389 - flowRule = DefaultFlowRule.builder()
390 - .fromApp(appId)
391 - .withSelector(selector)
392 - .withTreatment(treatment)
393 - .withPriority(PRIORITY_DEFAULT)
394 - .forDevice(node.intBrId())
395 - .forTable(TABLE_DST_IP)
396 - .makePermanent()
397 - .build();
398 -
399 - pipeline.processFlowRule(install, flowRule);
400 - }
401 - }
402 -
403 - private void tunnelInRule(Instance instance, long vni, boolean install) {
404 - TrafficSelector selector = DefaultTrafficSelector.builder()
405 - .matchTunnelId(vni)
406 - .matchEthDst(instance.mac())
407 - .build();
408 -
409 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
410 - .setOutput(instance.portNumber())
411 - .build();
412 -
413 - FlowRule flowRule = DefaultFlowRule.builder()
414 - .fromApp(appId)
415 - .withSelector(selector)
416 - .withTreatment(treatment)
417 - .withPriority(PRIORITY_DEFAULT)
418 - .forDevice(instance.deviceId())
419 - .forTable(TABLE_TUNNEL_IN)
420 - .makePermanent()
421 - .build();
422 -
423 - pipeline.processFlowRule(install, flowRule);
424 - }
425 -
426 - private void directAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange, boolean install) {
427 - TrafficSelector selector = DefaultTrafficSelector.builder()
428 - .matchEthType(Ethernet.TYPE_IPV4)
429 - .matchIPSrc(srcRange)
430 - .matchIPDst(dstRange)
431 - .build();
432 -
433 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
434 - .transition(TABLE_DST_IP)
435 - .build();
436 -
437 -
438 - nodeManager.completeNodes().stream().forEach(node -> {
439 - FlowRule flowRuleDirect = DefaultFlowRule.builder()
440 - .fromApp(appId)
441 - .withSelector(selector)
442 - .withTreatment(treatment)
443 - .withPriority(PRIORITY_DEFAULT)
444 - .forDevice(node.intBrId())
445 - .forTable(TABLE_ACCESS_TYPE)
446 - .makePermanent()
447 - .build();
448 -
449 - pipeline.processFlowRule(install, flowRuleDirect);
450 - });
451 - }
452 -
453 - private void serviceIsolationRule(Ip4Prefix dstRange, boolean install) {
454 - TrafficSelector selector = DefaultTrafficSelector.builder()
455 - .matchEthType(Ethernet.TYPE_IPV4)
456 - .matchIPDst(dstRange)
457 - .build();
458 -
459 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
460 - .drop()
461 - .build();
462 -
463 - nodeManager.completeNodes().stream().forEach(node -> {
464 - FlowRule flowRuleDirect = DefaultFlowRule.builder()
465 - .fromApp(appId)
466 - .withSelector(selector)
467 - .withTreatment(treatment)
468 - .withPriority(PRIORITY_LOW)
469 - .forDevice(node.intBrId())
470 - .forTable(TABLE_ACCESS_TYPE)
471 - .makePermanent()
472 - .build();
473 -
474 - pipeline.processFlowRule(install, flowRuleDirect);
475 - });
476 - }
477 -
478 - protected void readConfiguration() {
479 - CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
480 - if (config == null) {
481 - log.debug("No configuration found");
482 - return;
483 - }
484 - osAccess = config.openstackAccess();
485 - xosAccess = config.xosAccess();
486 - }
487 -
488 - public class InternalHostListener implements HostListener {
489 -
490 - @Override
491 - public void event(HostEvent event) {
492 - Host host = event.subject();
493 - if (!mastershipService.isLocalMaster(host.location().deviceId())) {
494 - // do not allow to proceed without mastership
495 - return;
496 - }
497 -
498 - Instance instance = Instance.of(host);
499 - if (!Objects.equals(instance.serviceType(), serviceType)) {
500 - // not my service instance, do nothing
501 - return;
502 - }
503 -
504 - switch (event.type()) {
505 - case HOST_UPDATED:
506 - case HOST_ADDED:
507 - eventExecutor.execute(() -> instanceDetected(instance));
508 - break;
509 - case HOST_REMOVED:
510 - eventExecutor.execute(() -> instanceRemoved(instance));
511 - break;
512 - default:
513 - break;
514 - }
515 - }
516 - }
517 -
518 - public class InternalConfigListener implements NetworkConfigListener {
519 -
520 - @Override
521 - public void event(NetworkConfigEvent event) {
522 - if (!event.configClass().equals(CordVtnConfig.class)) {
523 - return;
524 - }
525 -
526 - switch (event.type()) {
527 - case CONFIG_ADDED:
528 - case CONFIG_UPDATED:
529 - readConfiguration();
530 - break;
531 - default:
532 - break;
533 - }
534 - }
535 - }
536 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl;
17 -
18 -import com.google.common.collect.Sets;
19 -import org.apache.felix.scr.annotations.Activate;
20 -import org.apache.felix.scr.annotations.Component;
21 -import org.apache.felix.scr.annotations.Deactivate;
22 -import org.apache.felix.scr.annotations.Reference;
23 -import org.apache.felix.scr.annotations.ReferenceCardinality;
24 -import org.apache.felix.scr.annotations.Service;
25 -import org.onlab.packet.Ethernet;
26 -import org.onlab.packet.Ip4Address;
27 -import org.onlab.packet.IpAddress;
28 -import org.onlab.packet.MacAddress;
29 -import org.onlab.packet.VlanId;
30 -import org.onosproject.cordvtn.api.CordVtnConfig;
31 -import org.onosproject.cordvtn.api.CordVtnService;
32 -import org.onosproject.cordvtn.api.Instance;
33 -import org.onosproject.core.ApplicationId;
34 -import org.onosproject.core.CoreService;
35 -import org.onosproject.dhcp.DhcpService;
36 -import org.onosproject.dhcp.IpAssignment;
37 -import org.onosproject.mastership.MastershipService;
38 -import org.onosproject.net.ConnectPoint;
39 -import org.onosproject.net.DefaultAnnotations;
40 -import org.onosproject.net.Host;
41 -import org.onosproject.net.HostId;
42 -import org.onosproject.net.HostLocation;
43 -import org.onosproject.net.Port;
44 -import org.onosproject.net.config.ConfigFactory;
45 -import org.onosproject.net.config.NetworkConfigEvent;
46 -import org.onosproject.net.config.NetworkConfigListener;
47 -import org.onosproject.net.config.NetworkConfigRegistry;
48 -import org.onosproject.net.config.basics.SubjectFactories;
49 -import org.onosproject.net.device.DeviceService;
50 -import org.onosproject.net.host.DefaultHostDescription;
51 -import org.onosproject.net.host.HostDescription;
52 -import org.onosproject.net.host.HostEvent;
53 -import org.onosproject.net.host.HostListener;
54 -import org.onosproject.net.host.HostProvider;
55 -import org.onosproject.net.host.HostProviderRegistry;
56 -import org.onosproject.net.host.HostProviderService;
57 -import org.onosproject.net.host.HostService;
58 -import org.onosproject.net.packet.PacketContext;
59 -import org.onosproject.net.packet.PacketProcessor;
60 -import org.onosproject.net.packet.PacketService;
61 -import org.onosproject.net.provider.AbstractProvider;
62 -import org.onosproject.net.provider.ProviderId;
63 -import org.onosproject.xosclient.api.OpenStackAccess;
64 -import org.onosproject.xosclient.api.VtnPort;
65 -import org.onosproject.xosclient.api.VtnPortApi;
66 -import org.onosproject.xosclient.api.VtnService;
67 -import org.onosproject.xosclient.api.VtnServiceApi;
68 -import org.onosproject.xosclient.api.VtnServiceId;
69 -import org.onosproject.xosclient.api.XosAccess;
70 -import org.onosproject.xosclient.api.XosClientService;
71 -import org.slf4j.Logger;
72 -
73 -import java.util.Date;
74 -import java.util.Map;
75 -import java.util.Objects;
76 -import java.util.Set;
77 -import java.util.concurrent.ExecutorService;
78 -import java.util.stream.Collectors;
79 -import java.util.stream.StreamSupport;
80 -
81 -import static com.google.common.base.Preconditions.checkNotNull;
82 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
83 -import static org.onlab.util.Tools.groupedThreads;
84 -import static org.onosproject.cordvtn.api.Instance.*;
85 -import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
86 -import static org.onosproject.xosclient.api.VtnService.NetworkType.MANAGEMENT;
87 -import static org.onosproject.xosclient.api.VtnService.NetworkType.PRIVATE;
88 -import static org.slf4j.LoggerFactory.getLogger;
89 -
90 -/**
91 - * Adds or removes instances to network services.
92 - */
93 -@Component(immediate = true)
94 -@Service(value = CordVtnInstanceManager.class)
95 -public class CordVtnInstanceManager extends AbstractProvider implements HostProvider {
96 -
97 - protected final Logger log = getLogger(getClass());
98 -
99 - private static final String XOS_ACCESS_ERROR = "XOS access is not configured";
100 - private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
101 - private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
102 - private static final int DHCP_INFINITE_LEASE = -1;
103 -
104 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 - protected CoreService coreService;
106 -
107 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 - protected NetworkConfigRegistry configRegistry;
109 -
110 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 - protected HostProviderRegistry hostProviderRegistry;
112 -
113 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 - protected DeviceService deviceService;
115 -
116 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 - protected HostService hostService;
118 -
119 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 - protected PacketService packetService;
121 -
122 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 - protected DhcpService dhcpService;
124 -
125 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 - protected MastershipService mastershipService;
127 -
128 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
129 - protected XosClientService xosClient;
130 -
131 - private final ConfigFactory configFactory =
132 - new ConfigFactory(SubjectFactories.APP_SUBJECT_FACTORY, CordVtnConfig.class, "cordvtn") {
133 - @Override
134 - public CordVtnConfig createConfig() {
135 - return new CordVtnConfig();
136 - }
137 - };
138 -
139 - private final ExecutorService eventExecutor =
140 - newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-instance", "event-handler"));
141 - private final PacketProcessor packetProcessor = new InternalPacketProcessor();
142 - private final HostListener hostListener = new InternalHostListener();
143 - private final NetworkConfigListener configListener = new InternalConfigListener();
144 -
145 - private ApplicationId appId;
146 - private HostProviderService hostProvider;
147 - private CordVtnArpProxy arpProxy; // TODO make it a component service
148 - private MacAddress privateGatewayMac = MacAddress.NONE;
149 - private XosAccess xosAccess = null;
150 - private OpenStackAccess osAccess = null;
151 -
152 - /**
153 - * Creates an cordvtn host location provider.
154 - */
155 - public CordVtnInstanceManager() {
156 - super(new ProviderId("host", CordVtnService.CORDVTN_APP_ID));
157 - }
158 -
159 - @Activate
160 - protected void activate() {
161 - appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
162 -
163 - arpProxy = new CordVtnArpProxy(appId, packetService, hostService);
164 - packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
165 - arpProxy.requestPacket();
166 -
167 - hostService.addListener(hostListener);
168 - hostProvider = hostProviderRegistry.register(this);
169 -
170 - configRegistry.registerConfigFactory(configFactory);
171 - configRegistry.addListener(configListener);
172 -
173 - log.info("Started");
174 - }
175 -
176 - @Deactivate
177 - protected void deactivate() {
178 - hostProviderRegistry.unregister(this);
179 - hostService.removeListener(hostListener);
180 -
181 - packetService.removeProcessor(packetProcessor);
182 -
183 - configRegistry.unregisterConfigFactory(configFactory);
184 - configRegistry.removeListener(configListener);
185 -
186 - eventExecutor.shutdown();
187 - log.info("Stopped");
188 - }
189 -
190 - @Override
191 - public void triggerProbe(Host host) {
192 - /*
193 - * Note: In CORD deployment, we assume that all hosts are configured.
194 - * Therefore no probe is required.
195 - */
196 - }
197 -
198 - /**
199 - * Adds a service instance at a given connect point.
200 - *
201 - * @param connectPoint connect point of the instance
202 - */
203 - public void addInstance(ConnectPoint connectPoint) {
204 - Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
205 - if (port == null) {
206 - log.debug("No port found from {}", connectPoint);
207 - return;
208 - }
209 -
210 - VtnPort vtnPort = getVtnPort(port.annotations().value("portName"));
211 - if (vtnPort == null) {
212 - return;
213 - }
214 -
215 - VtnService vtnService = getVtnService(vtnPort.serviceId());
216 - if (vtnService == null) {
217 - return;
218 - }
219 -
220 - // Added CREATE_TIME intentionally to trigger HOST_UPDATED event for the
221 - // existing instances.
222 - DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
223 - .set(SERVICE_TYPE, vtnService.serviceType().toString())
224 - .set(SERVICE_ID, vtnPort.serviceId().id())
225 - .set(PORT_ID, vtnPort.id().id())
226 - .set(CREATE_TIME, String.valueOf(System.currentTimeMillis()));
227 -
228 - HostDescription hostDesc = new DefaultHostDescription(
229 - vtnPort.mac(),
230 - VlanId.NONE,
231 - new HostLocation(connectPoint, System.currentTimeMillis()),
232 - Sets.newHashSet(vtnPort.ip()),
233 - annotations.build());
234 -
235 - HostId hostId = HostId.hostId(vtnPort.mac());
236 - hostProvider.hostDetected(hostId, hostDesc, false);
237 - }
238 -
239 - /**
240 - * Adds a service instance with given host ID and host description.
241 - *
242 - * @param hostId host id
243 - * @param description host description
244 - */
245 - public void addInstance(HostId hostId, HostDescription description) {
246 - hostProvider.hostDetected(hostId, description, false);
247 - }
248 -
249 - /**
250 - * Removes a service instance from a given connect point.
251 - *
252 - * @param connectPoint connect point
253 - */
254 - public void removeInstance(ConnectPoint connectPoint) {
255 - hostService.getConnectedHosts(connectPoint)
256 - .stream()
257 - .forEach(host -> hostProvider.hostVanished(host.id()));
258 - }
259 -
260 - /**
261 - * Removes service instance with given host ID.
262 - *
263 - * @param hostId host id
264 - */
265 - public void removeInstance(HostId hostId) {
266 - hostProvider.hostVanished(hostId);
267 - }
268 -
269 - private void instanceDetected(Instance instance) {
270 - VtnService service = getVtnService(instance.serviceId());
271 - if (service == null) {
272 - return;
273 - }
274 -
275 - if (service.networkType().equals(PRIVATE)) {
276 - arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
277 - arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(instance));
278 - }
279 - if (!instance.isNestedInstance()) {
280 - registerDhcpLease(instance, service);
281 - }
282 - }
283 -
284 - private void instanceRemoved(Instance instance) {
285 - VtnService service = getVtnService(instance.serviceId());
286 - if (service == null) {
287 - return;
288 - }
289 -
290 - if (service.networkType().equals(PRIVATE) && getInstances(service.id()).isEmpty()) {
291 - arpProxy.removeGateway(service.serviceIp());
292 - }
293 -
294 - if (!instance.isNestedInstance()) {
295 - dhcpService.removeStaticMapping(instance.mac());
296 - }
297 - }
298 -
299 - private void registerDhcpLease(Instance instance, VtnService service) {
300 - Ip4Address broadcast = Ip4Address.makeMaskedAddress(
301 - instance.ipAddress(),
302 - service.subnet().prefixLength());
303 -
304 - IpAssignment.Builder ipBuilder = IpAssignment.builder()
305 - .ipAddress(instance.ipAddress())
306 - .leasePeriod(DHCP_INFINITE_LEASE)
307 - .timestamp(new Date())
308 - .subnetMask(Ip4Address.makeMaskPrefix(service.subnet().prefixLength()))
309 - .broadcast(broadcast)
310 - .domainServer(DEFAULT_DNS)
311 - .assignmentStatus(Option_RangeNotEnforced);
312 -
313 - if (service.networkType() != MANAGEMENT) {
314 - ipBuilder = ipBuilder.routerAddress(service.serviceIp().getIp4Address());
315 - }
316 -
317 - log.debug("Set static DHCP mapping for {} {}", instance.mac(), instance.ipAddress());
318 - dhcpService.setStaticMapping(instance.mac(), ipBuilder.build());
319 - }
320 -
321 - private VtnService getVtnService(VtnServiceId serviceId) {
322 - checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
323 - checkNotNull(xosAccess, XOS_ACCESS_ERROR);
324 -
325 - // TODO remove openstack access when XOS provides all information
326 - VtnServiceApi serviceApi = xosClient.getClient(xosAccess).vtnService();
327 - VtnService service = serviceApi.service(serviceId, osAccess);
328 - if (service == null) {
329 - log.warn("Failed to get VtnService for {}", serviceId);
330 - }
331 - return service;
332 - }
333 -
334 - private VtnPort getVtnPort(String portName) {
335 - checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
336 - checkNotNull(xosAccess, XOS_ACCESS_ERROR);
337 -
338 - // TODO remove openstack access when XOS provides all information
339 - VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
340 - VtnPort vtnPort = portApi.vtnPort(portName, osAccess);
341 - if (vtnPort == null) {
342 - log.warn("Failed to get port information of {}", portName);
343 - }
344 - return vtnPort;
345 - }
346 -
347 - private Set<Instance> getInstances(VtnServiceId serviceId) {
348 - return StreamSupport.stream(hostService.getHosts().spliterator(), false)
349 - .filter(host -> Objects.equals(
350 - serviceId.id(),
351 - host.annotations().value(Instance.SERVICE_ID)))
352 - .map(Instance::of)
353 - .collect(Collectors.toSet());
354 - }
355 -
356 - private void readConfiguration() {
357 - CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
358 - if (config == null) {
359 - log.debug("No configuration found");
360 - return;
361 - }
362 -
363 - log.info("Load CORD-VTN configurations");
364 -
365 - xosAccess = config.xosAccess();
366 - osAccess = config.openstackAccess();
367 - privateGatewayMac = config.privateGatewayMac();
368 -
369 - Map<IpAddress, MacAddress> publicGateways = config.publicGateways();
370 - publicGateways.entrySet()
371 - .stream()
372 - .forEach(entry -> {
373 - arpProxy.addGateway(entry.getKey(), entry.getValue());
374 - log.debug("Added public gateway IP {}, MAC {}",
375 - entry.getKey(), entry.getValue());
376 - });
377 - // TODO notice gateway MAC change to VMs holds this gateway IP
378 - }
379 -
380 - private class InternalHostListener implements HostListener {
381 -
382 - @Override
383 - public void event(HostEvent event) {
384 - Host host = event.subject();
385 - if (!mastershipService.isLocalMaster(host.location().deviceId())) {
386 - // do not allow to proceed without mastership
387 - return;
388 - }
389 -
390 - Instance instance = Instance.of(host);
391 - switch (event.type()) {
392 - case HOST_UPDATED:
393 - case HOST_ADDED:
394 - eventExecutor.execute(() -> instanceDetected(instance));
395 - break;
396 - case HOST_REMOVED:
397 - eventExecutor.execute(() -> instanceRemoved(instance));
398 - break;
399 - default:
400 - break;
401 - }
402 - }
403 - }
404 -
405 - private class InternalPacketProcessor implements PacketProcessor {
406 -
407 - @Override
408 - public void process(PacketContext context) {
409 - if (context.isHandled()) {
410 - return;
411 - }
412 - Ethernet ethPacket = context.inPacket().parsed();
413 - if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
414 - return;
415 - }
416 - arpProxy.processArpPacket(context, ethPacket);
417 - }
418 - }
419 -
420 - private class InternalConfigListener implements NetworkConfigListener {
421 -
422 - @Override
423 - public void event(NetworkConfigEvent event) {
424 - if (!event.configClass().equals(CordVtnConfig.class)) {
425 - return;
426 - }
427 -
428 - switch (event.type()) {
429 - case CONFIG_ADDED:
430 - case CONFIG_UPDATED:
431 - readConfiguration();
432 - break;
433 - default:
434 - break;
435 - }
436 - }
437 - }
438 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl;
17 -
18 -import com.google.common.collect.Sets;
19 -import com.jcraft.jsch.Session;
20 -import org.apache.felix.scr.annotations.Activate;
21 -import org.apache.felix.scr.annotations.Component;
22 -import org.apache.felix.scr.annotations.Deactivate;
23 -import org.apache.felix.scr.annotations.Reference;
24 -import org.apache.felix.scr.annotations.ReferenceCardinality;
25 -import org.apache.felix.scr.annotations.Service;
26 -import org.onlab.packet.IpAddress;
27 -import org.onlab.util.ItemNotFoundException;
28 -import org.onlab.util.KryoNamespace;
29 -import org.onosproject.cluster.ClusterService;
30 -import org.onosproject.cluster.LeadershipService;
31 -import org.onosproject.cluster.NodeId;
32 -import org.onosproject.cordvtn.api.ConnectionHandler;
33 -import org.onosproject.cordvtn.api.CordVtnConfig;
34 -import org.onosproject.cordvtn.api.CordVtnNode;
35 -import org.onosproject.cordvtn.api.CordVtnNodeState;
36 -import org.onosproject.cordvtn.api.CordVtnService;
37 -import org.onosproject.cordvtn.api.NetworkAddress;
38 -import org.onosproject.cordvtn.api.SshAccessInfo;
39 -import org.onosproject.core.ApplicationId;
40 -import org.onosproject.core.CoreService;
41 -import org.onosproject.net.ConnectPoint;
42 -import org.onosproject.net.DefaultAnnotations;
43 -import org.onosproject.net.Device;
44 -import org.onosproject.net.DeviceId;
45 -import org.onosproject.net.Host;
46 -import org.onosproject.net.Port;
47 -import org.onosproject.net.PortNumber;
48 -import org.onosproject.net.behaviour.BridgeConfig;
49 -import org.onosproject.net.behaviour.BridgeName;
50 -import org.onosproject.net.behaviour.ControllerInfo;
51 -import org.onosproject.net.behaviour.DefaultTunnelDescription;
52 -import org.onosproject.net.behaviour.TunnelConfig;
53 -import org.onosproject.net.behaviour.TunnelDescription;
54 -import org.onosproject.net.behaviour.TunnelName;
55 -import org.onosproject.net.config.NetworkConfigEvent;
56 -import org.onosproject.net.config.NetworkConfigListener;
57 -import org.onosproject.net.config.NetworkConfigRegistry;
58 -import org.onosproject.net.config.NetworkConfigService;
59 -import org.onosproject.net.device.DeviceAdminService;
60 -import org.onosproject.net.device.DeviceEvent;
61 -import org.onosproject.net.device.DeviceListener;
62 -import org.onosproject.net.device.DeviceService;
63 -import org.onosproject.net.host.HostService;
64 -import org.onosproject.ovsdb.controller.OvsdbClientService;
65 -import org.onosproject.ovsdb.controller.OvsdbController;
66 -import org.onosproject.ovsdb.controller.OvsdbNodeId;
67 -import org.onosproject.store.serializers.KryoNamespaces;
68 -import org.onosproject.store.service.ConsistentMap;
69 -import org.onosproject.store.service.MapEvent;
70 -import org.onosproject.store.service.MapEventListener;
71 -import org.onosproject.store.service.Serializer;
72 -import org.onosproject.store.service.StorageService;
73 -import org.onosproject.store.service.Versioned;
74 -import org.slf4j.Logger;
75 -
76 -import java.util.ArrayList;
77 -import java.util.HashMap;
78 -import java.util.List;
79 -import java.util.Map;
80 -import java.util.Objects;
81 -import java.util.Set;
82 -import java.util.concurrent.ExecutorService;
83 -import java.util.stream.Collectors;
84 -
85 -import static com.google.common.base.Preconditions.checkNotNull;
86 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
87 -import static org.onlab.util.Tools.groupedThreads;
88 -import static org.onosproject.cordvtn.impl.CordVtnPipeline.DEFAULT_TUNNEL;
89 -import static org.onosproject.cordvtn.impl.RemoteIpCommandUtil.*;
90 -import static org.onosproject.net.Device.Type.SWITCH;
91 -import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
92 -import static org.slf4j.LoggerFactory.getLogger;
93 -
94 -/**
95 - * Reads node information from the network config file and handles the config
96 - * update events.
97 - * Only a leader controller performs the node addition or deletion.
98 - */
99 -@Component(immediate = true)
100 -@Service(value = CordVtnNodeManager.class)
101 -public class CordVtnNodeManager {
102 -
103 - protected final Logger log = getLogger(getClass());
104 -
105 - private static final KryoNamespace.Builder NODE_SERIALIZER = KryoNamespace.newBuilder()
106 - .register(KryoNamespaces.API)
107 - .register(CordVtnNode.class)
108 - .register(NodeState.class)
109 - .register(SshAccessInfo.class)
110 - .register(NetworkAddress.class);
111 -
112 - private static final String DEFAULT_BRIDGE = "br-int";
113 - private static final String VPORT_PREFIX = "tap";
114 - private static final String OK = "OK";
115 - private static final String NO = "NO";
116 -
117 - private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
118 - {
119 - put("key", "flow");
120 - put("remote_ip", "flow");
121 - }
122 - };
123 - private static final int DPID_BEGIN = 3;
124 - private static final int OFPORT = 6653;
125 -
126 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 - protected CoreService coreService;
128 -
129 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 - protected NetworkConfigRegistry configRegistry;
131 -
132 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 - protected NetworkConfigService configService;
134 -
135 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 - protected StorageService storageService;
137 -
138 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
139 - protected DeviceAdminService adminService;
140 -
141 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 - protected OvsdbController controller;
143 -
144 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
145 - protected ClusterService clusterService;
146 -
147 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
148 - protected DeviceService deviceService;
149 -
150 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
151 - protected HostService hostService;
152 -
153 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
154 - protected LeadershipService leadershipService;
155 -
156 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
157 - protected CordVtnInstanceManager instanceManager;
158 -
159 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
160 - protected CordVtnPipeline pipeline;
161 -
162 - private final ExecutorService eventExecutor =
163 - newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-node", "event-handler"));
164 -
165 - private final NetworkConfigListener configListener = new InternalConfigListener();
166 - private final DeviceListener deviceListener = new InternalDeviceListener();
167 - private final MapEventListener<String, CordVtnNode> nodeStoreListener = new InternalMapListener();
168 -
169 - private final OvsdbHandler ovsdbHandler = new OvsdbHandler();
170 - private final BridgeHandler bridgeHandler = new BridgeHandler();
171 -
172 - private ConsistentMap<String, CordVtnNode> nodeStore;
173 - private ApplicationId appId;
174 - private NodeId localNodeId;
175 -
176 - private enum NodeState implements CordVtnNodeState {
177 -
178 - INIT {
179 - @Override
180 - public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
181 - if (!nodeManager.isOvsdbConnected(node)) {
182 - nodeManager.connectOvsdb(node);
183 - } else {
184 - nodeManager.createIntegrationBridge(node);
185 - }
186 - }
187 - },
188 - BRIDGE_CREATED {
189 - @Override
190 - public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
191 - if (!nodeManager.isOvsdbConnected(node)) {
192 - nodeManager.connectOvsdb(node);
193 - } else {
194 - nodeManager.createTunnelInterface(node);
195 - nodeManager.addDataPlaneInterface(node);
196 - }
197 - }
198 - },
199 - PORTS_ADDED {
200 - @Override
201 - public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
202 - nodeManager.setIpAddress(node);
203 - }
204 - },
205 - COMPLETE {
206 - @Override
207 - public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
208 - nodeManager.postInit(node);
209 - }
210 - },
211 - INCOMPLETE {
212 - @Override
213 - public void process(CordVtnNodeManager nodeManager, CordVtnNode node) {
214 - }
215 - };
216 -
217 - public abstract void process(CordVtnNodeManager nodeManager, CordVtnNode node);
218 - }
219 -
220 - @Activate
221 - protected void activate() {
222 - appId = coreService.getAppId(CordVtnService.CORDVTN_APP_ID);
223 -
224 - localNodeId = clusterService.getLocalNode().id();
225 - leadershipService.runForLeadership(appId.name());
226 -
227 - nodeStore = storageService.<String, CordVtnNode>consistentMapBuilder()
228 - .withSerializer(Serializer.using(NODE_SERIALIZER.build()))
229 - .withName("cordvtn-nodestore")
230 - .withApplicationId(appId)
231 - .build();
232 -
233 - nodeStore.addListener(nodeStoreListener);
234 - deviceService.addListener(deviceListener);
235 - configService.addListener(configListener);
236 -
237 - log.info("Started");
238 - }
239 -
240 - @Deactivate
241 - protected void deactivate() {
242 - configService.removeListener(configListener);
243 - deviceService.removeListener(deviceListener);
244 - nodeStore.removeListener(nodeStoreListener);
245 -
246 - leadershipService.withdraw(appId.name());
247 - eventExecutor.shutdown();
248 -
249 - log.info("Stopped");
250 - }
251 -
252 - /**
253 - * Adds or updates a new node to the service.
254 - *
255 - * @param node cordvtn node
256 - */
257 - public void addOrUpdateNode(CordVtnNode node) {
258 - checkNotNull(node);
259 - nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, getNodeState(node)));
260 - }
261 -
262 - /**
263 - * Deletes a node from the service.
264 - *
265 - * @param node cordvtn node
266 - */
267 - public void deleteNode(CordVtnNode node) {
268 - checkNotNull(node);
269 -
270 - if (isOvsdbConnected(node)) {
271 - disconnectOvsdb(node);
272 - }
273 -
274 - nodeStore.remove(node.hostname());
275 - }
276 -
277 - /**
278 - * Returns node initialization state.
279 - *
280 - * @param node cordvtn node
281 - * @return true if initial node setup is completed, otherwise false
282 - */
283 - public boolean isNodeInitComplete(CordVtnNode node) {
284 - checkNotNull(node);
285 - return nodeStore.containsKey(node.hostname()) && getNodeState(node).equals(NodeState.COMPLETE);
286 - }
287 -
288 - /**
289 - * Returns detailed node initialization state.
290 - *
291 - * @param node cordvtn node
292 - * @return string including detailed node init state
293 - */
294 - public String checkNodeInitState(CordVtnNode node) {
295 - checkNotNull(node);
296 -
297 - if (!nodeStore.containsKey(node.hostname())) {
298 - log.warn("Node {} does not exist, add node first", node.hostname());
299 - return null;
300 - }
301 -
302 - Session session = connect(node.sshInfo());
303 - if (session == null) {
304 - log.debug("Failed to SSH to {}", node.hostname());
305 - return null;
306 - }
307 -
308 - Set<IpAddress> intBrIps = getCurrentIps(session, DEFAULT_BRIDGE);
309 - String result = String.format(
310 - "Current state : %s%n" +
311 - "br-int created and connected to ONOS : %s (%s)%n" +
312 - "VXLAN interface added to br-int : %s%n" +
313 - "Data plane interface is added to br-int and enabled : %s (%s)%n" +
314 - "IP flushed from data plane interface : %s (%s)%n" +
315 - "Data plane IP added to br-int : %s (%s)%n" +
316 - "Local management IP added to br-int : %s (%s)",
317 - node.state(),
318 - isBrIntCreated(node) ? OK : NO, node.intBrId(),
319 - isTunnelIntfCreated(node) ? OK : NO,
320 - isDataPlaneIntfAdded(node) ? OK : NO, node.dpIntf(),
321 - isInterfaceUp(session, node.dpIntf()) &&
322 - getCurrentIps(session, node.dpIntf()).isEmpty() ? OK : NO, node.dpIntf(),
323 - intBrIps.contains(node.dpIp().ip()) ? OK : NO, node.dpIp().cidr(),
324 - intBrIps.contains(node.localMgmtIp().ip()) ? OK : NO, node.localMgmtIp().cidr());
325 -
326 - disconnect(session);
327 -
328 - return result;
329 - }
330 -
331 - /**
332 - * Returns the number of the nodes known to the service.
333 - *
334 - * @return number of nodes
335 - */
336 - public int getNodeCount() {
337 - return nodeStore.size();
338 - }
339 -
340 - /**
341 - * Returns all nodes known to the service.
342 - *
343 - * @return list of nodes
344 - */
345 - public List<CordVtnNode> getNodes() {
346 - return nodeStore.values().stream().map(Versioned::value).collect(Collectors.toList());
347 - }
348 -
349 - /**
350 - * Returns all nodes in complete state.
351 - *
352 - * @return set of nodes
353 - */
354 - public Set<CordVtnNode> completeNodes() {
355 - return getNodes().stream().filter(this::isNodeInitComplete).collect(Collectors.toSet());
356 - }
357 -
358 - /**
359 - * Returns physical data plane port number of a given device.
360 - *
361 - * @param deviceId integration bridge device id
362 - * @return port number; null otherwise
363 - */
364 - public PortNumber dpPort(DeviceId deviceId) {
365 - CordVtnNode node = nodeByBridgeId(deviceId);
366 - if (node == null) {
367 - log.warn("Failed to get node for {}", deviceId);
368 - return null;
369 - }
370 - Port port = deviceService.getPorts(deviceId).stream()
371 - .filter(p -> portName(p).contains(node.dpIntf()) &&
372 - p.isEnabled())
373 - .findFirst().orElse(null);
374 -
375 - return port == null ? null : port.number();
376 - }
377 -
378 - /**
379 - * Returns physical data plane IP address of a given device.
380 - *
381 - * @param deviceId integration bridge device id
382 - * @return ip address; null otherwise
383 - */
384 - public IpAddress dpIp(DeviceId deviceId) {
385 - CordVtnNode node = nodeByBridgeId(deviceId);
386 - if (node == null) {
387 - log.warn("Failed to get node for {}", deviceId);
388 - return null;
389 - }
390 - return node.dpIp().ip();
391 - }
392 -
393 - /**
394 - * Returns tunnel port number of a given device.
395 - *
396 - * @param deviceId integration bridge device id
397 - * @return port number
398 - */
399 - public PortNumber tunnelPort(DeviceId deviceId) {
400 - Port port = deviceService.getPorts(deviceId).stream()
401 - .filter(p -> portName(p).contains(DEFAULT_TUNNEL))
402 - .findFirst().orElse(null);
403 -
404 - return port == null ? null : port.number();
405 - }
406 -
407 - /**
408 - * Returns if current node state saved in nodeStore is COMPLETE or not.
409 - *
410 - * @param node cordvtn node
411 - * @return true if it's complete state, otherwise false
412 - */
413 - private boolean isNodeStateComplete(CordVtnNode node) {
414 - checkNotNull(node);
415 -
416 - // the state saved in nodeStore can be wrong if IP address settings are changed
417 - // after the node init has been completed since there's no way to detect it
418 - // getNodeState and checkNodeInitState always return correct answer but can be slow
419 - Versioned<CordVtnNode> versionedNode = nodeStore.get(node.hostname());
420 - CordVtnNodeState state = versionedNode.value().state();
421 - return state != null && state.equals(NodeState.COMPLETE);
422 - }
423 -
424 - /**
425 - * Initiates node to serve virtual tenant network.
426 - *
427 - * @param node cordvtn node
428 - */
429 - private void initNode(CordVtnNode node) {
430 - checkNotNull(node);
431 -
432 - NodeState state = (NodeState) node.state();
433 - log.debug("Processing node: {} state: {}", node.hostname(), state);
434 -
435 - state.process(this, node);
436 - }
437 -
438 - /**
439 - * Performs tasks after node initialization.
440 - * It disconnects unnecessary OVSDB connection and installs initial flow
441 - * rules on the device.
442 - *
443 - * @param node cordvtn node
444 - */
445 - private void postInit(CordVtnNode node) {
446 - disconnectOvsdb(node);
447 - pipeline.initPipeline(node, dpPort(node.intBrId()), tunnelPort(node.intBrId()));
448 -
449 - deviceService.getPorts(node.intBrId()).stream()
450 - .filter(port -> portName(port).startsWith(VPORT_PREFIX) &&
451 - port.isEnabled())
452 - .forEach(port -> instanceManager.addInstance(connectPoint(port)));
453 -
454 - hostService.getHosts().forEach(host -> {
455 - if (deviceService.getPort(host.location().deviceId(),
456 - host.location().port()) == null) {
457 - instanceManager.removeInstance(connectPoint(host));
458 - }
459 - });
460 -
461 - log.info("Finished init {}", node.hostname());
462 - }
463 -
464 - /**
465 - * Sets a new state for a given cordvtn node.
466 - *
467 - * @param node cordvtn node
468 - * @param newState new node state
469 - */
470 - private void setNodeState(CordVtnNode node, NodeState newState) {
471 - checkNotNull(node);
472 -
473 - log.debug("Changed {} state: {}", node.hostname(), newState);
474 - nodeStore.put(node.hostname(), CordVtnNode.getUpdatedNode(node, newState));
475 - }
476 -
477 - /**
478 - * Checks current state of a given cordvtn node and returns it.
479 - *
480 - * @param node cordvtn node
481 - * @return node state
482 - */
483 - private NodeState getNodeState(CordVtnNode node) {
484 - checkNotNull(node);
485 -
486 - if (isBrIntCreated(node) && isTunnelIntfCreated(node) &&
487 - isDataPlaneIntfAdded(node) && isIpAddressSet(node)) {
488 - return NodeState.COMPLETE;
489 - } else if (isDataPlaneIntfAdded(node) && isTunnelIntfCreated(node)) {
490 - return NodeState.PORTS_ADDED;
491 - } else if (isBrIntCreated(node)) {
492 - return NodeState.BRIDGE_CREATED;
493 - } else {
494 - return NodeState.INIT;
495 - }
496 - }
497 -
498 - /**
499 - * Returns connection state of OVSDB server for a given node.
500 - *
501 - * @param node cordvtn node
502 - * @return true if it is connected, false otherwise
503 - */
504 - private boolean isOvsdbConnected(CordVtnNode node) {
505 - checkNotNull(node);
506 -
507 - OvsdbClientService ovsdbClient = getOvsdbClient(node);
508 - return deviceService.isAvailable(node.ovsdbId()) &&
509 - ovsdbClient != null && ovsdbClient.isConnected();
510 - }
511 -
512 - /**
513 - * Connects to OVSDB server for a given node.
514 - *
515 - * @param node cordvtn node
516 - */
517 - private void connectOvsdb(CordVtnNode node) {
518 - checkNotNull(node);
519 -
520 - if (!nodeStore.containsKey(node.hostname())) {
521 - log.warn("Node {} does not exist", node.hostname());
522 - return;
523 - }
524 -
525 - if (!isOvsdbConnected(node)) {
526 - controller.connect(node.hostMgmtIp().ip(), node.ovsdbPort());
527 - }
528 - }
529 -
530 - /**
531 - * Disconnects OVSDB server for a given node.
532 - *
533 - * @param node cordvtn node
534 - */
535 - private void disconnectOvsdb(CordVtnNode node) {
536 - checkNotNull(node);
537 -
538 - if (!nodeStore.containsKey(node.hostname())) {
539 - log.warn("Node {} does not exist", node.hostname());
540 - return;
541 - }
542 -
543 - if (isOvsdbConnected(node)) {
544 - OvsdbClientService ovsdbClient = getOvsdbClient(node);
545 - ovsdbClient.disconnect();
546 - }
547 - }
548 -
549 - /**
550 - * Returns OVSDB client for a given node.
551 - *
552 - * @param node cordvtn node
553 - * @return OVSDB client, or null if it fails to get OVSDB client
554 - */
555 - private OvsdbClientService getOvsdbClient(CordVtnNode node) {
556 - checkNotNull(node);
557 -
558 - OvsdbClientService ovsdbClient = controller.getOvsdbClient(
559 - new OvsdbNodeId(node.hostMgmtIp().ip(), node.ovsdbPort().toInt()));
560 - if (ovsdbClient == null) {
561 - log.trace("Couldn't find OVSDB client for {}", node.hostname());
562 - }
563 - return ovsdbClient;
564 - }
565 -
566 - /**
567 - * Creates an integration bridge for a given node.
568 - *
569 - * @param node cordvtn node
570 - */
571 - private void createIntegrationBridge(CordVtnNode node) {
572 - if (isBrIntCreated(node)) {
573 - return;
574 - }
575 -
576 - List<ControllerInfo> controllers = new ArrayList<>();
577 - Sets.newHashSet(clusterService.getNodes()).stream()
578 - .forEach(controller -> {
579 - ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
580 - controllers.add(ctrlInfo);
581 - });
582 -
583 - String dpid = node.intBrId().toString().substring(DPID_BEGIN);
584 -
585 - try {
586 - Device device = deviceService.getDevice(node.ovsdbId());
587 - if (device.is(BridgeConfig.class)) {
588 - BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
589 - bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers);
590 - } else {
591 - log.warn("The bridging behaviour is not supported in device {}", device.id());
592 - }
593 - } catch (ItemNotFoundException e) {
594 - log.warn("Failed to create integration bridge on {}", node.hostname());
595 - }
596 - }
597 -
598 - /**
599 - * Creates tunnel interface to the integration bridge for a given node.
600 - *
601 - * @param node cordvtn node
602 - */
603 - private void createTunnelInterface(CordVtnNode node) {
604 - if (isTunnelIntfCreated(node)) {
605 - return;
606 - }
607 -
608 - DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
609 - for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
610 - optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
611 - }
612 -
613 - TunnelDescription description = new DefaultTunnelDescription(
614 - null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL),
615 - optionBuilder.build());
616 -
617 - try {
618 - Device device = deviceService.getDevice(node.ovsdbId());
619 - if (device.is(TunnelConfig.class)) {
620 - TunnelConfig tunnelConfig = device.as(TunnelConfig.class);
621 - tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description);
622 - } else {
623 - log.warn("The tunneling behaviour is not supported in device {}", device.id());
624 - }
625 - } catch (ItemNotFoundException e) {
626 - log.warn("Failed to create tunnel interface on {}", node.hostname());
627 - }
628 - }
629 -
630 - /**
631 - * Adds data plane interface to a given node.
632 - *
633 - * @param node cordvtn node
634 - */
635 - private void addDataPlaneInterface(CordVtnNode node) {
636 - if (isDataPlaneIntfAdded(node)) {
637 - return;
638 - }
639 -
640 - Session session = connect(node.sshInfo());
641 - if (session == null) {
642 - log.debug("Failed to SSH to {}", node.hostname());
643 - return;
644 - }
645 -
646 - if (!isInterfaceUp(session, node.dpIntf())) {
647 - log.warn("Interface {} is not available", node.dpIntf());
648 - return;
649 - }
650 - disconnect(session);
651 -
652 - try {
653 - Device device = deviceService.getDevice(node.ovsdbId());
654 - if (device.is(BridgeConfig.class)) {
655 - BridgeConfig bridgeConfig = device.as(BridgeConfig.class);
656 - bridgeConfig.addPort(BridgeName.bridgeName(DEFAULT_BRIDGE), node.dpIntf());
657 - } else {
658 - log.warn("The bridging behaviour is not supported in device {}", device.id());
659 - }
660 - } catch (ItemNotFoundException e) {
661 - log.warn("Failed to add {} on {}", node.dpIntf(), node.hostname());
662 - }
663 - }
664 -
665 - /**
666 - * Flushes IP address from data plane interface and adds data plane IP address
667 - * to integration bridge.
668 - *
669 - * @param node cordvtn node
670 - */
671 - private void setIpAddress(CordVtnNode node) {
672 - Session session = connect(node.sshInfo());
673 - if (session == null) {
674 - log.debug("Failed to SSH to {}", node.hostname());
675 - return;
676 - }
677 -
678 - getCurrentIps(session, DEFAULT_BRIDGE).stream()
679 - .filter(ip -> !ip.equals(node.localMgmtIp().ip()))
680 - .filter(ip -> !ip.equals(node.dpIp().ip()))
681 - .forEach(ip -> deleteIp(session, ip, DEFAULT_BRIDGE));
682 -
683 - boolean result = flushIp(session, node.dpIntf()) &&
684 - setInterfaceUp(session, node.dpIntf()) &&
685 - addIp(session, node.dpIp(), DEFAULT_BRIDGE) &&
686 - addIp(session, node.localMgmtIp(), DEFAULT_BRIDGE) &&
687 - setInterfaceUp(session, DEFAULT_BRIDGE);
688 -
689 - disconnect(session);
690 -
691 - if (result) {
692 - setNodeState(node, NodeState.COMPLETE);
693 - }
694 - }
695 -
696 - /**
697 - * Checks if integration bridge exists and available.
698 - *
699 - * @param node cordvtn node
700 - * @return true if the bridge is available, false otherwise
701 - */
702 - private boolean isBrIntCreated(CordVtnNode node) {
703 - return (deviceService.getDevice(node.intBrId()) != null
704 - && deviceService.isAvailable(node.intBrId()));
705 - }
706 -
707 - /**
708 - * Checks if tunnel interface exists.
709 - *
710 - * @param node cordvtn node
711 - * @return true if the interface exists, false otherwise
712 - */
713 - private boolean isTunnelIntfCreated(CordVtnNode node) {
714 - return deviceService.getPorts(node.intBrId())
715 - .stream()
716 - .filter(p -> portName(p).contains(DEFAULT_TUNNEL) &&
717 - p.isEnabled())
718 - .findAny().isPresent();
719 - }
720 -
721 - /**
722 - * Checks if data plane interface exists.
723 - *
724 - * @param node cordvtn node
725 - * @return true if the interface exists, false otherwise
726 - */
727 - private boolean isDataPlaneIntfAdded(CordVtnNode node) {
728 - return deviceService.getPorts(node.intBrId())
729 - .stream()
730 - .filter(p -> portName(p).contains(node.dpIntf()) &&
731 - p.isEnabled())
732 - .findAny().isPresent();
733 - }
734 -
735 - /**
736 - * Checks if the IP addresses are correctly set.
737 - *
738 - * @param node cordvtn node
739 - * @return true if the IP is set, false otherwise
740 - */
741 - private boolean isIpAddressSet(CordVtnNode node) {
742 - Session session = connect(node.sshInfo());
743 - if (session == null) {
744 - log.debug("Failed to SSH to {}", node.hostname());
745 - return false;
746 - }
747 -
748 - Set<IpAddress> intBrIps = getCurrentIps(session, DEFAULT_BRIDGE);
749 - boolean result = getCurrentIps(session, node.dpIntf()).isEmpty() &&
750 - isInterfaceUp(session, node.dpIntf()) &&
751 - intBrIps.contains(node.dpIp().ip()) &&
752 - intBrIps.contains(node.localMgmtIp().ip()) &&
753 - isInterfaceUp(session, DEFAULT_BRIDGE);
754 -
755 - disconnect(session);
756 - return result;
757 - }
758 -
759 - /**
760 - * Returns connect point of a given port.
761 - *
762 - * @param port port
763 - * @return connect point
764 - */
765 - private ConnectPoint connectPoint(Port port) {
766 - return new ConnectPoint(port.element().id(), port.number());
767 - }
768 -
769 - /**
770 - * Returns connect point of a given host.
771 - *
772 - * @param host host
773 - * @return connect point
774 - */
775 - private ConnectPoint connectPoint(Host host) {
776 - return new ConnectPoint(host.location().deviceId(), host.location().port());
777 - }
778 -
779 - /**
780 - * Returns cordvtn node associated with a given OVSDB device.
781 - *
782 - * @param ovsdbId OVSDB device id
783 - * @return cordvtn node, null if it fails to find the node
784 - */
785 - private CordVtnNode nodeByOvsdbId(DeviceId ovsdbId) {
786 - return getNodes().stream()
787 - .filter(node -> node.ovsdbId().equals(ovsdbId))
788 - .findFirst().orElse(null);
789 - }
790 -
791 - /**
792 - * Returns cordvtn node associated with a given integration bridge.
793 - *
794 - * @param bridgeId device id of integration bridge
795 - * @return cordvtn node, null if it fails to find the node
796 - */
797 - private CordVtnNode nodeByBridgeId(DeviceId bridgeId) {
798 - return getNodes().stream()
799 - .filter(node -> node.intBrId().equals(bridgeId))
800 - .findFirst().orElse(null);
801 - }
802 -
803 - /**
804 - * Returns port name.
805 - *
806 - * @param port port
807 - * @return port name
808 - */
809 - private String portName(Port port) {
810 - return port.annotations().value("portName");
811 - }
812 -
813 - private class OvsdbHandler implements ConnectionHandler<Device> {
814 -
815 - @Override
816 - public void connected(Device device) {
817 - CordVtnNode node = nodeByOvsdbId(device.id());
818 - if (node != null) {
819 - setNodeState(node, getNodeState(node));
820 - } else {
821 - log.debug("{} is detected on unregistered node, ignore it.", device.id());
822 - }
823 - }
824 -
825 - @Override
826 - public void disconnected(Device device) {
827 - if (!deviceService.isAvailable(device.id())) {
828 - log.debug("Device {} is disconnected", device.id());
829 - adminService.removeDevice(device.id());
830 - }
831 - }
832 - }
833 -
834 - private class BridgeHandler implements ConnectionHandler<Device> {
835 -
836 - @Override
837 - public void connected(Device device) {
838 - CordVtnNode node = nodeByBridgeId(device.id());
839 - if (node != null) {
840 - setNodeState(node, getNodeState(node));
841 - } else {
842 - log.debug("{} is detected on unregistered node, ignore it.", device.id());
843 - }
844 - }
845 -
846 - @Override
847 - public void disconnected(Device device) {
848 - CordVtnNode node = nodeByBridgeId(device.id());
849 - if (node != null) {
850 - log.debug("Integration Bridge is disconnected from {}", node.hostname());
851 - setNodeState(node, NodeState.INCOMPLETE);
852 - }
853 - }
854 -
855 - /**
856 - * Handles port added situation.
857 - * If the added port is tunnel or data plane interface, proceed to the remaining
858 - * node initialization. Otherwise, do nothing.
859 - *
860 - * @param port port
861 - */
862 - public void portAdded(Port port) {
863 - CordVtnNode node = nodeByBridgeId((DeviceId) port.element().id());
864 - String portName = portName(port);
865 -
866 - if (node == null) {
867 - log.debug("{} is added to unregistered node, ignore it.", portName);
868 - return;
869 - }
870 -
871 - log.info("Port {} is added to {}", portName, node.hostname());
872 -
873 - if (portName.startsWith(VPORT_PREFIX)) {
874 - if (isNodeStateComplete(node)) {
875 - instanceManager.addInstance(connectPoint(port));
876 - } else {
877 - log.debug("VM is detected on incomplete node, ignore it.", portName);
878 - }
879 - } else if (portName.contains(DEFAULT_TUNNEL) || portName.equals(node.dpIntf())) {
880 - setNodeState(node, getNodeState(node));
881 - }
882 - }
883 -
884 - /**
885 - * Handles port removed situation.
886 - * If the removed port is tunnel or data plane interface, proceed to the remaining
887 - * node initialization.Others, do nothing.
888 - *
889 - * @param port port
890 - */
891 - public void portRemoved(Port port) {
892 - CordVtnNode node = nodeByBridgeId((DeviceId) port.element().id());
893 - String portName = portName(port);
894 -
895 - if (node == null) {
896 - return;
897 - }
898 -
899 - log.info("Port {} is removed from {}", portName, node.hostname());
900 -
901 - if (portName.startsWith(VPORT_PREFIX)) {
902 - if (isNodeStateComplete(node)) {
903 - instanceManager.removeInstance(connectPoint(port));
904 - } else {
905 - log.debug("VM is vanished from incomplete node, ignore it.", portName);
906 - }
907 - } else if (portName.contains(DEFAULT_TUNNEL) || portName.equals(node.dpIntf())) {
908 - setNodeState(node, NodeState.INCOMPLETE);
909 - }
910 - }
911 - }
912 -
913 - private class InternalDeviceListener implements DeviceListener {
914 -
915 - @Override
916 - public void event(DeviceEvent event) {
917 -
918 - NodeId leaderNodeId = leadershipService.getLeader(appId.name());
919 - if (!Objects.equals(localNodeId, leaderNodeId)) {
920 - // do not allow to proceed without leadership
921 - return;
922 - }
923 -
924 - Device device = event.subject();
925 - ConnectionHandler<Device> handler =
926 - (device.type().equals(SWITCH) ? bridgeHandler : ovsdbHandler);
927 -
928 - switch (event.type()) {
929 - case PORT_ADDED:
930 - eventExecutor.execute(() -> bridgeHandler.portAdded(event.port()));
931 - break;
932 - case PORT_UPDATED:
933 - if (!event.port().isEnabled()) {
934 - eventExecutor.execute(() -> bridgeHandler.portRemoved(event.port()));
935 - }
936 - break;
937 - case DEVICE_ADDED:
938 - case DEVICE_AVAILABILITY_CHANGED:
939 - if (deviceService.isAvailable(device.id())) {
940 - eventExecutor.execute(() -> handler.connected(device));
941 - } else {
942 - eventExecutor.execute(() -> handler.disconnected(device));
943 - }
944 - break;
945 - default:
946 - break;
947 - }
948 - }
949 - }
950 -
951 - /**
952 - * Reads cordvtn nodes from config file.
953 - */
954 - private void readConfiguration() {
955 - CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
956 - if (config == null) {
957 - log.debug("No configuration found");
958 - return;
959 - }
960 - config.cordVtnNodes().forEach(this::addOrUpdateNode);
961 - }
962 -
963 - private class InternalConfigListener implements NetworkConfigListener {
964 -
965 - @Override
966 - public void event(NetworkConfigEvent event) {
967 - NodeId leaderNodeId = leadershipService.getLeader(appId.name());
968 - if (!Objects.equals(localNodeId, leaderNodeId)) {
969 - // do not allow to proceed without leadership
970 - return;
971 - }
972 -
973 - if (!event.configClass().equals(CordVtnConfig.class)) {
974 - return;
975 - }
976 -
977 - switch (event.type()) {
978 - case CONFIG_ADDED:
979 - case CONFIG_UPDATED:
980 - eventExecutor.execute(CordVtnNodeManager.this::readConfiguration);
981 - break;
982 - default:
983 - break;
984 - }
985 - }
986 - }
987 -
988 - private class InternalMapListener implements MapEventListener<String, CordVtnNode> {
989 -
990 - @Override
991 - public void event(MapEvent<String, CordVtnNode> event) {
992 - NodeId leaderNodeId = leadershipService.getLeader(appId.name());
993 - if (!Objects.equals(localNodeId, leaderNodeId)) {
994 - // do not allow to proceed without leadership
995 - return;
996 - }
997 -
998 - CordVtnNode oldNode;
999 - CordVtnNode newNode;
1000 -
1001 - switch (event.type()) {
1002 - case UPDATE:
1003 - oldNode = event.oldValue().value();
1004 - newNode = event.newValue().value();
1005 -
1006 - log.info("Reloaded {}", newNode.hostname());
1007 - if (!newNode.equals(oldNode)) {
1008 - log.debug("New node: {}", newNode);
1009 - }
1010 - // performs init procedure even if the node is not changed
1011 - // for robustness since it's no harm to run init procedure
1012 - // multiple times
1013 - eventExecutor.execute(() -> initNode(newNode));
1014 - break;
1015 - case INSERT:
1016 - newNode = event.newValue().value();
1017 - log.info("Added {}", newNode.hostname());
1018 - eventExecutor.execute(() -> initNode(newNode));
1019 - break;
1020 - case REMOVE:
1021 - oldNode = event.oldValue().value();
1022 - log.info("Removed {}", oldNode.hostname());
1023 - break;
1024 - default:
1025 - break;
1026 - }
1027 - }
1028 - }
1029 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl;
17 -
18 -import org.apache.felix.scr.annotations.Activate;
19 -import org.apache.felix.scr.annotations.Component;
20 -import org.apache.felix.scr.annotations.Deactivate;
21 -import org.apache.felix.scr.annotations.Reference;
22 -import org.apache.felix.scr.annotations.ReferenceCardinality;
23 -import org.apache.felix.scr.annotations.Service;
24 -import org.onlab.packet.Ethernet;
25 -import org.onlab.packet.IPv4;
26 -import org.onlab.packet.Ip4Address;
27 -import org.onlab.packet.IpAddress;
28 -import org.onlab.packet.TpPort;
29 -import org.onlab.packet.VlanId;
30 -import org.onlab.util.ItemNotFoundException;
31 -import org.onosproject.cordvtn.api.CordVtnNode;
32 -import org.onosproject.cordvtn.api.CordVtnService;
33 -import org.onosproject.core.ApplicationId;
34 -import org.onosproject.core.CoreService;
35 -import org.onosproject.net.Device;
36 -import org.onosproject.net.DeviceId;
37 -import org.onosproject.net.PortNumber;
38 -import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
39 -import org.onosproject.net.device.DeviceService;
40 -import org.onosproject.net.flow.DefaultFlowRule;
41 -import org.onosproject.net.flow.DefaultTrafficSelector;
42 -import org.onosproject.net.flow.DefaultTrafficTreatment;
43 -import org.onosproject.net.flow.FlowRule;
44 -import org.onosproject.net.flow.FlowRuleOperations;
45 -import org.onosproject.net.flow.FlowRuleOperationsContext;
46 -import org.onosproject.net.flow.FlowRuleService;
47 -import org.onosproject.net.flow.TrafficSelector;
48 -import org.onosproject.net.flow.TrafficTreatment;
49 -import org.onosproject.net.flow.instructions.ExtensionPropertyException;
50 -import org.onosproject.net.flow.instructions.ExtensionTreatment;
51 -import org.slf4j.Logger;
52 -
53 -import static com.google.common.base.Preconditions.checkNotNull;
54 -import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
55 -import static org.slf4j.LoggerFactory.getLogger;
56 -
57 -/**
58 - * Provides CORD VTN pipeline.
59 - */
60 -@Component(immediate = true)
61 -@Service(value = CordVtnPipeline.class)
62 -public final class CordVtnPipeline {
63 -
64 - protected final Logger log = getLogger(getClass());
65 -
66 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 - protected CoreService coreService;
68 -
69 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 - protected FlowRuleService flowRuleService;
71 -
72 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 - protected DeviceService deviceService;
74 -
75 - // tables
76 - public static final int TABLE_ZERO = 0;
77 - public static final int TABLE_IN_PORT = 1;
78 - public static final int TABLE_ACCESS_TYPE = 2;
79 - public static final int TABLE_IN_SERVICE = 3;
80 - public static final int TABLE_DST_IP = 4;
81 - public static final int TABLE_TUNNEL_IN = 5;
82 - public static final int TABLE_VLAN = 6;
83 -
84 - // priorities
85 - public static final int PRIORITY_MANAGEMENT = 55000;
86 - public static final int PRIORITY_HIGH = 50000;
87 - public static final int PRIORITY_DEFAULT = 5000;
88 - public static final int PRIORITY_LOW = 4000;
89 - public static final int PRIORITY_ZERO = 0;
90 -
91 - public static final int VXLAN_UDP_PORT = 4789;
92 - public static final VlanId VLAN_WAN = VlanId.vlanId((short) 500);
93 - public static final String DEFAULT_TUNNEL = "vxlan";
94 - private static final String PORT_NAME = "portName";
95 -
96 - private ApplicationId appId;
97 -
98 - @Activate
99 - protected void activate() {
100 - appId = coreService.registerApplication(CordVtnService.CORDVTN_APP_ID);
101 - log.info("Started");
102 - }
103 -
104 - @Deactivate
105 - protected void deactivate() {
106 - log.info("Stopped");
107 - }
108 -
109 - /**
110 - * Flush flows installed by this application.
111 - */
112 - public void flushRules() {
113 - flowRuleService.getFlowRulesById(appId).forEach(flowRule -> processFlowRule(false, flowRule));
114 - }
115 -
116 - /**
117 - * Installs table miss rule to a give device.
118 - *
119 - * @param node cordvtn node
120 - * @param dpPort data plane port number
121 - * @param tunnelPort tunnel port number
122 - */
123 - public void initPipeline(CordVtnNode node, PortNumber dpPort, PortNumber tunnelPort) {
124 - checkNotNull(node);
125 -
126 - processTableZero(node.intBrId(), dpPort, node.dpIp().ip());
127 - processInPortTable(node.intBrId(), tunnelPort, dpPort);
128 - processAccessTypeTable(node.intBrId(), dpPort);
129 - processVlanTable(node.intBrId(), dpPort);
130 - }
131 -
132 - private void processTableZero(DeviceId deviceId, PortNumber dpPort, IpAddress dpIp) {
133 - // take vxlan packet out onto the physical port
134 - TrafficSelector selector = DefaultTrafficSelector.builder()
135 - .matchInPort(PortNumber.LOCAL)
136 - .build();
137 -
138 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
139 - .setOutput(dpPort)
140 - .build();
141 -
142 - FlowRule flowRule = DefaultFlowRule.builder()
143 - .fromApp(appId)
144 - .withSelector(selector)
145 - .withTreatment(treatment)
146 - .withPriority(PRIORITY_HIGH)
147 - .forDevice(deviceId)
148 - .forTable(TABLE_ZERO)
149 - .makePermanent()
150 - .build();
151 -
152 - processFlowRule(true, flowRule);
153 -
154 - // take a vxlan encap'd packet through the Linux stack
155 - selector = DefaultTrafficSelector.builder()
156 - .matchInPort(dpPort)
157 - .matchEthType(Ethernet.TYPE_IPV4)
158 - .matchIPProtocol(IPv4.PROTOCOL_UDP)
159 - .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
160 - .build();
161 -
162 - treatment = DefaultTrafficTreatment.builder()
163 - .setOutput(PortNumber.LOCAL)
164 - .build();
165 -
166 - flowRule = DefaultFlowRule.builder()
167 - .fromApp(appId)
168 - .withSelector(selector)
169 - .withTreatment(treatment)
170 - .withPriority(PRIORITY_HIGH)
171 - .forDevice(deviceId)
172 - .forTable(TABLE_ZERO)
173 - .makePermanent()
174 - .build();
175 -
176 - processFlowRule(true, flowRule);
177 -
178 - // take a packet to the data plane ip through Linux stack
179 - selector = DefaultTrafficSelector.builder()
180 - .matchInPort(dpPort)
181 - .matchEthType(Ethernet.TYPE_IPV4)
182 - .matchIPDst(dpIp.toIpPrefix())
183 - .build();
184 -
185 - treatment = DefaultTrafficTreatment.builder()
186 - .setOutput(PortNumber.LOCAL)
187 - .build();
188 -
189 - flowRule = DefaultFlowRule.builder()
190 - .fromApp(appId)
191 - .withSelector(selector)
192 - .withTreatment(treatment)
193 - .withPriority(PRIORITY_HIGH)
194 - .forDevice(deviceId)
195 - .forTable(TABLE_ZERO)
196 - .makePermanent()
197 - .build();
198 -
199 - processFlowRule(true, flowRule);
200 -
201 - // take an arp packet from physical through Linux stack
202 - selector = DefaultTrafficSelector.builder()
203 - .matchInPort(dpPort)
204 - .matchEthType(Ethernet.TYPE_ARP)
205 - .matchArpTpa(dpIp.getIp4Address())
206 - .build();
207 -
208 - treatment = DefaultTrafficTreatment.builder()
209 - .setOutput(PortNumber.LOCAL)
210 - .build();
211 -
212 - flowRule = DefaultFlowRule.builder()
213 - .fromApp(appId)
214 - .withSelector(selector)
215 - .withTreatment(treatment)
216 - .withPriority(PRIORITY_HIGH)
217 - .forDevice(deviceId)
218 - .forTable(TABLE_ZERO)
219 - .makePermanent()
220 - .build();
221 -
222 - processFlowRule(true, flowRule);
223 -
224 - // take all else to the next table
225 - selector = DefaultTrafficSelector.builder()
226 - .build();
227 -
228 - treatment = DefaultTrafficTreatment.builder()
229 - .transition(TABLE_IN_PORT)
230 - .build();
231 -
232 - flowRule = DefaultFlowRule.builder()
233 - .fromApp(appId)
234 - .withSelector(selector)
235 - .withTreatment(treatment)
236 - .withPriority(PRIORITY_ZERO)
237 - .forDevice(deviceId)
238 - .forTable(TABLE_ZERO)
239 - .makePermanent()
240 - .build();
241 -
242 - processFlowRule(true, flowRule);
243 -
244 - // take all vlan tagged packet to the VLAN table
245 - selector = DefaultTrafficSelector.builder()
246 - .matchVlanId(VlanId.ANY)
247 - .build();
248 -
249 - treatment = DefaultTrafficTreatment.builder()
250 - .transition(TABLE_VLAN)
251 - .build();
252 -
253 - flowRule = DefaultFlowRule.builder()
254 - .fromApp(appId)
255 - .withSelector(selector)
256 - .withTreatment(treatment)
257 - .withPriority(PRIORITY_MANAGEMENT)
258 - .forDevice(deviceId)
259 - .forTable(TABLE_ZERO)
260 - .makePermanent()
261 - .build();
262 -
263 - processFlowRule(true, flowRule);
264 - }
265 -
266 - private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dpPort) {
267 - checkNotNull(tunnelPort);
268 -
269 - TrafficSelector selector = DefaultTrafficSelector.builder()
270 - .matchInPort(tunnelPort)
271 - .build();
272 -
273 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
274 - .transition(TABLE_TUNNEL_IN)
275 - .build();
276 -
277 - FlowRule flowRule = DefaultFlowRule.builder()
278 - .fromApp(appId)
279 - .withSelector(selector)
280 - .withTreatment(treatment)
281 - .withPriority(PRIORITY_DEFAULT)
282 - .forDevice(deviceId)
283 - .forTable(TABLE_IN_PORT)
284 - .makePermanent()
285 - .build();
286 -
287 - processFlowRule(true, flowRule);
288 -
289 - selector = DefaultTrafficSelector.builder()
290 - .matchInPort(dpPort)
291 - .build();
292 -
293 - treatment = DefaultTrafficTreatment.builder()
294 - .transition(TABLE_DST_IP)
295 - .build();
296 -
297 - flowRule = DefaultFlowRule.builder()
298 - .fromApp(appId)
299 - .withSelector(selector)
300 - .withTreatment(treatment)
301 - .withPriority(PRIORITY_DEFAULT)
302 - .forDevice(deviceId)
303 - .forTable(TABLE_IN_PORT)
304 - .makePermanent()
305 - .build();
306 -
307 - processFlowRule(true, flowRule);
308 - }
309 -
310 - private void processAccessTypeTable(DeviceId deviceId, PortNumber dpPort) {
311 - TrafficSelector selector = DefaultTrafficSelector.builder()
312 - .build();
313 -
314 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
315 - .setOutput(dpPort)
316 - .build();
317 -
318 - FlowRule flowRule = DefaultFlowRule.builder()
319 - .fromApp(appId)
320 - .withSelector(selector)
321 - .withTreatment(treatment)
322 - .withPriority(PRIORITY_ZERO)
323 - .forDevice(deviceId)
324 - .forTable(TABLE_ACCESS_TYPE)
325 - .makePermanent()
326 - .build();
327 -
328 - processFlowRule(true, flowRule);
329 - }
330 -
331 - private void processVlanTable(DeviceId deviceId, PortNumber dpPort) {
332 - // for traffic going out to WAN, strip vid 500 and take through data plane interface
333 - TrafficSelector selector = DefaultTrafficSelector.builder()
334 - .matchVlanId(VLAN_WAN)
335 - .build();
336 -
337 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
338 - .popVlan()
339 - .setOutput(dpPort)
340 - .build();
341 -
342 - FlowRule flowRule = DefaultFlowRule.builder()
343 - .fromApp(appId)
344 - .withSelector(selector)
345 - .withTreatment(treatment)
346 - .withPriority(PRIORITY_DEFAULT)
347 - .forDevice(deviceId)
348 - .forTable(TABLE_VLAN)
349 - .makePermanent()
350 - .build();
351 -
352 - processFlowRule(true, flowRule);
353 -
354 - selector = DefaultTrafficSelector.builder()
355 - .matchVlanId(VLAN_WAN)
356 - .matchEthType(Ethernet.TYPE_ARP)
357 - .build();
358 -
359 - treatment = DefaultTrafficTreatment.builder()
360 - .setOutput(PortNumber.CONTROLLER)
361 - .build();
362 -
363 - flowRule = DefaultFlowRule.builder()
364 - .fromApp(appId)
365 - .withSelector(selector)
366 - .withTreatment(treatment)
367 - .withPriority(PRIORITY_HIGH)
368 - .forDevice(deviceId)
369 - .forTable(TABLE_VLAN)
370 - .makePermanent()
371 - .build();
372 -
373 - processFlowRule(true, flowRule);
374 - }
375 -
376 - public void processFlowRule(boolean install, FlowRule rule) {
377 - FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
378 - oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
379 -
380 - flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
381 - @Override
382 - public void onError(FlowRuleOperations ops) {
383 - log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
384 - }
385 - }));
386 - }
387 -
388 - public ExtensionTreatment tunnelDstTreatment(DeviceId deviceId, Ip4Address remoteIp) {
389 - try {
390 - Device device = deviceService.getDevice(deviceId);
391 -
392 - if (device.is(ExtensionTreatmentResolver.class)) {
393 - ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
394 - ExtensionTreatment treatment =
395 - resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
396 - treatment.setPropertyValue("tunnelDst", remoteIp);
397 - return treatment;
398 - } else {
399 - log.warn("The extension treatment resolving behaviour is not supported in device {}",
400 - device.id().toString());
401 - return null;
402 - }
403 - } catch (ItemNotFoundException | UnsupportedOperationException |
404 - ExtensionPropertyException e) {
405 - log.error("Failed to get extension instruction {}", deviceId);
406 - return null;
407 - }
408 - }
409 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl;
17 -
18 -import com.google.common.collect.Sets;
19 -import com.google.common.io.CharStreams;
20 -import com.jcraft.jsch.Channel;
21 -import com.jcraft.jsch.ChannelExec;
22 -import com.jcraft.jsch.JSch;
23 -import com.jcraft.jsch.JSchException;
24 -import com.jcraft.jsch.Session;
25 -import org.onlab.packet.IpAddress;
26 -import org.onosproject.cordvtn.api.NetworkAddress;
27 -import org.onosproject.cordvtn.api.SshAccessInfo;
28 -import org.slf4j.Logger;
29 -
30 -import java.io.IOException;
31 -import java.io.InputStream;
32 -import java.io.InputStreamReader;
33 -import java.util.Set;
34 -import java.util.regex.Pattern;
35 -import java.util.stream.Collectors;
36 -
37 -import static org.slf4j.LoggerFactory.getLogger;
38 -
39 -/**
40 - * {@code RemoteIpCommandUtil} provides methods to help execute Linux IP commands to a remote server.
41 - * It opens individual exec channels for each command. User can create a session with {@code connect}
42 - * method and then execute a series commands. After done with all commands, the session must be closed
43 - * explicitly by calling {@code disconnect}.
44 - */
45 -public final class RemoteIpCommandUtil {
46 -
47 - protected static final Logger log = getLogger(RemoteIpCommandUtil.class);
48 -
49 - private static final String STRICT_HOST_CHECKING = "StrictHostKeyChecking";
50 - private static final String DEFAULT_STRICT_HOST_CHECKING = "no";
51 - private static final int DEFAULT_SESSION_TIMEOUT = 60000; // milliseconds
52 -
53 - private static final String IP_PATTERN = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
54 - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
55 - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
56 - "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
57 -
58 - private static final String IP_ADDR_SHOW = "sudo ip addr show %s";
59 - private static final String IP_ADDR_FLUSH = "sudo ip addr flush %s";
60 - private static final String IP_ADDR_ADD = "sudo ip addr add %s dev %s";
61 - private static final String IP_ADDR_DELETE = "sudo ip addr delete %s dev %s";
62 - private static final String IP_LINK_SHOW = "sudo ip link show %s";
63 - private static final String IP_LINK_UP = "sudo ip link set %s up";
64 -
65 - /**
66 - * Default constructor.
67 - */
68 - private RemoteIpCommandUtil() {
69 - }
70 -
71 - /**
72 - * Adds a given IP address to a given device.
73 - *
74 - * @param session ssh connection
75 - * @param ip network address
76 - * @param device device name to assign the ip address
77 - * @return true if the command succeeds, or false
78 - */
79 - public static boolean addIp(Session session, NetworkAddress ip, String device) {
80 - if (session == null || !session.isConnected()) {
81 - return false;
82 - }
83 -
84 - executeCommand(session, String.format(IP_ADDR_ADD, ip.cidr(), device));
85 - Set<IpAddress> result = getCurrentIps(session, device);
86 - return result.contains(ip.ip());
87 - }
88 -
89 - /**
90 - * Removes the IP address from a given device.
91 - *
92 - * @param session ssh connection
93 - * @param ip ip address
94 - * @param device device name
95 - * @return true if the command succeeds, or false
96 - */
97 - public static boolean deleteIp(Session session, IpAddress ip, String device) {
98 - if (session == null || !session.isConnected()) {
99 - return false;
100 - }
101 -
102 - executeCommand(session, String.format(IP_ADDR_DELETE, ip, device));
103 - Set<IpAddress> result = getCurrentIps(session, device);
104 - return !result.contains(ip);
105 - }
106 -
107 - /**
108 - * Removes all IP address on a given device.
109 - *
110 - * @param session ssh connection
111 - * @param device device name
112 - * @return true if the command succeeds, or false
113 - */
114 - public static boolean flushIp(Session session, String device) {
115 - if (session == null || !session.isConnected()) {
116 - return false;
117 - }
118 -
119 - executeCommand(session, String.format(IP_ADDR_FLUSH, device));
120 - return getCurrentIps(session, device).isEmpty();
121 - }
122 -
123 - /**
124 - * Returns a set of IP address that a given device has.
125 - *
126 - * @param session ssh connection
127 - * @param device device name
128 - * @return set of IP prefix or empty set
129 - */
130 - public static Set<IpAddress> getCurrentIps(Session session, String device) {
131 - if (session == null || !session.isConnected()) {
132 - return Sets.newHashSet();
133 - }
134 -
135 - String output = executeCommand(session, String.format(IP_ADDR_SHOW, device));
136 - Set<IpAddress> result = Pattern.compile(" |/")
137 - .splitAsStream(output)
138 - .filter(s -> s.matches(IP_PATTERN))
139 - .map(IpAddress::valueOf)
140 - .collect(Collectors.toSet());
141 -
142 - return result;
143 - }
144 -
145 - /**
146 - * Sets link state up for a given device.
147 - *
148 - * @param session ssh connection
149 - * @param device device name
150 - * @return true if the command succeeds, or false
151 - */
152 - public static boolean setInterfaceUp(Session session, String device) {
153 - if (session == null || !session.isConnected()) {
154 - return false;
155 - }
156 -
157 - executeCommand(session, String.format(IP_LINK_UP, device));
158 - return isInterfaceUp(session, device);
159 - }
160 -
161 - /**
162 - * Checks if a given interface is up or not.
163 - *
164 - * @param session ssh connection
165 - * @param device device name
166 - * @return true if the interface is up, or false
167 - */
168 - public static boolean isInterfaceUp(Session session, String device) {
169 - if (session == null || !session.isConnected()) {
170 - return false;
171 - }
172 -
173 - String output = executeCommand(session, String.format(IP_LINK_SHOW, device));
174 - return output != null && output.contains("UP");
175 - }
176 -
177 - /**
178 - * Creates a new session with a given access information.
179 - *
180 - * @param sshInfo information to ssh to the remove server
181 - * @return ssh session, or null
182 - */
183 - public static Session connect(SshAccessInfo sshInfo) {
184 - try {
185 - JSch jsch = new JSch();
186 - jsch.addIdentity(sshInfo.privateKey());
187 -
188 - Session session = jsch.getSession(sshInfo.user(),
189 - sshInfo.remoteIp().toString(),
190 - sshInfo.port().toInt());
191 - session.setConfig(STRICT_HOST_CHECKING, DEFAULT_STRICT_HOST_CHECKING);
192 - session.connect(DEFAULT_SESSION_TIMEOUT);
193 -
194 - return session;
195 - } catch (JSchException e) {
196 - log.debug("Failed to connect to {} due to {}", sshInfo.toString(), e.toString());
197 - return null;
198 - }
199 - }
200 -
201 - /**
202 - * Closes a connection.
203 - *
204 - * @param session session
205 - */
206 - public static void disconnect(Session session) {
207 - if (session.isConnected()) {
208 - session.disconnect();
209 - }
210 - }
211 -
212 - /**
213 - * Executes a given command. It opens exec channel for the command and closes
214 - * the channel when it's done.
215 - *
216 - * @param session ssh connection to a remote server
217 - * @param command command to execute
218 - * @return command output string if the command succeeds, or null
219 - */
220 - private static String executeCommand(Session session, String command) {
221 - if (session == null || !session.isConnected()) {
222 - return null;
223 - }
224 -
225 - log.trace("Execute command {} to {}", command, session.getHost());
226 -
227 - try {
228 - Channel channel = session.openChannel("exec");
229 - ((ChannelExec) channel).setCommand(command);
230 - channel.setInputStream(null);
231 - InputStream output = channel.getInputStream();
232 -
233 - channel.connect();
234 - String result = CharStreams.toString(new InputStreamReader(output));
235 - channel.disconnect();
236 -
237 - return result;
238 - } catch (JSchException | IOException e) {
239 - log.debug("Failed to execute command {} due to {}", command, e.toString());
240 - return null;
241 - }
242 - }
243 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * Implementation for CORD VTN application.
19 - */
20 -package org.onosproject.cordvtn.impl;
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl.service;
17 -
18 -import org.apache.felix.scr.annotations.Activate;
19 -import org.apache.felix.scr.annotations.Component;
20 -
21 -import org.apache.felix.scr.annotations.Deactivate;
22 -import org.onosproject.cordvtn.api.Instance;
23 -import org.onosproject.cordvtn.api.InstanceHandler;
24 -import org.onosproject.cordvtn.impl.CordVtnInstanceHandler;
25 -import org.onosproject.xosclient.api.VtnService;
26 -
27 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
28 -import static org.onlab.util.Tools.groupedThreads;
29 -
30 -/**
31 - * Provides network connectivity for dummy service instances.
32 - */
33 -@Component(immediate = true)
34 -public class DummyInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
35 -
36 - @Activate
37 - protected void activate() {
38 - serviceType = VtnService.ServiceType.DUMMY;
39 - eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-dummy", "event-handler"));
40 - super.activate();
41 - }
42 -
43 - @Deactivate
44 - protected void deactivate() {
45 - super.deactivate();
46 - }
47 -
48 - @Override
49 - public void instanceDetected(Instance instance) {
50 - super.instanceDetected(instance);
51 - }
52 -
53 - @Override
54 - public void instanceRemoved(Instance instance) {
55 - super.instanceRemoved(instance);
56 - }
57 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl.service;
17 -
18 -import com.google.common.collect.Maps;
19 -import org.apache.felix.scr.annotations.Activate;
20 -import org.apache.felix.scr.annotations.Component;
21 -import org.apache.felix.scr.annotations.Deactivate;
22 -import org.onlab.packet.Ethernet;
23 -import org.onlab.packet.IpPrefix;
24 -import org.onosproject.cordconfig.access.AccessAgentConfig;
25 -import org.onosproject.cordconfig.access.AccessAgentData;
26 -import org.onosproject.cordvtn.api.CordVtnConfig;
27 -import org.onosproject.cordvtn.api.Instance;
28 -import org.onosproject.cordvtn.api.InstanceHandler;
29 -import org.onosproject.cordvtn.impl.CordVtnInstanceHandler;
30 -import org.onosproject.net.DeviceId;
31 -import org.onosproject.net.PortNumber;
32 -import org.onosproject.net.config.ConfigFactory;
33 -import org.onosproject.net.config.NetworkConfigEvent;
34 -import org.onosproject.net.config.NetworkConfigListener;
35 -import org.onosproject.net.config.basics.SubjectFactories;
36 -import org.onosproject.net.flow.DefaultFlowRule;
37 -import org.onosproject.net.flow.DefaultTrafficSelector;
38 -import org.onosproject.net.flow.DefaultTrafficTreatment;
39 -import org.onosproject.net.flow.FlowRule;
40 -import org.onosproject.net.flow.TrafficSelector;
41 -import org.onosproject.net.flow.TrafficTreatment;
42 -import org.onosproject.xosclient.api.VtnService;
43 -
44 -import java.util.Map;
45 -import java.util.Set;
46 -
47 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
48 -import static org.onlab.util.Tools.groupedThreads;
49 -import static org.onosproject.cordvtn.impl.CordVtnPipeline.PRIORITY_MANAGEMENT;
50 -import static org.onosproject.cordvtn.impl.CordVtnPipeline.TABLE_ACCESS_TYPE;
51 -
52 -/**
53 - * Provides network connectivity for OLT agent instances.
54 - */
55 -@Component(immediate = true)
56 -public class OltAgentInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
57 -
58 - private static final Class<AccessAgentConfig> CONFIG_CLASS = AccessAgentConfig.class;
59 - private ConfigFactory<DeviceId, AccessAgentConfig> configFactory =
60 - new ConfigFactory<DeviceId, AccessAgentConfig>(
61 - SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessAgent") {
62 - @Override
63 - public AccessAgentConfig createConfig() {
64 - return new AccessAgentConfig();
65 - }
66 - };
67 -
68 - private Map<DeviceId, AccessAgentData> oltAgentData = Maps.newConcurrentMap();
69 - private IpPrefix mgmtIpRange = null;
70 -
71 - @Activate
72 - protected void activate() {
73 - eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-olt", "event-handler"));
74 - serviceType = VtnService.ServiceType.OLT_AGENT;
75 -
76 - configRegistry.registerConfigFactory(configFactory);
77 - configListener = new InternalConfigListener();
78 -
79 - super.activate();
80 - }
81 -
82 - @Deactivate
83 - protected void deactivate() {
84 - super.deactivate();
85 - }
86 -
87 - @Override
88 - public void instanceDetected(Instance instance) {
89 - log.info("OLT agent instance detected {}", instance);
90 -
91 - managementAccessRule(instance.deviceId(), true);
92 - // TODO implement
93 - }
94 -
95 - @Override
96 - public void instanceRemoved(Instance instance) {
97 - log.info("OLT agent instance removed {}", instance);
98 -
99 - if (getInstances(instance.serviceId()).isEmpty()) {
100 - nodeManager.completeNodes().stream().forEach(node ->
101 - managementAccessRule(node.intBrId(), false));
102 - }
103 -
104 - // TODO implement
105 - }
106 -
107 - private void managementAccessRule(DeviceId deviceId, boolean install) {
108 - // TODO remove this rule after long term management network is done
109 - if (mgmtIpRange != null) {
110 - TrafficSelector selector = DefaultTrafficSelector.builder()
111 - .matchEthType(Ethernet.TYPE_IPV4)
112 - .matchIPDst(mgmtIpRange)
113 - .build();
114 -
115 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
116 - .setOutput(PortNumber.LOCAL)
117 - .build();
118 -
119 - FlowRule flowRule = DefaultFlowRule.builder()
120 - .fromApp(appId)
121 - .withSelector(selector)
122 - .withTreatment(treatment)
123 - .withPriority(PRIORITY_MANAGEMENT)
124 - .forDevice(deviceId)
125 - .forTable(TABLE_ACCESS_TYPE)
126 - .makePermanent()
127 - .build();
128 -
129 - pipeline.processFlowRule(install, flowRule);
130 - }
131 - }
132 -
133 - private void readAccessAgentConfig() {
134 -
135 - Set<DeviceId> deviceSubjects = configRegistry.getSubjects(DeviceId.class, CONFIG_CLASS);
136 - deviceSubjects.stream().forEach(subject -> {
137 - AccessAgentConfig config = configRegistry.getConfig(subject, CONFIG_CLASS);
138 - if (config != null) {
139 - oltAgentData.put(subject, config.getAgent());
140 - }
141 - });
142 - }
143 -
144 - @Override
145 - protected void readConfiguration() {
146 - CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
147 - if (config == null) {
148 - log.debug("No configuration found");
149 - return;
150 - }
151 -
152 - osAccess = config.openstackAccess();
153 - xosAccess = config.xosAccess();
154 - mgmtIpRange = config.managementIpRange();
155 - }
156 -
157 - public class InternalConfigListener implements NetworkConfigListener {
158 -
159 - @Override
160 - public void event(NetworkConfigEvent event) {
161 -
162 - switch (event.type()) {
163 - case CONFIG_UPDATED:
164 - case CONFIG_ADDED:
165 - if (event.configClass().equals(CordVtnConfig.class)) {
166 - readConfiguration();
167 - } else if (event.configClass().equals(CONFIG_CLASS)) {
168 - readAccessAgentConfig();
169 - }
170 - break;
171 - default:
172 - break;
173 - }
174 - }
175 - }
176 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.impl.service;
17 -
18 -import com.google.common.base.Strings;
19 -import com.google.common.collect.Sets;
20 -import org.apache.felix.scr.annotations.Activate;
21 -import org.apache.felix.scr.annotations.Component;
22 -import org.apache.felix.scr.annotations.Deactivate;
23 -import org.apache.felix.scr.annotations.Reference;
24 -import org.apache.felix.scr.annotations.ReferenceCardinality;
25 -import org.apache.felix.scr.annotations.Service;
26 -import org.onlab.packet.Ethernet;
27 -import org.onlab.packet.IpAddress;
28 -import org.onlab.packet.IpPrefix;
29 -import org.onlab.packet.MacAddress;
30 -import org.onlab.packet.VlanId;
31 -import org.onosproject.cordvtn.api.Instance;
32 -import org.onosproject.cordvtn.api.InstanceHandler;
33 -import org.onosproject.cordvtn.impl.CordVtnInstanceHandler;
34 -import org.onosproject.cordvtn.impl.CordVtnInstanceManager;
35 -import org.onosproject.net.DefaultAnnotations;
36 -import org.onosproject.net.HostId;
37 -import org.onosproject.net.PortNumber;
38 -import org.onosproject.net.flow.DefaultFlowRule;
39 -import org.onosproject.net.flow.DefaultTrafficSelector;
40 -import org.onosproject.net.flow.DefaultTrafficTreatment;
41 -import org.onosproject.net.flow.FlowRule;
42 -import org.onosproject.net.flow.FlowRuleService;
43 -import org.onosproject.net.flow.TrafficSelector;
44 -import org.onosproject.net.flow.TrafficTreatment;
45 -import org.onosproject.net.flow.criteria.Criterion;
46 -import org.onosproject.net.flow.criteria.IPCriterion;
47 -import org.onosproject.net.flow.instructions.Instruction;
48 -import org.onosproject.net.flow.instructions.Instructions;
49 -import org.onosproject.net.flow.instructions.L2ModificationInstruction;
50 -import org.onosproject.net.host.DefaultHostDescription;
51 -import org.onosproject.net.host.HostDescription;
52 -import org.onosproject.xosclient.api.VtnPort;
53 -import org.onosproject.xosclient.api.VtnPortApi;
54 -import org.onosproject.xosclient.api.VtnPortId;
55 -import org.onosproject.xosclient.api.VtnService;
56 -
57 -import java.util.Map;
58 -import java.util.Set;
59 -
60 -import static com.google.common.base.Preconditions.checkNotNull;
61 -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
62 -import static org.onlab.util.Tools.groupedThreads;
63 -import static org.onosproject.cordvtn.api.Instance.*;
64 -import static org.onosproject.cordvtn.impl.CordVtnPipeline.*;
65 -import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
66 -import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
67 -
68 -/**
69 - * Provides network connectivity for vSG instances.
70 - */
71 -@Component(immediate = true)
72 -@Service(value = VsgInstanceHandler.class)
73 -public final class VsgInstanceHandler extends CordVtnInstanceHandler implements InstanceHandler {
74 -
75 - private static final String STAG = "stag";
76 - private static final String VSG_VM = "vsgVm";
77 -
78 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 - protected FlowRuleService flowRuleService;
80 -
81 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 - protected CordVtnInstanceManager instanceManager;
83 -
84 - @Activate
85 - protected void activate() {
86 - serviceType = VtnService.ServiceType.VSG;
87 - eventExecutor = newSingleThreadScheduledExecutor(groupedThreads("onos/cordvtn-vsg", "event-handler"));
88 - super.activate();
89 - }
90 -
91 - @Deactivate
92 - protected void deactivate() {
93 - super.deactivate();
94 - }
95 -
96 - @Override
97 - public void instanceDetected(Instance instance) {
98 - if (isVsgContainer(instance)) {
99 - log.info("vSG container detected {}", instance);
100 -
101 - // find vsg vm for this vsg container
102 - String vsgVmId = instance.getAnnotation(VSG_VM);
103 - if (Strings.isNullOrEmpty(vsgVmId)) {
104 - log.warn("Failed to find VSG VM for {}", instance);
105 - return;
106 - }
107 -
108 - Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
109 - VtnPort vtnPort = getVtnPort(vsgVm);
110 - if (vtnPort == null || getStag(vtnPort) == null) {
111 - return;
112 - }
113 -
114 - populateVsgRules(vsgVm, getStag(vtnPort),
115 - nodeManager.dpPort(vsgVm.deviceId()),
116 - vtnPort.addressPairs().keySet(),
117 - true);
118 -
119 - } else {
120 - VtnPort vtnPort = getVtnPort(instance);
121 - if (vtnPort == null || getStag(vtnPort) == null) {
122 - return;
123 - }
124 -
125 - vtnPort.addressPairs().entrySet().stream()
126 - .forEach(pair -> addVsgContainer(
127 - instance,
128 - pair.getKey(),
129 - pair.getValue(),
130 - getStag(vtnPort).toString()
131 - ));
132 - super.instanceDetected(instance);
133 - }
134 - }
135 -
136 - @Override
137 - public void instanceRemoved(Instance instance) {
138 - if (isVsgContainer(instance)) {
139 - log.info("vSG container vanished {}", instance);
140 -
141 - // find vsg vm for this vsg container
142 - String vsgVmId = instance.getAnnotation(VSG_VM);
143 - if (Strings.isNullOrEmpty(vsgVmId)) {
144 - log.warn("Failed to find VSG VM for {}", instance);
145 - return;
146 - }
147 -
148 - Instance vsgVm = Instance.of(hostService.getHost(HostId.hostId(vsgVmId)));
149 - VtnPort vtnPort = getVtnPort(vsgVm);
150 - if (vtnPort == null || getStag(vtnPort) == null) {
151 - return;
152 - }
153 -
154 - populateVsgRules(vsgVm, getStag(vtnPort),
155 - nodeManager.dpPort(vsgVm.deviceId()),
156 - vtnPort.addressPairs().keySet(),
157 - false);
158 -
159 - } else {
160 - // TODO remove vsg vm related rules
161 - super.instanceRemoved(instance);
162 - }
163 - }
164 -
165 - /**
166 - * Updates set of vSGs in a given vSG VM.
167 - *
168 - * @param vsgVmId vsg vm host id
169 - * @param stag stag
170 - * @param vsgInstances full set of vsg wan ip and mac address pairs in this vsg vm
171 - */
172 - public void updateVsgInstances(HostId vsgVmId, String stag, Map<IpAddress, MacAddress> vsgInstances) {
173 - if (hostService.getHost(vsgVmId) == null) {
174 - log.debug("vSG VM {} is not added yet, ignore this update", vsgVmId);
175 - return;
176 - }
177 -
178 - Instance vsgVm = Instance.of(hostService.getHost(vsgVmId));
179 - if (vsgVm == null) {
180 - log.warn("Failed to find existing vSG VM for STAG: {}", stag);
181 - return;
182 - }
183 -
184 - log.info("Updates vSGs in {} with STAG: {}", vsgVm, stag);
185 -
186 - // adds vSGs in the address pair
187 - vsgInstances.entrySet().stream()
188 - .filter(addr -> hostService.getHostsByMac(addr.getValue()).isEmpty())
189 - .forEach(addr -> addVsgContainer(
190 - vsgVm,
191 - addr.getKey(),
192 - addr.getValue(),
193 - stag));
194 -
195 - // removes vSGs not listed in the address pair
196 - hostService.getConnectedHosts(vsgVm.host().location()).stream()
197 - .filter(host -> !host.mac().equals(vsgVm.mac()))
198 - .filter(host -> !vsgInstances.values().contains(host.mac()))
199 - .forEach(host -> {
200 - log.info("Removed vSG {}", host.toString());
201 - instanceManager.removeInstance(host.id());
202 - });
203 - }
204 -
205 - private boolean isVsgContainer(Instance instance) {
206 - return !Strings.isNullOrEmpty(instance.host().annotations().value(STAG));
207 - }
208 -
209 - private void addVsgContainer(Instance vsgVm, IpAddress vsgWanIp, MacAddress vsgMac,
210 - String stag) {
211 - HostId hostId = HostId.hostId(vsgMac);
212 - DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
213 - .set(SERVICE_TYPE, vsgVm.serviceType().toString())
214 - .set(SERVICE_ID, vsgVm.serviceId().id())
215 - .set(PORT_ID, vsgVm.portId().id())
216 - .set(NESTED_INSTANCE, TRUE)
217 - .set(STAG, stag)
218 - .set(VSG_VM, vsgVm.host().id().toString())
219 - .set(CREATE_TIME, String.valueOf(System.currentTimeMillis()));
220 -
221 - HostDescription hostDesc = new DefaultHostDescription(
222 - vsgMac,
223 - VlanId.NONE,
224 - vsgVm.host().location(),
225 - Sets.newHashSet(vsgWanIp),
226 - annotations.build());
227 -
228 - instanceManager.addInstance(hostId, hostDesc);
229 - }
230 -
231 - private void populateVsgRules(Instance vsgVm, VlanId stag, PortNumber dpPort,
232 - Set<IpAddress> vsgWanIps, boolean install) {
233 - // for traffics with s-tag, strip the tag and take through the vSG VM
234 - TrafficSelector selector = DefaultTrafficSelector.builder()
235 - .matchInPort(dpPort)
236 - .matchVlanId(stag)
237 - .build();
238 -
239 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
240 - .setOutput(vsgVm.portNumber())
241 - .build();
242 -
243 - FlowRule flowRule = DefaultFlowRule.builder()
244 - .fromApp(appId)
245 - .withSelector(selector)
246 - .withTreatment(treatment)
247 - .withPriority(PRIORITY_DEFAULT)
248 - .forDevice(vsgVm.deviceId())
249 - .forTable(TABLE_VLAN)
250 - .makePermanent()
251 - .build();
252 -
253 - pipeline.processFlowRule(install, flowRule);
254 -
255 - // for traffics with customer vlan, tag with the service vlan based on input port with
256 - // lower priority to avoid conflict with WAN tag
257 - selector = DefaultTrafficSelector.builder()
258 - .matchInPort(vsgVm.portNumber())
259 - .matchVlanId(stag)
260 - .build();
261 -
262 - treatment = DefaultTrafficTreatment.builder()
263 - .setOutput(dpPort)
264 - .build();
265 -
266 - flowRule = DefaultFlowRule.builder()
267 - .fromApp(appId)
268 - .withSelector(selector)
269 - .withTreatment(treatment)
270 - .withPriority(PRIORITY_DEFAULT)
271 - .forDevice(vsgVm.deviceId())
272 - .forTable(TABLE_VLAN)
273 - .makePermanent()
274 - .build();
275 -
276 - pipeline.processFlowRule(install, flowRule);
277 -
278 - // for traffic coming from WAN, tag 500 and take through the vSG VM
279 - // based on destination ip
280 - vsgWanIps.stream().forEach(ip -> {
281 - TrafficSelector downstream = DefaultTrafficSelector.builder()
282 - .matchEthType(Ethernet.TYPE_IPV4)
283 - .matchIPDst(ip.toIpPrefix())
284 - .build();
285 -
286 - TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
287 - .pushVlan()
288 - .setVlanId(VLAN_WAN)
289 - .setEthDst(vsgVm.mac())
290 - .setOutput(vsgVm.portNumber())
291 - .build();
292 -
293 - FlowRule downstreamFlowRule = DefaultFlowRule.builder()
294 - .fromApp(appId)
295 - .withSelector(downstream)
296 - .withTreatment(downstreamTreatment)
297 - .withPriority(PRIORITY_DEFAULT)
298 - .forDevice(vsgVm.deviceId())
299 - .forTable(TABLE_DST_IP)
300 - .makePermanent()
301 - .build();
302 -
303 - pipeline.processFlowRule(install, downstreamFlowRule);
304 - });
305 -
306 - // remove downstream flow rules for the vSG not shown in vsgWanIps
307 - for (FlowRule rule : flowRuleService.getFlowRulesById(appId)) {
308 - if (!rule.deviceId().equals(vsgVm.deviceId())) {
309 - continue;
310 - }
311 - PortNumber output = getOutputFromTreatment(rule);
312 - if (output == null || !output.equals(vsgVm.portNumber()) ||
313 - !isVlanPushFromTreatment(rule)) {
314 - continue;
315 - }
316 -
317 - IpPrefix dstIp = getDstIpFromSelector(rule);
318 - if (dstIp != null && !vsgWanIps.contains(dstIp.address())) {
319 - pipeline.processFlowRule(false, rule);
320 - }
321 - }
322 - }
323 -
324 - private VtnPort getVtnPort(Instance instance) {
325 - checkNotNull(osAccess, OPENSTACK_ACCESS_ERROR);
326 - checkNotNull(xosAccess, XOS_ACCESS_ERROR);
327 -
328 - VtnPortId vtnPortId = instance.portId();
329 - VtnPortApi portApi = xosClient.getClient(xosAccess).vtnPort();
330 - VtnPort vtnPort = portApi.vtnPort(vtnPortId, osAccess);
331 - if (vtnPort == null) {
332 - log.warn("Failed to get port information of {}", instance);
333 - return null;
334 - }
335 - return vtnPort;
336 - }
337 -
338 - // TODO get stag from XOS when XOS provides it, extract if from port name for now
339 - private VlanId getStag(VtnPort vtnPort) {
340 - checkNotNull(vtnPort);
341 -
342 - String portName = vtnPort.name();
343 - if (portName != null && portName.startsWith(STAG)) {
344 - return VlanId.vlanId(portName.split("-")[1]);
345 - } else {
346 - return null;
347 - }
348 - }
349 -
350 - private PortNumber getOutputFromTreatment(FlowRule flowRule) {
351 - Instruction instruction = flowRule.treatment().allInstructions().stream()
352 - .filter(inst -> inst instanceof Instructions.OutputInstruction)
353 - .findFirst()
354 - .orElse(null);
355 - if (instruction == null) {
356 - return null;
357 - }
358 - return ((Instructions.OutputInstruction) instruction).port();
359 - }
360 -
361 - private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
362 - Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
363 - if (criterion != null && criterion instanceof IPCriterion) {
364 - IPCriterion ip = (IPCriterion) criterion;
365 - return ip.ip();
366 - } else {
367 - return null;
368 - }
369 - }
370 -
371 - private boolean isVlanPushFromTreatment(FlowRule flowRule) {
372 - Instruction instruction = flowRule.treatment().allInstructions().stream()
373 - .filter(inst -> inst instanceof L2ModificationInstruction)
374 - .filter(inst -> ((L2ModificationInstruction) inst).subtype().equals(VLAN_PUSH))
375 - .findAny()
376 - .orElse(null);
377 - return instruction != null;
378 - }
379 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * Implementation of instance handlers for various network services.
19 - */
20 -package org.onosproject.cordvtn.impl.service;
...\ No newline at end of file ...\ No newline at end of file
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.cordvtn.rest;
18 -
19 -import org.onlab.rest.AbstractWebApplication;
20 -
21 -import java.util.Set;
22 -
23 -/**
24 - * CORD VTN Web application.
25 - */
26 -public class CordVtnWebApplication extends AbstractWebApplication {
27 - @Override
28 - public Set<Class<?>> getClasses() {
29 - return getClasses(ServiceDependencyWebResource.class,
30 - NeutronMl2NetworksWebResource.class,
31 - NeutronMl2SubnetsWebResource.class,
32 - NeutronMl2PortsWebResource.class);
33 - }
34 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.rest;
17 -
18 -import org.onosproject.rest.AbstractWebResource;
19 -import org.slf4j.Logger;
20 -import org.slf4j.LoggerFactory;
21 -
22 -import javax.ws.rs.Consumes;
23 -import javax.ws.rs.DELETE;
24 -import javax.ws.rs.POST;
25 -import javax.ws.rs.PUT;
26 -import javax.ws.rs.Path;
27 -import javax.ws.rs.PathParam;
28 -import javax.ws.rs.Produces;
29 -import javax.ws.rs.core.MediaType;
30 -import javax.ws.rs.core.Response;
31 -import java.io.InputStream;
32 -
33 -/**
34 - * Dummy Neutron ML2 mechanism driver.
35 - * It just returns OK for networks resource requests.
36 - */
37 -@Path("networks")
38 -public class NeutronMl2NetworksWebResource extends AbstractWebResource {
39 - protected final Logger log = LoggerFactory.getLogger(getClass());
40 - private static final String NETWORKS_MESSAGE = "Received networks %s";
41 -
42 - @POST
43 - @Consumes(MediaType.APPLICATION_JSON)
44 - @Produces(MediaType.APPLICATION_JSON)
45 - public Response createNetwork(InputStream input) {
46 - log.trace(String.format(NETWORKS_MESSAGE, "create"));
47 - return Response.status(Response.Status.OK).build();
48 - }
49 -
50 - @PUT
51 - @Path("{id}")
52 - @Consumes(MediaType.APPLICATION_JSON)
53 - @Produces(MediaType.APPLICATION_JSON)
54 - public Response updateNetwork(@PathParam("id") String id, InputStream input) {
55 - log.trace(String.format(NETWORKS_MESSAGE, "update"));
56 - return Response.status(Response.Status.OK).build();
57 - }
58 -
59 - @DELETE
60 - @Path("{id}")
61 - public Response deleteNetwork(@PathParam("id") String id) {
62 - log.trace(String.format(NETWORKS_MESSAGE, "delete"));
63 - return Response.noContent().build();
64 - }
65 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.rest;
17 -
18 -import com.fasterxml.jackson.databind.JsonNode;
19 -import com.fasterxml.jackson.databind.ObjectMapper;
20 -import com.google.common.collect.Maps;
21 -import org.onlab.osgi.DefaultServiceDirectory;
22 -import org.onlab.packet.IpAddress;
23 -import org.onlab.packet.MacAddress;
24 -import org.onosproject.cordvtn.impl.service.VsgInstanceHandler;
25 -import org.onosproject.net.HostId;
26 -import org.onosproject.rest.AbstractWebResource;
27 -import org.slf4j.Logger;
28 -import org.slf4j.LoggerFactory;
29 -
30 -import javax.ws.rs.Consumes;
31 -import javax.ws.rs.DELETE;
32 -import javax.ws.rs.POST;
33 -import javax.ws.rs.PUT;
34 -import javax.ws.rs.Path;
35 -import javax.ws.rs.PathParam;
36 -import javax.ws.rs.Produces;
37 -import javax.ws.rs.core.MediaType;
38 -import javax.ws.rs.core.Response;
39 -import java.io.InputStream;
40 -import java.util.Map;
41 -
42 -
43 -/**
44 - * Dummy Neutron ML2 mechanism driver.
45 - * It just returns OK for ports resource requests except for the port update.
46 - */
47 -@Path("ports")
48 -public class NeutronMl2PortsWebResource extends AbstractWebResource {
49 - protected final Logger log = LoggerFactory.getLogger(getClass());
50 - private static final String PORTS_MESSAGE = "Received ports %s";
51 -
52 - private static final String PORT = "port";
53 - private static final String DEVICE_ID = "device_id";
54 - private static final String NAME = "name";
55 - private static final String MAC_ADDRESS = "mac_address";
56 - private static final String ADDRESS_PAIRS = "allowed_address_pairs";
57 - private static final String IP_ADDERSS = "ip_address";
58 - private static final String STAG_PREFIX = "stag-";
59 - private static final int STAG_BEGIN_INDEX = 5;
60 -
61 - private final VsgInstanceHandler service = DefaultServiceDirectory.getService(VsgInstanceHandler.class);
62 -
63 - @POST
64 - @Consumes(MediaType.APPLICATION_JSON)
65 - @Produces(MediaType.APPLICATION_JSON)
66 - public Response createPorts(InputStream input) {
67 - log.trace(String.format(PORTS_MESSAGE, "create"));
68 - return Response.status(Response.Status.OK).build();
69 - }
70 -
71 - @PUT
72 - @Path("{id}")
73 - @Consumes(MediaType.APPLICATION_JSON)
74 - @Produces(MediaType.APPLICATION_JSON)
75 - public Response updatePorts(@PathParam("id") String id, InputStream input) {
76 - log.debug(String.format(PORTS_MESSAGE, "update"));
77 -
78 - // TODO get vSG updates from XOS to CORD VTN service directly
79 - try {
80 - ObjectMapper mapper = new ObjectMapper();
81 - JsonNode jsonNode = mapper.readTree(input).get(PORT);
82 - log.trace("{}", jsonNode.toString());
83 -
84 - String deviceId = jsonNode.path(DEVICE_ID).asText();
85 - String name = jsonNode.path(NAME).asText();
86 - if (deviceId.isEmpty() || name.isEmpty() || !name.startsWith(STAG_PREFIX)) {
87 - // ignore all updates other than allowed address pairs
88 - return Response.status(Response.Status.OK).build();
89 - }
90 -
91 - // this is allowed address pairs updates
92 - MacAddress mac = MacAddress.valueOf(jsonNode.path(MAC_ADDRESS).asText());
93 - Map<IpAddress, MacAddress> vsgInstances = Maps.newHashMap();
94 - jsonNode.path(ADDRESS_PAIRS).forEach(addrPair -> {
95 - IpAddress pairIp = IpAddress.valueOf(addrPair.path(IP_ADDERSS).asText());
96 - MacAddress pairMac = MacAddress.valueOf(addrPair.path(MAC_ADDRESS).asText());
97 - vsgInstances.put(pairIp, pairMac);
98 - });
99 -
100 - service.updateVsgInstances(HostId.hostId(mac),
101 - name.substring(STAG_BEGIN_INDEX),
102 - vsgInstances);
103 - } catch (Exception e) {
104 - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
105 - }
106 -
107 - return Response.status(Response.Status.OK).build();
108 - }
109 -
110 - @Path("{id}")
111 - @DELETE
112 - public Response deletePorts(@PathParam("id") String id) {
113 - log.trace(String.format(PORTS_MESSAGE, "delete"));
114 - return Response.noContent().build();
115 - }
116 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.rest;
17 -
18 -import org.onosproject.rest.AbstractWebResource;
19 -import org.slf4j.Logger;
20 -import org.slf4j.LoggerFactory;
21 -
22 -import javax.ws.rs.Consumes;
23 -import javax.ws.rs.DELETE;
24 -import javax.ws.rs.POST;
25 -import javax.ws.rs.PUT;
26 -import javax.ws.rs.Path;
27 -import javax.ws.rs.PathParam;
28 -import javax.ws.rs.Produces;
29 -import javax.ws.rs.core.MediaType;
30 -import javax.ws.rs.core.Response;
31 -import java.io.InputStream;
32 -
33 -/**
34 - * Dummy Neutron ML2 mechanism driver.
35 - * It just returns OK for subnets resource requests.
36 - */
37 -@Path("subnets")
38 -public class NeutronMl2SubnetsWebResource extends AbstractWebResource {
39 - protected final Logger log = LoggerFactory.getLogger(getClass());
40 - private static final String SUBNETS_MESSAGE = "Received subnets %s";
41 -
42 - @POST
43 - @Consumes(MediaType.APPLICATION_JSON)
44 - @Produces(MediaType.APPLICATION_JSON)
45 - public Response createSubnet(InputStream input) {
46 - log.trace(String.format(SUBNETS_MESSAGE, "create"));
47 - return Response.status(Response.Status.OK).build();
48 - }
49 -
50 -
51 - @PUT
52 - @Path("{id}")
53 - @Produces(MediaType.APPLICATION_JSON)
54 - @Consumes(MediaType.APPLICATION_JSON)
55 - public Response updateSubnet(@PathParam("id") String id, InputStream input) {
56 - log.trace(String.format(SUBNETS_MESSAGE, "update"));
57 - return Response.status(Response.Status.OK).build();
58 -
59 - }
60 -
61 - @DELETE
62 - @Path("{id}")
63 - public Response deleteSubnet(@PathParam("id") String id) {
64 - log.trace(String.format(SUBNETS_MESSAGE, "delete"));
65 - return Response.noContent().build();
66 - }
67 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.cordvtn.rest;
17 -
18 -import org.onosproject.cordvtn.api.CordVtnService;
19 -import org.onosproject.rest.AbstractWebResource;
20 -import org.onosproject.xosclient.api.VtnServiceId;
21 -
22 -import javax.ws.rs.DELETE;
23 -import javax.ws.rs.POST;
24 -import javax.ws.rs.Path;
25 -import javax.ws.rs.PathParam;
26 -import javax.ws.rs.Produces;
27 -import javax.ws.rs.core.MediaType;
28 -import javax.ws.rs.core.Response;
29 -
30 -/**
31 - * Manages service dependency.
32 - */
33 -@Path("service-dependency")
34 -public class ServiceDependencyWebResource extends AbstractWebResource {
35 -
36 - private final CordVtnService service = get(CordVtnService.class);
37 - private static final String BIDIRECTION = "b";
38 -
39 - /**
40 - * Creates service dependencies with unidirectional access between the services.
41 - *
42 - * @param tServiceId tenant service id
43 - * @param pServiceId provider service id
44 - * @return 200 OK
45 - */
46 - @POST
47 - @Path("{tenantServiceId}/{providerServiceId}")
48 - @Produces(MediaType.APPLICATION_JSON)
49 - public Response createServiceDependency(@PathParam("tenantServiceId") String tServiceId,
50 - @PathParam("providerServiceId") String pServiceId) {
51 - service.createServiceDependency(VtnServiceId.of(tServiceId),
52 - VtnServiceId.of(pServiceId),
53 - false);
54 - return Response.status(Response.Status.OK).build();
55 - }
56 -
57 - /**
58 - * Creates service dependencies with an access type extension between the services.
59 - *
60 - * @param tServiceId tenant service id
61 - * @param pServiceId provider service id
62 - * @param direction b for bidirectional access, otherwise unidirectional access
63 - * @return 200 OK
64 - */
65 - @POST
66 - @Path("{tenantServiceId}/{providerServiceId}/{direction}")
67 - @Produces(MediaType.APPLICATION_JSON)
68 - public Response createServiceDependency(@PathParam("tenantServiceId") String tServiceId,
69 - @PathParam("providerServiceId") String pServiceId,
70 - @PathParam("direction") String direction) {
71 - service.createServiceDependency(VtnServiceId.of(tServiceId),
72 - VtnServiceId.of(pServiceId),
73 - direction.equals(BIDIRECTION));
74 - return Response.status(Response.Status.OK).build();
75 - }
76 -
77 - /**
78 - * Removes service dependencies.
79 - *
80 - * @param tServiceId tenant service id
81 - * @param pServiceId provider service id
82 - * @return 204 NO CONTENT
83 - */
84 - @DELETE
85 - @Path("{tenantServiceId}/{providerServiceId}")
86 - public Response removeServiceDependency(@PathParam("tenantServiceId") String tServiceId,
87 - @PathParam("providerServiceId") String pServiceId) {
88 - service.removeServiceDependency(VtnServiceId.of(tServiceId), VtnServiceId.of(pServiceId));
89 - return Response.noContent().build();
90 - }
91 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * REST APIs for CORD VTN.
19 - */
20 -package org.onosproject.cordvtn.rest;
...\ No newline at end of file ...\ No newline at end of file
1 -<!--
2 - ~ Copyright 2015-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
17 -
18 - <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
19 - <command>
20 - <action class="org.onosproject.cordvtn.cli.CordVtnNodeListCommand"/>
21 - </command>
22 - <command>
23 - <action class="org.onosproject.cordvtn.cli.CordVtnNodeDeleteCommand"/>
24 - </command>
25 - <command>
26 - <action class="org.onosproject.cordvtn.cli.CordVtnNodeInitCommand"/>
27 - </command>
28 - <command>
29 - <action class="org.onosproject.cordvtn.cli.CordVtnNodeCheckCommand"/>
30 - </command>
31 - <command>
32 - <action class="org.onosproject.cordvtn.cli.CordVtnFlushRules"/>
33 - </command>
34 - </command-bundle>
35 -</blueprint>
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18 - xmlns="http://java.sun.com/xml/ns/javaee"
19 - xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
20 - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
21 - id="ONOS" version="2.5">
22 - <display-name>CORD VTN REST API v1.0</display-name>
23 -
24 - <security-constraint>
25 - <web-resource-collection>
26 - <web-resource-name>Secured</web-resource-name>
27 - <url-pattern>/*</url-pattern>
28 - </web-resource-collection>
29 - <auth-constraint>
30 - <role-name>admin</role-name>
31 - </auth-constraint>
32 - </security-constraint>
33 -
34 - <security-role>
35 - <role-name>admin</role-name>
36 - </security-role>
37 -
38 - <login-config>
39 - <auth-method>BASIC</auth-method>
40 - <realm-name>karaf</realm-name>
41 - </login-config>
42 -
43 - <servlet>
44 - <servlet-name>JAX-RS Service</servlet-name>
45 - <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
46 - <init-param>
47 - <param-name>javax.ws.rs.Application</param-name>
48 - <param-value>org.onosproject.cordvtn.rest.CordVtnWebApplication</param-value>
49 - </init-param>
50 - <load-on-startup>1</load-on-startup>
51 - </servlet>
52 -
53 - <servlet-mapping>
54 - <servlet-name>JAX-RS Service</servlet-name>
55 - <url-pattern>/*</url-pattern>
56 - </servlet-mapping>
57 -</web-app>
1 -COMPILE_DEPS = [
2 - '//lib:CORE_DEPS',
3 - '//lib:org.apache.karaf.shell.console',
4 - '//cli:onos-cli',
5 - '//apps/olt:onos-apps-olt-api',
6 - '//apps/cordconfig:onos-apps-cordconfig',
7 -]
8 -
9 -BUNDLES = [
10 - '//apps/olt:onos-apps-olt-api',
11 - '//apps/igmp:onos-apps-igmp',
12 -]
13 -
14 -osgi_jar_with_tests (
15 - deps = COMPILE_DEPS,
16 -)
17 -
18 -onos_app (
19 - title = 'IGMP App',
20 - category = 'Traffic Steering',
21 - url = 'http://onosproject.org',
22 - description = 'Internet Group Message Protocol',
23 - included_bundles = BUNDLES,
24 -)
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onos-apps</artifactId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 - <artifactId>onos-app-igmp</artifactId>
30 - <packaging>bundle</packaging>
31 -
32 - <description>Internet Group Message Protocol</description>
33 -
34 - <properties>
35 - <onos.app.name>org.onosproject.igmp</onos.app.name>
36 - <onos.app.title>IGMP App</onos.app.title>
37 - <onos.app.category>Traffic Steering</onos.app.category>
38 - <onos.app.url>http://onosproject.org</onos.app.url>
39 - <onos.app.readme>IGMP implementation.</onos.app.readme>
40 - <onos.app.requires>org.onosproject.cord-config</onos.app.requires>
41 - </properties>
42 -
43 - <dependencies>
44 - <dependency>
45 - <groupId>org.onosproject</groupId>
46 - <artifactId>onos-api</artifactId>
47 - <version>${project.version}</version>
48 - </dependency>
49 -
50 - <dependency>
51 - <groupId>org.onosproject</groupId>
52 - <artifactId>onos-cli</artifactId>
53 - <version>${project.version}</version>
54 - </dependency>
55 -
56 - <dependency>
57 - <groupId>org.onosproject</groupId>
58 - <artifactId>onos-app-olt-api</artifactId>
59 - <version>${project.version}</version>
60 - </dependency>
61 -
62 - <dependency>
63 - <groupId>org.onosproject</groupId>
64 - <artifactId>onlab-osgi</artifactId>
65 - <version>${project.version}</version>
66 - </dependency>
67 -
68 - <dependency>
69 - <groupId>org.onosproject</groupId>
70 - <artifactId>onos-cord-config</artifactId>
71 - <version>${project.version}</version>
72 - </dependency>
73 -
74 - <dependency>
75 - <groupId>org.onosproject</groupId>
76 - <artifactId>onlab-junit</artifactId>
77 - <scope>test</scope>
78 - </dependency>
79 -
80 - <!-- This is needed by ComponentContext, used for tunable configuration -->
81 - <dependency>
82 - <groupId>org.osgi</groupId>
83 - <artifactId>org.osgi.compendium</artifactId>
84 - </dependency>
85 -
86 - <dependency>
87 - <groupId>org.apache.felix</groupId>
88 - <artifactId>org.apache.felix.scr.annotations</artifactId>
89 - <scope>provided</scope>
90 - </dependency>
91 -
92 - </dependencies>
93 -
94 -</project>
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.igmp;
17 -
18 -import org.apache.felix.scr.annotations.Activate;
19 -import org.apache.felix.scr.annotations.Component;
20 -import org.apache.felix.scr.annotations.Deactivate;
21 -import org.apache.felix.scr.annotations.Modified;
22 -import org.apache.felix.scr.annotations.Property;
23 -import org.apache.felix.scr.annotations.Reference;
24 -import org.apache.felix.scr.annotations.ReferenceCardinality;
25 -import org.onlab.packet.EthType;
26 -import org.onlab.packet.Ethernet;
27 -import org.onlab.packet.IGMP;
28 -import org.onlab.packet.IGMPMembership;
29 -import org.onlab.packet.IGMPQuery;
30 -import org.onlab.packet.IPv4;
31 -import org.onlab.packet.Ip4Address;
32 -import org.onlab.packet.IpAddress;
33 -import org.onlab.packet.IpPrefix;
34 -import org.onlab.util.SafeRecurringTask;
35 -import org.onlab.util.Tools;
36 -import org.onosproject.cfg.ComponentConfigService;
37 -import org.onosproject.cordconfig.access.AccessDeviceConfig;
38 -import org.onosproject.cordconfig.access.AccessDeviceData;
39 -import org.onosproject.core.ApplicationId;
40 -import org.onosproject.core.CoreService;
41 -import org.onosproject.net.ConnectPoint;
42 -import org.onosproject.net.DeviceId;
43 -import org.onosproject.net.Port;
44 -import org.onosproject.net.PortNumber;
45 -import org.onosproject.net.config.ConfigFactory;
46 -import org.onosproject.net.config.NetworkConfigEvent;
47 -import org.onosproject.net.config.NetworkConfigListener;
48 -import org.onosproject.net.config.NetworkConfigRegistry;
49 -import org.onosproject.net.config.basics.SubjectFactories;
50 -import org.onosproject.net.device.DeviceEvent;
51 -import org.onosproject.net.device.DeviceListener;
52 -import org.onosproject.net.device.DeviceService;
53 -import org.onosproject.net.flow.DefaultTrafficTreatment;
54 -import org.onosproject.net.flow.TrafficTreatment;
55 -import org.onosproject.net.flow.criteria.Criteria;
56 -import org.onosproject.net.flowobjective.DefaultFilteringObjective;
57 -import org.onosproject.net.flowobjective.FilteringObjective;
58 -import org.onosproject.net.flowobjective.FlowObjectiveService;
59 -import org.onosproject.net.flowobjective.Objective;
60 -import org.onosproject.net.flowobjective.ObjectiveContext;
61 -import org.onosproject.net.flowobjective.ObjectiveError;
62 -import org.onosproject.net.mcast.McastRoute;
63 -import org.onosproject.net.mcast.MulticastRouteService;
64 -import org.onosproject.net.packet.DefaultOutboundPacket;
65 -import org.onosproject.net.packet.InboundPacket;
66 -import org.onosproject.net.packet.PacketContext;
67 -import org.onosproject.net.packet.PacketProcessor;
68 -import org.onosproject.net.packet.PacketService;
69 -
70 -import org.osgi.service.component.ComponentContext;
71 -import org.slf4j.Logger;
72 -
73 -import java.nio.ByteBuffer;
74 -import java.util.Collection;
75 -import java.util.Dictionary;
76 -import java.util.List;
77 -import java.util.Map;
78 -import java.util.Properties;
79 -import java.util.concurrent.ConcurrentHashMap;
80 -import java.util.concurrent.Executors;
81 -import java.util.concurrent.ScheduledExecutorService;
82 -import java.util.concurrent.ScheduledFuture;
83 -import java.util.concurrent.TimeUnit;
84 -
85 -import static org.onlab.util.Tools.groupedThreads;
86 -import static org.slf4j.LoggerFactory.getLogger;
87 -
88 -/**
89 - * Internet Group Management Protocol.
90 - */
91 -@Component(immediate = true)
92 -public class IgmpSnoop {
93 -
94 - private final Logger log = getLogger(getClass());
95 -
96 - private static final String DEST_MAC = "01:00:5E:00:00:01";
97 - private static final String DEST_IP = "224.0.0.1";
98 -
99 - private static final int DEFAULT_QUERY_PERIOD_SECS = 60;
100 - private static final byte DEFAULT_IGMP_RESP_CODE = 100;
101 -
102 - @Property(name = "multicastAddress",
103 - label = "Define the multicast base range to listen to")
104 - private String multicastAddress = IpPrefix.IPV4_MULTICAST_PREFIX.toString();
105 -
106 - @Property(name = "queryPeriod", intValue = DEFAULT_QUERY_PERIOD_SECS,
107 - label = "Delay in seconds between successive query runs")
108 - private int queryPeriod = DEFAULT_QUERY_PERIOD_SECS;
109 -
110 - @Property(name = "maxRespCode", byteValue = DEFAULT_IGMP_RESP_CODE,
111 - label = "Maximum time allowed before sending a responding report")
112 - private byte maxRespCode = DEFAULT_IGMP_RESP_CODE;
113 -
114 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 - protected FlowObjectiveService flowObjectiveService;
116 -
117 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 - protected PacketService packetService;
119 -
120 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 - protected CoreService coreService;
122 -
123 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 - protected NetworkConfigRegistry networkConfig;
125 -
126 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 - protected ComponentConfigService componentConfigService;
128 -
129 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 - protected MulticastRouteService multicastService;
131 -
132 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
133 - protected DeviceService deviceService;
134 -
135 -
136 - private ScheduledFuture<?> queryTask;
137 - private final ScheduledExecutorService queryService =
138 - Executors.newSingleThreadScheduledExecutor(groupedThreads("onos/igmp-query",
139 - "membership-query"));
140 -
141 - private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
142 -
143 - private Map<IpAddress, IpAddress> ssmTranslateTable = new ConcurrentHashMap<>();
144 -
145 - private DeviceListener deviceListener = new InternalDeviceListener();
146 - private IgmpPacketProcessor processor = new IgmpPacketProcessor();
147 - private static ApplicationId appId;
148 -
149 - private InternalNetworkConfigListener configListener =
150 - new InternalNetworkConfigListener();
151 -
152 - private static final Class<AccessDeviceConfig> CONFIG_CLASS =
153 - AccessDeviceConfig.class;
154 -
155 - private static final Class<IgmpSsmTranslateConfig> SSM_TRANSLATE_CONFIG_CLASS =
156 - IgmpSsmTranslateConfig.class;
157 -
158 - private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
159 - new ConfigFactory<DeviceId, AccessDeviceConfig>(
160 - SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
161 - @Override
162 - public AccessDeviceConfig createConfig() {
163 - return new AccessDeviceConfig();
164 - }
165 - };
166 -
167 - private ConfigFactory<ApplicationId, IgmpSsmTranslateConfig> ssmTranslateConfigFactory =
168 - new ConfigFactory<ApplicationId, IgmpSsmTranslateConfig>(
169 - SubjectFactories.APP_SUBJECT_FACTORY, SSM_TRANSLATE_CONFIG_CLASS, "ssmTranslate", true) {
170 - @Override
171 - public IgmpSsmTranslateConfig createConfig() {
172 - return new IgmpSsmTranslateConfig();
173 - }
174 - };
175 -
176 -
177 - private ByteBuffer queryPacket;
178 -
179 -
180 - @Activate
181 - public void activate(ComponentContext context) {
182 - componentConfigService.registerProperties(getClass());
183 - modified(context);
184 -
185 - appId = coreService.registerApplication("org.onosproject.igmp");
186 -
187 - packetService.addProcessor(processor, PacketProcessor.director(1));
188 -
189 - networkConfig.registerConfigFactory(configFactory);
190 - networkConfig.registerConfigFactory(ssmTranslateConfigFactory);
191 - networkConfig.addListener(configListener);
192 -
193 - networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
194 - subject -> {
195 - AccessDeviceConfig config = networkConfig.getConfig(subject,
196 - AccessDeviceConfig.class);
197 - if (config != null) {
198 - AccessDeviceData data = config.getOlt();
199 - oltData.put(data.deviceId(), data);
200 -
201 - }
202 - }
203 - );
204 -
205 - IgmpSsmTranslateConfig ssmTranslateConfig =
206 - networkConfig.getConfig(appId, IgmpSsmTranslateConfig.class);
207 -
208 - if (ssmTranslateConfig != null) {
209 - Collection<McastRoute> translations = ssmTranslateConfig.getSsmTranslations();
210 - for (McastRoute route : translations) {
211 - ssmTranslateTable.put(route.group(), route.source());
212 - }
213 - }
214 -
215 - oltData.keySet().stream()
216 - .flatMap(did -> deviceService.getPorts(did).stream())
217 - .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
218 - .filter(p -> p.isEnabled())
219 - .forEach(p -> processFilterObjective((DeviceId) p.element().id(), p, false));
220 -
221 - deviceService.addListener(deviceListener);
222 -
223 - restartQueryTask();
224 -
225 - log.info("Started");
226 - }
227 -
228 - @Deactivate
229 - public void deactivate() {
230 - packetService.removeProcessor(processor);
231 - processor = null;
232 - deviceService.removeListener(deviceListener);
233 - networkConfig.removeListener(configListener);
234 - networkConfig.unregisterConfigFactory(configFactory);
235 - networkConfig.unregisterConfigFactory(ssmTranslateConfigFactory);
236 - queryTask.cancel(true);
237 - queryService.shutdownNow();
238 - componentConfigService.unregisterProperties(getClass(), false);
239 - log.info("Stopped");
240 - }
241 -
242 - @Modified
243 - protected void modified(ComponentContext context) {
244 - Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
245 -
246 - // TODO read multicastAddress from config
247 - String strQueryPeriod = Tools.get(properties, "queryPeriod");
248 - String strResponseCode = Tools.get(properties, "maxRespCode");
249 - try {
250 - byte newMaxRespCode = Byte.parseByte(strResponseCode);
251 - if (maxRespCode != newMaxRespCode) {
252 - maxRespCode = newMaxRespCode;
253 - queryPacket = buildQueryPacket();
254 - }
255 -
256 - int newQueryPeriod = Integer.parseInt(strQueryPeriod);
257 - if (newQueryPeriod != queryPeriod) {
258 - queryPeriod = newQueryPeriod;
259 - restartQueryTask();
260 - }
261 -
262 - } catch (NumberFormatException e) {
263 - log.warn("Error parsing config input", e);
264 - }
265 -
266 - log.info("queryPeriod set to {}", queryPeriod);
267 - log.info("maxRespCode set to {}", maxRespCode);
268 - }
269 -
270 - private void restartQueryTask() {
271 - if (queryTask != null) {
272 - queryTask.cancel(true);
273 - }
274 - queryPacket = buildQueryPacket();
275 - queryTask = queryService.scheduleWithFixedDelay(
276 - SafeRecurringTask.wrap(this::querySubscribers),
277 - 0,
278 - queryPeriod,
279 - TimeUnit.SECONDS);
280 - }
281 -
282 - private void processFilterObjective(DeviceId devId, Port port, boolean remove) {
283 -
284 - //TODO migrate to packet requests when packet service uses filtering objectives
285 - DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
286 -
287 - builder = remove ? builder.deny() : builder.permit();
288 -
289 - FilteringObjective igmp = builder
290 - .withKey(Criteria.matchInPort(port.number()))
291 - .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
292 - .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
293 - .withMeta(DefaultTrafficTreatment.builder()
294 - .setOutput(PortNumber.CONTROLLER).build())
295 - .fromApp(appId)
296 - .withPriority(10000)
297 - .add(new ObjectiveContext() {
298 - @Override
299 - public void onSuccess(Objective objective) {
300 - log.info("Igmp filter for {} on {} installed.",
301 - devId, port);
302 - }
303 -
304 - @Override
305 - public void onError(Objective objective, ObjectiveError error) {
306 - log.info("Igmp filter for {} on {} failed because {}.",
307 - devId, port, error);
308 - }
309 - });
310 -
311 - flowObjectiveService.filter(devId, igmp);
312 - }
313 -
314 - private void processMembership(IGMP pkt, ConnectPoint location) {
315 - pkt.getGroups().forEach(group -> {
316 -
317 - if (!(group instanceof IGMPMembership)) {
318 - log.warn("Wrong group type in IGMP membership");
319 - return;
320 - }
321 -
322 - IGMPMembership membership = (IGMPMembership) group;
323 -
324 - IpAddress groupAddress = membership.getGaddr();
325 -
326 - if (membership.getRecordType() == IGMPMembership.MODE_IS_INCLUDE ||
327 - membership.getRecordType() == IGMPMembership.CHANGE_TO_INCLUDE_MODE) {
328 -
329 - if (membership.getSources().isEmpty()) {
330 - McastRoute route = ssmTranslateRoute(groupAddress);
331 - if (route != null) {
332 - removeRoute(route, location);
333 - }
334 - } else {
335 - membership.getSources().stream()
336 - .map(source -> new McastRoute(source, groupAddress, McastRoute.Type.IGMP))
337 - .forEach(route -> addRoute(route, location));
338 - }
339 - } else if (membership.getRecordType() == IGMPMembership.MODE_IS_EXCLUDE ||
340 - membership.getRecordType() == IGMPMembership.CHANGE_TO_EXCLUDE_MODE) {
341 -
342 - if (membership.getSources().isEmpty()) {
343 - McastRoute route = ssmTranslateRoute(groupAddress);
344 - if (route != null) {
345 - addRoute(route, location);
346 - }
347 - } else {
348 - membership.getSources().stream()
349 - .map(source -> new McastRoute(source, groupAddress, McastRoute.Type.IGMP))
350 - .forEach(route -> removeRoute(route, location));
351 - }
352 - }
353 - });
354 - }
355 -
356 - private McastRoute ssmTranslateRoute(IpAddress group) {
357 - IpAddress source = ssmTranslateTable.get(group);
358 - if (source == null) {
359 - log.warn("No SSM translate source found for group {}", group);
360 - return null;
361 - }
362 - return new McastRoute(source, group, McastRoute.Type.IGMP);
363 - }
364 -
365 - private void addRoute(McastRoute route, ConnectPoint location) {
366 - multicastService.add(route);
367 - multicastService.addSink(route, location);
368 - }
369 -
370 - private void removeRoute(McastRoute route, ConnectPoint location) {
371 - multicastService.removeSink(route, location);
372 - // TODO remove route if all sinks are gone
373 - }
374 -
375 - private ByteBuffer buildQueryPacket() {
376 - IGMP igmp = new IGMP();
377 - igmp.setIgmpType(IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY);
378 - igmp.setMaxRespCode(maxRespCode);
379 -
380 - IGMPQuery query = new IGMPQuery(IpAddress.valueOf("0.0.0.0"), 0);
381 - igmp.addGroup(query);
382 -
383 - IPv4 ip = new IPv4();
384 - ip.setDestinationAddress(DEST_IP);
385 - ip.setProtocol(IPv4.PROTOCOL_IGMP);
386 - ip.setSourceAddress("192.168.1.1");
387 - ip.setTtl((byte) 1);
388 - ip.setPayload(igmp);
389 -
390 - Ethernet eth = new Ethernet();
391 - eth.setDestinationMACAddress(DEST_MAC);
392 - eth.setSourceMACAddress("DE:AD:BE:EF:BA:11");
393 - eth.setEtherType(Ethernet.TYPE_IPV4);
394 -
395 - eth.setPayload(ip);
396 -
397 - eth.setPad(true);
398 -
399 - return ByteBuffer.wrap(eth.serialize());
400 - }
401 -
402 - private void querySubscribers() {
403 - oltData.keySet().stream()
404 - .flatMap(did -> deviceService.getPorts(did).stream())
405 - .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
406 - .filter(p -> p.isEnabled())
407 - .forEach(p -> {
408 - TrafficTreatment treatment = DefaultTrafficTreatment.builder()
409 - .setOutput(p.number()).build();
410 - packetService.emit(new DefaultOutboundPacket((DeviceId) p.element().id(),
411 - treatment, queryPacket));
412 - });
413 - }
414 -
415 - /**
416 - * Packet processor responsible for handling IGMP packets.
417 - */
418 - private class IgmpPacketProcessor implements PacketProcessor {
419 -
420 - @Override
421 - public void process(PacketContext context) {
422 - // Stop processing if the packet has been handled, since we
423 - // can't do any more to it.
424 - if (context.isHandled()) {
425 - return;
426 - }
427 -
428 - InboundPacket pkt = context.inPacket();
429 - Ethernet ethPkt = pkt.parsed();
430 - if (ethPkt == null) {
431 - return;
432 - }
433 -
434 -
435 - // IPv6 MLD packets are handled by ICMP6. We'll only deal with IPv4.
436 - if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
437 - return;
438 - }
439 -
440 - IPv4 ip = (IPv4) ethPkt.getPayload();
441 - IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
442 - IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
443 - log.trace("Packet ({}, {}) -> ingress port: {}", saddr, gaddr,
444 - context.inPacket().receivedFrom());
445 -
446 -
447 - if (ip.getProtocol() != IPv4.PROTOCOL_IGMP ||
448 - !IpPrefix.IPV4_MULTICAST_PREFIX.contains(gaddr)) {
449 - return;
450 - }
451 -
452 - if (IpPrefix.IPV4_MULTICAST_PREFIX.contains(saddr)) {
453 - log.debug("IGMP Picked up a packet with a multicast source address.");
454 - return;
455 - }
456 -
457 - IGMP igmp = (IGMP) ip.getPayload();
458 - switch (igmp.getIgmpType()) {
459 - case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT:
460 - processMembership(igmp, pkt.receivedFrom());
461 - break;
462 -
463 - case IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY:
464 - log.debug("Received a membership query {} from {}",
465 - igmp, pkt.receivedFrom());
466 - break;
467 -
468 - case IGMP.TYPE_IGMPV1_MEMBERSHIP_REPORT:
469 - case IGMP.TYPE_IGMPV2_MEMBERSHIP_REPORT:
470 - case IGMP.TYPE_IGMPV2_LEAVE_GROUP:
471 - log.debug("IGMP version 1 & 2 message types are not currently supported. Message type: {}",
472 - igmp.getIgmpType());
473 - break;
474 - default:
475 - log.warn("Unknown IGMP message type: {}", igmp.getIgmpType());
476 - break;
477 - }
478 - }
479 - }
480 -
481 -
482 - private class InternalDeviceListener implements DeviceListener {
483 - @Override
484 - public void event(DeviceEvent event) {
485 - DeviceId devId = event.subject().id();
486 - switch (event.type()) {
487 -
488 - case DEVICE_ADDED:
489 - case DEVICE_UPDATED:
490 - case DEVICE_REMOVED:
491 - case DEVICE_SUSPENDED:
492 - case DEVICE_AVAILABILITY_CHANGED:
493 - case PORT_STATS_UPDATED:
494 - break;
495 - case PORT_ADDED:
496 - if (!oltData.get(devId).uplink().equals(event.port().number()) &&
497 - event.port().isEnabled()) {
498 - processFilterObjective(event.subject().id(), event.port(), false);
499 - }
500 - break;
501 - case PORT_UPDATED:
502 - if (oltData.get(devId).uplink().equals(event.port().number())) {
503 - break;
504 - }
505 - if (event.port().isEnabled()) {
506 - processFilterObjective(event.subject().id(), event.port(), false);
507 - } else {
508 - processFilterObjective(event.subject().id(), event.port(), true);
509 - }
510 - break;
511 - case PORT_REMOVED:
512 - processFilterObjective(event.subject().id(), event.port(), true);
513 - break;
514 - default:
515 - log.warn("Unknown device event {}", event.type());
516 - break;
517 - }
518 - }
519 -
520 - @Override
521 - public boolean isRelevant(DeviceEvent event) {
522 - return oltData.containsKey(event.subject().id());
523 - }
524 - }
525 -
526 - private class InternalNetworkConfigListener implements NetworkConfigListener {
527 - @Override
528 - public void event(NetworkConfigEvent event) {
529 - switch (event.type()) {
530 -
531 - case CONFIG_ADDED:
532 - case CONFIG_UPDATED:
533 - if (event.configClass().equals(CONFIG_CLASS)) {
534 - AccessDeviceConfig config =
535 - networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
536 - if (config != null) {
537 - oltData.put(config.getOlt().deviceId(), config.getOlt());
538 - provisionDefaultFlows((DeviceId) event.subject());
539 - }
540 - }
541 - if (event.configClass().equals(SSM_TRANSLATE_CONFIG_CLASS)) {
542 - IgmpSsmTranslateConfig config =
543 - networkConfig.getConfig((ApplicationId) event.subject(),
544 - SSM_TRANSLATE_CONFIG_CLASS);
545 -
546 - if (config != null) {
547 - ssmTranslateTable.clear();
548 - config.getSsmTranslations().forEach(
549 - route -> ssmTranslateTable.put(route.group(), route.source()));
550 - }
551 - }
552 - break;
553 - case CONFIG_REGISTERED:
554 - case CONFIG_UNREGISTERED:
555 - break;
556 - case CONFIG_REMOVED:
557 - if (event.configClass().equals(SSM_TRANSLATE_CONFIG_CLASS)) {
558 - ssmTranslateTable.clear();
559 - } else if (event.configClass().equals(CONFIG_CLASS)) {
560 - oltData.remove(event.subject());
561 - }
562 -
563 - default:
564 - break;
565 - }
566 - }
567 - }
568 -
569 - private void provisionDefaultFlows(DeviceId deviceId) {
570 - List<Port> ports = deviceService.getPorts(deviceId);
571 -
572 - ports.stream()
573 - .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
574 - .filter(p -> p.isEnabled())
575 - .forEach(p -> processFilterObjective((DeviceId) p.element().id(), p, false));
576 - }
577 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.igmp;
18 -
19 -import com.fasterxml.jackson.databind.JsonNode;
20 -import com.fasterxml.jackson.databind.node.ObjectNode;
21 -import org.onlab.packet.IpAddress;
22 -import org.onosproject.core.ApplicationId;
23 -import org.onosproject.net.config.Config;
24 -import org.onosproject.net.mcast.McastRoute;
25 -
26 -import java.util.ArrayList;
27 -import java.util.List;
28 -
29 -/**
30 - * IGMP SSM translate configuration.
31 - */
32 -public class IgmpSsmTranslateConfig extends Config<ApplicationId> {
33 -
34 - private static final String SOURCE = "source";
35 - private static final String GROUP = "group";
36 -
37 - @Override
38 - public boolean isValid() {
39 - for (JsonNode node : array) {
40 - if (!hasOnlyFields((ObjectNode) node, SOURCE, GROUP)) {
41 - return false;
42 - }
43 -
44 - if (!(isIpAddress((ObjectNode) node, SOURCE, FieldPresence.MANDATORY) &&
45 - isIpAddress((ObjectNode) node, GROUP, FieldPresence.MANDATORY))) {
46 - return false;
47 - }
48 -
49 - }
50 - return true;
51 - }
52 -
53 - /**
54 - * Gets the list of SSM translations.
55 - *
56 - * @return SSM translations
57 - */
58 - public List<McastRoute> getSsmTranslations() {
59 - List<McastRoute> translations = new ArrayList();
60 - for (JsonNode node : array) {
61 - translations.add(
62 - new McastRoute(
63 - IpAddress.valueOf(node.path(SOURCE).asText().trim()),
64 - IpAddress.valueOf(node.path(GROUP).asText().trim()),
65 - McastRoute.Type.STATIC));
66 - }
67 -
68 - return translations;
69 - }
70 -}
1 -/*
2 - * Copyright 2015-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * IGMP implementation.
19 - */
20 -package org.onosproject.igmp;
1 -COMPILE_DEPS = [
2 - '//lib:CORE_DEPS',
3 - '//lib:javax.ws.rs-api',
4 - '//lib:jersey-client',
5 - '//lib:org.apache.karaf.shell.console',
6 - '//utils/rest:onlab-rest',
7 - '//cli:onos-cli',
8 - '//core/store/serializers:onos-core-serializers',
9 - '//apps/cordconfig:onos-apps-cordconfig',
10 -]
11 -
12 -BUNDLES = [
13 - ':onos-apps-olt-api',
14 - ':onos-apps-olt',
15 -]
16 -
17 -osgi_jar_with_tests (
18 - name = 'onos-apps-olt-api',
19 - srcs = glob(['api/' + SRC + '*.java']),
20 - deps = COMPILE_DEPS,
21 - visibility = ['PUBLIC'],
22 -)
23 -
24 -osgi_jar_with_tests (
25 - srcs = glob(['app/' + SRC + '*.java']),
26 - deps = COMPILE_DEPS + [':onos-apps-olt-api'],
27 - visibility = ['PUBLIC'],
28 -)
29 -
30 -onos_app (
31 - title = 'ONOS OLT REST API',
32 - category = 'Security',
33 - url = 'http://onosproject.org',
34 - description = 'OLT application for CORD.',
35 - included_bundles = BUNDLES,
36 -)
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <artifactId>onos-olt</artifactId>
24 - <groupId>org.onosproject</groupId>
25 - <version>1.6.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 - <artifactId>onos-app-olt-api</artifactId>
30 - <packaging>bundle</packaging>
31 -
32 - <url>http://onosproject.org</url>
33 -
34 - <description>CORD OLT application API</description>
35 -
36 - <dependencies>
37 - <dependency>
38 - <groupId>org.onosproject</groupId>
39 - <artifactId>onlab-junit</artifactId>
40 - <scope>test</scope>
41 - </dependency>
42 - <dependency>
43 - <groupId>org.onosproject</groupId>
44 - <artifactId>onos-core-serializers</artifactId>
45 - <version>${project.version}</version>
46 - </dependency>
47 -
48 - <dependency>
49 - <groupId>org.onosproject</groupId>
50 - <artifactId>onos-api</artifactId>
51 - <version>${project.version}</version>
52 - <classifier>tests</classifier>
53 - <scope>test</scope>
54 - </dependency>
55 - <dependency>
56 - <groupId>org.onosproject</groupId>
57 - <artifactId>onos-cord-config</artifactId>
58 - <version>${project.version}</version>
59 - </dependency>
60 -
61 - </dependencies>
62 -
63 - <build>
64 - <plugins>
65 - <plugin>
66 - <groupId>org.apache.felix</groupId>
67 - <artifactId>maven-bundle-plugin</artifactId>
68 - <extensions>true</extensions>
69 - <configuration>
70 - <instructions>
71 - <Export-Package>org.onosproject.olt</Export-Package>
72 - </instructions>
73 - </configuration>
74 - </plugin>
75 - </plugins>
76 - </build>
77 -</project>
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.olt;
17 -
18 -import org.onlab.packet.VlanId;
19 -import org.onosproject.event.AbstractEvent;
20 -import org.onosproject.net.DeviceId;
21 -
22 -import java.util.Optional;
23 -
24 -/**
25 - * Describes an access device event.
26 - */
27 -public class AccessDeviceEvent extends AbstractEvent<AccessDeviceEvent.Type, DeviceId> {
28 -
29 - private final Optional<VlanId> sVlan;
30 - private final Optional<VlanId> cVlan;
31 -
32 - public enum Type {
33 - /**
34 - * A subscriber was registered and provisioned.
35 - */
36 - SUBSCRIBER_REGISTERED,
37 -
38 - /**
39 - * A subscriber was unregistered and deprovisioned.
40 - */
41 - SUBSCRIBER_UNREGISTERED,
42 -
43 - /**
44 - * An access device connected.
45 - */
46 - DEVICE_CONNECTED,
47 -
48 - /**
49 - * An access device disconnected.
50 - */
51 - DEVICE_DISCONNECTED
52 -
53 - }
54 -
55 - /**
56 - *
57 - * Creates an event of a given type and for the specified device,
58 - * along with the cVlanId and sVlanId. The vlan fields may not be provisioned
59 - * if the event is related to the access device (dis)connection.
60 - *
61 - * @param type the event type
62 - * @param deviceId the device id
63 - * @param sVlanId the service vlan
64 - * @param cVlanId the customer vlan
65 - */
66 - public AccessDeviceEvent(Type type, DeviceId deviceId,
67 - VlanId sVlanId,
68 - VlanId cVlanId) {
69 - super(type, deviceId);
70 - this.sVlan = Optional.ofNullable(sVlanId);
71 - this.cVlan = Optional.ofNullable(cVlanId);
72 - }
73 -
74 - /**
75 - *
76 - * Creates an event of a given type and for the specified device, and timestamp
77 - * along with the cVlanId and sVlanId. The vlan fields may not be provisioned
78 - * if the event is related to the access device (dis)connection.
79 - *
80 - * @param type the event type
81 - * @param deviceId the device id
82 - * @param time a timestamp
83 - * @param sVlanId the service vlan
84 - * @param cVlanId the customer vlan
85 - */
86 - protected AccessDeviceEvent(Type type, DeviceId deviceId, long time,
87 - VlanId sVlanId,
88 - VlanId cVlanId) {
89 - super(type, deviceId, time);
90 - this.sVlan = Optional.ofNullable(sVlanId);
91 - this.cVlan = Optional.ofNullable(cVlanId);
92 -
93 - }
94 -
95 - public Optional<VlanId> sVlanId() {
96 - return sVlan;
97 - }
98 -
99 - public Optional<VlanId> cVlanId() {
100 - return cVlan;
101 - }
102 -
103 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.olt;
17 -
18 -import org.onosproject.event.EventListener;
19 -
20 -/**
21 - * Entity capable of receiving access device related events.
22 - */
23 -public interface AccessDeviceListener extends EventListener<AccessDeviceEvent> {
24 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.olt;
18 -
19 -import org.onlab.packet.VlanId;
20 -import org.onosproject.cordconfig.access.AccessDeviceData;
21 -import org.onosproject.event.ListenerService;
22 -import org.onosproject.net.ConnectPoint;
23 -import org.onosproject.net.DeviceId;
24 -
25 -import java.util.Collection;
26 -import java.util.Map;
27 -
28 -/**
29 - * Service for interacting with an access device (OLT).
30 - */
31 -public interface AccessDeviceService
32 - extends ListenerService<AccessDeviceEvent, AccessDeviceListener> {
33 -
34 - /**
35 - * Provisions connectivity for a subscriber on an access device.
36 - *
37 - * @param port subscriber's connection point
38 - * @param vlan VLAN ID to provision for subscriber
39 - */
40 - void provisionSubscriber(ConnectPoint port, VlanId vlan);
41 -
42 - /**
43 - * Removes provisioned connectivity for a subscriber from an access device.
44 - *
45 - * @param port subscriber's connection point
46 - */
47 - void removeSubscriber(ConnectPoint port);
48 -
49 - /**
50 - * Returns information about the provisioned subscribers.
51 - *
52 - * @return subscribers
53 - */
54 - Collection<Map.Entry<ConnectPoint, VlanId>> getSubscribers();
55 -
56 - /**
57 - * Returns the map of configured OLTs.
58 - *
59 - * @return a map
60 - */
61 - Map<DeviceId, AccessDeviceData> fetchOlts();
62 -
63 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * OLT application api.
19 - */
20 -package org.onosproject.olt;
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<app name="org.onosproject.olt" origin="ON.Lab" version="${project.version}"
18 - category="Traffic Steering" url="http://onosproject.org" title="Optical Line Terminal App"
19 - featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
20 - features="${project.artifactId}" apps="org.onosproject.cord-config">
21 - <description>${project.description}</description>
22 - <artifact>mvn:${project.groupId}/${project.artifactId}/${project.version}</artifact>
23 - <artifact>mvn:${project.groupId}/onos-app-olt-api/${project.version}</artifact>
24 -</app>
1 -<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
18 - <feature name="${project.artifactId}" version="${project.version}"
19 - description="${project.description}">
20 - <feature>onos-api</feature>
21 - <bundle>mvn:${project.groupId}/onos-app-olt-api/${project.version}</bundle>
22 - <bundle>mvn:${project.groupId}/onos-app-olt/${project.version}</bundle>
23 - </feature>
24 -</features>
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20 - <parent>
21 - <groupId>org.onosproject</groupId>
22 - <artifactId>onos-olt</artifactId>
23 - <version>1.6.0-SNAPSHOT</version>
24 - <relativePath>../pom.xml</relativePath>
25 - </parent>
26 - <modelVersion>4.0.0</modelVersion>
27 -
28 - <artifactId>onos-app-olt</artifactId>
29 -
30 - <packaging>bundle</packaging>
31 - <description>OLT application for CORD</description>
32 -
33 - <properties>
34 - <web.context>/onos/olt</web.context>
35 - <api.version>1.0.0</api.version>
36 - <api.title>ONOS OLT REST API</api.title>
37 - <api.description>
38 - APIs for interacting with the CORD OLT application.
39 - </api.description>
40 - <api.package>org.onosproject.olt.rest</api.package>
41 - </properties>
42 -
43 - <dependencies>
44 - <dependency>
45 - <groupId>org.onosproject</groupId>
46 - <artifactId>onos-cord-config</artifactId>
47 - <version>${project.version}</version>
48 - </dependency>
49 - <dependency>
50 - <groupId>org.onosproject</groupId>
51 - <artifactId>onos-app-olt-api</artifactId>
52 - <version>${project.version}</version>
53 - </dependency>
54 -
55 - <dependency>
56 - <groupId>org.onosproject</groupId>
57 - <artifactId>onos-cli</artifactId>
58 - <version>${project.version}</version>
59 - </dependency>
60 -
61 - <dependency>
62 - <groupId>org.apache.karaf.shell</groupId>
63 - <artifactId>org.apache.karaf.shell.console</artifactId>
64 - </dependency>
65 - <dependency>
66 - <groupId>org.onosproject</groupId>
67 - <artifactId>onos-rest</artifactId>
68 - <version>${project.version}</version>
69 - </dependency>
70 - <dependency>
71 - <groupId>org.onosproject</groupId>
72 - <artifactId>onlab-rest</artifactId>
73 - <version>${project.version}</version>
74 - </dependency>
75 - <dependency>
76 - <groupId>javax.ws.rs</groupId>
77 - <artifactId>javax.ws.rs-api</artifactId>
78 - <version>2.0.1</version>
79 - </dependency>
80 - <dependency>
81 - <groupId>org.glassfish.jersey.containers</groupId>
82 - <artifactId>jersey-container-servlet</artifactId>
83 - </dependency>
84 - <dependency>
85 - <groupId>com.fasterxml.jackson.core</groupId>
86 - <artifactId>jackson-databind</artifactId>
87 - </dependency>
88 -
89 - <dependency>
90 - <groupId>com.fasterxml.jackson.core</groupId>
91 - <artifactId>jackson-annotations</artifactId>
92 - </dependency>
93 -
94 - <dependency>
95 - <groupId>org.osgi</groupId>
96 - <artifactId>org.osgi.compendium</artifactId>
97 - </dependency>
98 - <dependency>
99 - <groupId>org.osgi</groupId>
100 - <artifactId>org.osgi.core</artifactId>
101 - </dependency>
102 - </dependencies>
103 -
104 - <build>
105 - <plugins>
106 - <plugin>
107 - <groupId>org.apache.felix</groupId>
108 - <artifactId>maven-bundle-plugin</artifactId>
109 - <extensions>true</extensions>
110 - <configuration>
111 - <instructions>
112 - <_wab>src/main/webapp/</_wab>
113 - <Include-Resource>
114 - WEB-INF/classes/apidoc/swagger.json=target/swagger.json,
115 - {maven-resources}
116 - </Include-Resource>
117 - <Bundle-SymbolicName>
118 - ${project.groupId}.${project.artifactId}
119 - </Bundle-SymbolicName>
120 - <Import-Package>
121 - *,org.glassfish.jersey.servlet
122 - </Import-Package>
123 - <Web-ContextPath>${web.context}</Web-ContextPath>
124 - </instructions>
125 - </configuration>
126 - </plugin>
127 - </plugins>
128 - </build>
129 -</project>
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.olt.cli;
18 -
19 -import org.apache.karaf.shell.commands.Argument;
20 -import org.apache.karaf.shell.commands.Command;
21 -import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.cordconfig.access.AccessDeviceData;
23 -import org.onosproject.net.DeviceId;
24 -import org.onosproject.olt.AccessDeviceService;
25 -
26 -import java.util.Map;
27 -
28 -/**
29 - * Shows configured OLTs.
30 - */
31 -@Command(scope = "onos", name = "olts",
32 - description = "Shows configured OLTs")
33 -public class ShowOltCommand extends AbstractShellCommand {
34 -
35 - @Argument(index = 0, name = "deviceId", description = "Access device ID",
36 - required = false, multiValued = false)
37 - private String strDeviceId = null;
38 -
39 - @Override
40 - protected void execute() {
41 - AccessDeviceService service = AbstractShellCommand.get(AccessDeviceService.class);
42 - Map<DeviceId, AccessDeviceData> data = service.fetchOlts();
43 - if (strDeviceId != null) {
44 - DeviceId deviceId = DeviceId.deviceId(strDeviceId);
45 - print("OLT %s:", deviceId);
46 - display(data.get(deviceId));
47 - } else {
48 - data.keySet().forEach(did -> {
49 - print("OLT %s:", did);
50 - display(data.get(did));
51 - });
52 - }
53 - }
54 -
55 - private void display(AccessDeviceData accessDeviceData) {
56 - print("\tvlan : %s", accessDeviceData.vlan());
57 - print("\tuplink : %s", accessDeviceData.uplink());
58 - }
59 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.olt.cli;
18 -
19 -import org.apache.karaf.shell.commands.Command;
20 -import org.onlab.packet.VlanId;
21 -import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.net.ConnectPoint;
23 -import org.onosproject.olt.AccessDeviceService;
24 -
25 -import java.util.Map;
26 -
27 -/**
28 - * Shows provisioned subscribers.
29 - */
30 -@Command(scope = "onos", name = "subscribers",
31 - description = "Shows provisioned subscribers")
32 -public class ShowSubscribersCommand extends AbstractShellCommand {
33 -
34 - private static final String FORMAT = "port=%s, cvlan=%s";
35 -
36 - @Override
37 - protected void execute() {
38 - AccessDeviceService service = AbstractShellCommand.get(AccessDeviceService.class);
39 - service.getSubscribers().forEach(this::display);
40 - }
41 -
42 - private void display(Map.Entry<ConnectPoint, VlanId> subscriber) {
43 - print(FORMAT, subscriber.getKey(), subscriber.getValue());
44 - }
45 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.olt.cli;
18 -
19 -import org.apache.karaf.shell.commands.Argument;
20 -import org.apache.karaf.shell.commands.Command;
21 -import org.onlab.packet.VlanId;
22 -import org.onosproject.cli.AbstractShellCommand;
23 -import org.onosproject.net.ConnectPoint;
24 -import org.onosproject.net.DeviceId;
25 -import org.onosproject.net.PortNumber;
26 -import org.onosproject.olt.AccessDeviceService;
27 -
28 -/**
29 - * Adds a subscriber to an access device.
30 - */
31 -@Command(scope = "onos", name = "add-subscriber-access",
32 - description = "Adds a subscriber to an access device")
33 -public class SubscriberAddCommand extends AbstractShellCommand {
34 -
35 - @Argument(index = 0, name = "deviceId", description = "Access device ID",
36 - required = true, multiValued = false)
37 - private String strDeviceId = null;
38 -
39 - @Argument(index = 1, name = "port", description = "Subscriber port number",
40 - required = true, multiValued = false)
41 - private String strPort = null;
42 -
43 - @Argument(index = 2, name = "vlanId",
44 - description = "VLAN ID to add",
45 - required = true, multiValued = false)
46 - private String strVlanId = null;
47 -
48 - @Override
49 - protected void execute() {
50 - AccessDeviceService service = AbstractShellCommand.get(AccessDeviceService.class);
51 -
52 - DeviceId deviceId = DeviceId.deviceId(strDeviceId);
53 - PortNumber port = PortNumber.portNumber(strPort);
54 - VlanId vlan = VlanId.vlanId(Short.parseShort(strVlanId));
55 - ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
56 -
57 - service.provisionSubscriber(connectPoint, vlan);
58 - }
59 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -package org.onosproject.olt.cli;
18 -
19 -import org.apache.karaf.shell.commands.Argument;
20 -import org.apache.karaf.shell.commands.Command;
21 -import org.onosproject.cli.AbstractShellCommand;
22 -import org.onosproject.net.ConnectPoint;
23 -import org.onosproject.net.DeviceId;
24 -import org.onosproject.net.PortNumber;
25 -import org.onosproject.olt.AccessDeviceService;
26 -
27 -/**
28 - * Adds a subscriber to an access device.
29 - */
30 -@Command(scope = "onos", name = "remove-subscriber-access",
31 - description = "Adds a subscriber to an access device")
32 -public class SubscriberRemoveCommand extends AbstractShellCommand {
33 -
34 - @Argument(index = 0, name = "deviceId", description = "Access device ID",
35 - required = true, multiValued = false)
36 - private String strDeviceId = null;
37 -
38 - @Argument(index = 1, name = "port", description = "Subscriber port number",
39 - required = true, multiValued = false)
40 - private String strPort = null;
41 -
42 - @Override
43 - protected void execute() {
44 - AccessDeviceService service = AbstractShellCommand.get(AccessDeviceService.class);
45 -
46 - DeviceId deviceId = DeviceId.deviceId(strDeviceId);
47 - PortNumber port = PortNumber.portNumber(strPort);
48 - ConnectPoint connectPoint = new ConnectPoint(deviceId, port);
49 -
50 - service.removeSubscriber(connectPoint);
51 -
52 - }
53 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * OLT application handling PMC OLT hardware.
19 - */
20 -package org.onosproject.olt.cli;
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.olt.impl;
17 -
18 -import com.google.common.collect.Maps;
19 -import org.apache.felix.scr.annotations.Activate;
20 -import org.apache.felix.scr.annotations.Component;
21 -import org.apache.felix.scr.annotations.Deactivate;
22 -import org.apache.felix.scr.annotations.Modified;
23 -import org.apache.felix.scr.annotations.Property;
24 -import org.apache.felix.scr.annotations.Reference;
25 -import org.apache.felix.scr.annotations.ReferenceCardinality;
26 -import org.apache.felix.scr.annotations.Service;
27 -import org.onlab.packet.EthType;
28 -import org.onlab.packet.VlanId;
29 -import org.onosproject.cfg.ComponentConfigService;
30 -import org.onosproject.cordconfig.access.AccessDeviceConfig;
31 -import org.onosproject.cordconfig.access.AccessDeviceData;
32 -import org.onosproject.core.ApplicationId;
33 -import org.onosproject.core.CoreService;
34 -import org.onosproject.event.AbstractListenerManager;
35 -import org.onosproject.mastership.MastershipService;
36 -import org.onosproject.net.ConnectPoint;
37 -import org.onosproject.net.DeviceId;
38 -import org.onosproject.net.Port;
39 -import org.onosproject.net.PortNumber;
40 -import org.onosproject.net.config.ConfigFactory;
41 -import org.onosproject.net.config.NetworkConfigEvent;
42 -import org.onosproject.net.config.NetworkConfigListener;
43 -import org.onosproject.net.config.NetworkConfigRegistry;
44 -import org.onosproject.net.config.basics.SubjectFactories;
45 -import org.onosproject.net.device.DeviceEvent;
46 -import org.onosproject.net.device.DeviceListener;
47 -import org.onosproject.net.device.DeviceService;
48 -import org.onosproject.net.flow.DefaultTrafficSelector;
49 -import org.onosproject.net.flow.DefaultTrafficTreatment;
50 -import org.onosproject.net.flow.TrafficSelector;
51 -import org.onosproject.net.flow.TrafficTreatment;
52 -import org.onosproject.net.flow.criteria.Criteria;
53 -import org.onosproject.net.flowobjective.DefaultFilteringObjective;
54 -import org.onosproject.net.flowobjective.DefaultForwardingObjective;
55 -import org.onosproject.net.flowobjective.FilteringObjective;
56 -import org.onosproject.net.flowobjective.FlowObjectiveService;
57 -import org.onosproject.net.flowobjective.ForwardingObjective;
58 -import org.onosproject.net.flowobjective.Objective;
59 -import org.onosproject.net.flowobjective.ObjectiveContext;
60 -import org.onosproject.net.flowobjective.ObjectiveError;
61 -import org.onosproject.olt.AccessDeviceEvent;
62 -import org.onosproject.olt.AccessDeviceListener;
63 -import org.onosproject.olt.AccessDeviceService;
64 -import org.onosproject.store.serializers.KryoNamespaces;
65 -import org.onosproject.store.service.Serializer;
66 -import org.onosproject.store.service.StorageService;
67 -import org.osgi.service.component.ComponentContext;
68 -import org.slf4j.Logger;
69 -
70 -import java.util.Collection;
71 -import java.util.Dictionary;
72 -import java.util.List;
73 -import java.util.Map;
74 -import java.util.Optional;
75 -import java.util.Properties;
76 -import java.util.concurrent.CompletableFuture;
77 -import java.util.concurrent.ConcurrentHashMap;
78 -import java.util.concurrent.ExecutorService;
79 -import java.util.concurrent.Executors;
80 -
81 -import static com.google.common.base.Strings.isNullOrEmpty;
82 -import static org.onlab.util.Tools.get;
83 -import static org.onlab.util.Tools.groupedThreads;
84 -import static org.slf4j.LoggerFactory.getLogger;
85 -
86 -/**
87 - * Provisions rules on access devices.
88 - */
89 -@Service
90 -@Component(immediate = true)
91 -public class Olt
92 - extends AbstractListenerManager<AccessDeviceEvent, AccessDeviceListener>
93 - implements AccessDeviceService {
94 -
95 - private static final short DEFAULT_VLAN = 0;
96 - private static final String SUBSCRIBERS = "existing-subscribers";
97 -
98 - private final Logger log = getLogger(getClass());
99 -
100 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 - protected FlowObjectiveService flowObjectiveService;
102 -
103 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 - protected MastershipService mastershipService;
105 -
106 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 - protected DeviceService deviceService;
108 -
109 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 - protected CoreService coreService;
111 -
112 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 - protected NetworkConfigRegistry networkConfig;
114 -
115 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 - protected ComponentConfigService componentConfigService;
117 -
118 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 - protected StorageService storageService;
120 -
121 - @Property(name = "defaultVlan", intValue = DEFAULT_VLAN,
122 - label = "Default VLAN RG<->ONU traffic")
123 - private int defaultVlan = DEFAULT_VLAN;
124 -
125 - private final DeviceListener deviceListener = new InternalDeviceListener();
126 -
127 - private ApplicationId appId;
128 -
129 - private ExecutorService oltInstallers = Executors.newFixedThreadPool(4,
130 - groupedThreads("onos/olt-service",
131 - "olt-installer-%d"));
132 -
133 - private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
134 -
135 - private Map<ConnectPoint, VlanId> subscribers;
136 -
137 - private InternalNetworkConfigListener configListener =
138 - new InternalNetworkConfigListener();
139 - private static final Class<AccessDeviceConfig> CONFIG_CLASS =
140 - AccessDeviceConfig.class;
141 -
142 - private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
143 - new ConfigFactory<DeviceId, AccessDeviceConfig>(
144 - SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
145 - @Override
146 - public AccessDeviceConfig createConfig() {
147 - return new AccessDeviceConfig();
148 - }
149 - };
150 -
151 -
152 - @Activate
153 - public void activate(ComponentContext context) {
154 - modified(context);
155 - appId = coreService.registerApplication("org.onosproject.olt");
156 - componentConfigService.registerProperties(getClass());
157 -
158 - eventDispatcher.addSink(AccessDeviceEvent.class, listenerRegistry);
159 -
160 - networkConfig.registerConfigFactory(configFactory);
161 - networkConfig.addListener(configListener);
162 -
163 -
164 - networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
165 - subject -> {
166 - AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
167 - if (config != null) {
168 - AccessDeviceData data = config.getOlt();
169 - oltData.put(data.deviceId(), data);
170 - }
171 - }
172 - );
173 -
174 - oltData.keySet().stream()
175 - .flatMap(did -> deviceService.getPorts(did).stream())
176 - .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
177 - .filter(p -> p.isEnabled())
178 - .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
179 - p.number(), true));
180 -
181 - subscribers = storageService.<ConnectPoint, VlanId>consistentMapBuilder()
182 - .withName(SUBSCRIBERS)
183 - .withSerializer(Serializer.using(KryoNamespaces.API))
184 - .build().asJavaMap();
185 -
186 - deviceService.addListener(deviceListener);
187 -
188 - log.info("Started with Application ID {}", appId.id());
189 - }
190 -
191 - @Deactivate
192 - public void deactivate() {
193 - componentConfigService.unregisterProperties(getClass(), false);
194 - deviceService.removeListener(deviceListener);
195 - networkConfig.removeListener(configListener);
196 - networkConfig.unregisterConfigFactory(configFactory);
197 - log.info("Stopped");
198 - }
199 -
200 - @Modified
201 - public void modified(ComponentContext context) {
202 - Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
203 -
204 - try {
205 - String s = get(properties, "defaultVlan");
206 - defaultVlan = isNullOrEmpty(s) ? DEFAULT_VLAN : Integer.parseInt(s.trim());
207 - } catch (Exception e) {
208 - defaultVlan = DEFAULT_VLAN;
209 - }
210 - }
211 -
212 - @Override
213 - public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
214 - AccessDeviceData olt = oltData.get(port.deviceId());
215 -
216 - if (olt == null) {
217 - log.warn("No data found for OLT device {}", port.deviceId());
218 - return;
219 - }
220 -
221 - provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
222 - olt.defaultVlan());
223 - }
224 -
225 - @Override
226 - public void removeSubscriber(ConnectPoint port) {
227 - AccessDeviceData olt = oltData.get(port.deviceId());
228 -
229 - if (olt == null) {
230 - log.warn("No data found for OLT device {}", port.deviceId());
231 - return;
232 - }
233 -
234 - VlanId subscriberVlan = subscribers.remove(port);
235 -
236 - if (subscriberVlan == null) {
237 - log.warn("Unknown subscriber at location {}", port);
238 - return;
239 - }
240 -
241 - unprovisionSubscriber(olt.deviceId(), olt.uplink(), port.port(), subscriberVlan,
242 - olt.vlan(), olt.defaultVlan());
243 -
244 - }
245 -
246 - @Override
247 - public Collection<Map.Entry<ConnectPoint, VlanId>> getSubscribers() {
248 - return subscribers.entrySet();
249 - }
250 -
251 - @Override
252 - public Map<DeviceId, AccessDeviceData> fetchOlts() {
253 - return Maps.newHashMap(oltData);
254 - }
255 -
256 - private void unprovisionSubscriber(DeviceId deviceId, PortNumber uplink,
257 - PortNumber subscriberPort, VlanId subscriberVlan,
258 - VlanId deviceVlan, Optional<VlanId> defaultVlan) {
259 -
260 - CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
261 - CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
262 -
263 - ForwardingObjective.Builder upFwd = upBuilder(uplink, subscriberPort,
264 - subscriberVlan, deviceVlan,
265 - defaultVlan);
266 - ForwardingObjective.Builder downFwd = downBuilder(uplink, subscriberPort,
267 - subscriberVlan, deviceVlan,
268 - defaultVlan);
269 -
270 -
271 - flowObjectiveService.forward(deviceId, upFwd.remove(new ObjectiveContext() {
272 - @Override
273 - public void onSuccess(Objective objective) {
274 - upFuture.complete(null);
275 - }
276 -
277 - @Override
278 - public void onError(Objective objective, ObjectiveError error) {
279 - upFuture.complete(error);
280 - }
281 - }));
282 -
283 - flowObjectiveService.forward(deviceId, downFwd.remove(new ObjectiveContext() {
284 - @Override
285 - public void onSuccess(Objective objective) {
286 - downFuture.complete(null);
287 - }
288 -
289 - @Override
290 - public void onError(Objective objective, ObjectiveError error) {
291 - downFuture.complete(error);
292 - }
293 - }));
294 -
295 - upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
296 - if (upStatus == null && downStatus == null) {
297 - post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_UNREGISTERED,
298 - deviceId,
299 - deviceVlan,
300 - subscriberVlan));
301 - } else if (downStatus != null) {
302 - log.error("Subscriber with vlan {} on device {} " +
303 - "on port {} failed downstream uninstallation: {}",
304 - subscriberVlan, deviceId, subscriberPort, downStatus);
305 - } else if (upStatus != null) {
306 - log.error("Subscriber with vlan {} on device {} " +
307 - "on port {} failed upstream uninstallation: {}",
308 - subscriberVlan, deviceId, subscriberPort, upStatus);
309 - }
310 - }, oltInstallers);
311 -
312 - }
313 -
314 - private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
315 - PortNumber subscriberPort,
316 - VlanId subscriberVlan, VlanId deviceVlan,
317 - Optional<VlanId> defaultVlan) {
318 -
319 - CompletableFuture<ObjectiveError> downFuture = new CompletableFuture();
320 - CompletableFuture<ObjectiveError> upFuture = new CompletableFuture();
321 -
322 - ForwardingObjective.Builder upFwd = upBuilder(uplinkPort, subscriberPort,
323 - subscriberVlan, deviceVlan,
324 - defaultVlan);
325 -
326 -
327 - ForwardingObjective.Builder downFwd = downBuilder(uplinkPort, subscriberPort,
328 - subscriberVlan, deviceVlan,
329 - defaultVlan);
330 -
331 - ConnectPoint cp = new ConnectPoint(deviceId, subscriberPort);
332 - subscribers.put(cp, subscriberVlan);
333 -
334 - flowObjectiveService.forward(deviceId, upFwd.add(new ObjectiveContext() {
335 - @Override
336 - public void onSuccess(Objective objective) {
337 - upFuture.complete(null);
338 - }
339 -
340 - @Override
341 - public void onError(Objective objective, ObjectiveError error) {
342 - upFuture.complete(error);
343 - }
344 - }));
345 -
346 - flowObjectiveService.forward(deviceId, downFwd.add(new ObjectiveContext() {
347 - @Override
348 - public void onSuccess(Objective objective) {
349 - downFuture.complete(null);
350 - }
351 -
352 - @Override
353 - public void onError(Objective objective, ObjectiveError error) {
354 - downFuture.complete(error);
355 - }
356 - }));
357 -
358 - upFuture.thenAcceptBothAsync(downFuture, (upStatus, downStatus) -> {
359 - if (upStatus == null && downStatus == null) {
360 - post(new AccessDeviceEvent(AccessDeviceEvent.Type.SUBSCRIBER_REGISTERED,
361 - deviceId,
362 - deviceVlan,
363 - subscriberVlan));
364 -
365 - } else if (downStatus != null) {
366 - log.error("Subscriber with vlan {} on device {} " +
367 - "on port {} failed downstream installation: {}",
368 - subscriberVlan, deviceId, subscriberPort, downStatus);
369 - } else if (upStatus != null) {
370 - log.error("Subscriber with vlan {} on device {} " +
371 - "on port {} failed upstream installation: {}",
372 - subscriberVlan, deviceId, subscriberPort, upStatus);
373 - }
374 - }, oltInstallers);
375 -
376 - }
377 -
378 - private ForwardingObjective.Builder downBuilder(PortNumber uplinkPort,
379 - PortNumber subscriberPort,
380 - VlanId subscriberVlan,
381 - VlanId deviceVlan,
382 - Optional<VlanId> defaultVlan) {
383 - TrafficSelector downstream = DefaultTrafficSelector.builder()
384 - .matchVlanId(deviceVlan)
385 - .matchInPort(uplinkPort)
386 - .matchInnerVlanId(subscriberVlan)
387 - .build();
388 -
389 - TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
390 - .popVlan()
391 - .setVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
392 - .setOutput(subscriberPort)
393 - .build();
394 -
395 - return DefaultForwardingObjective.builder()
396 - .withFlag(ForwardingObjective.Flag.VERSATILE)
397 - .withPriority(1000)
398 - .makePermanent()
399 - .withSelector(downstream)
400 - .fromApp(appId)
401 - .withTreatment(downstreamTreatment);
402 - }
403 -
404 - private ForwardingObjective.Builder upBuilder(PortNumber uplinkPort,
405 - PortNumber subscriberPort,
406 - VlanId subscriberVlan,
407 - VlanId deviceVlan,
408 - Optional<VlanId> defaultVlan) {
409 - TrafficSelector upstream = DefaultTrafficSelector.builder()
410 - .matchVlanId(defaultVlan.orElse(VlanId.vlanId((short) this.defaultVlan)))
411 - .matchInPort(subscriberPort)
412 - .build();
413 -
414 -
415 - TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
416 - .pushVlan()
417 - .setVlanId(subscriberVlan)
418 - .pushVlan()
419 - .setVlanId(deviceVlan)
420 - .setOutput(uplinkPort)
421 - .build();
422 -
423 - return DefaultForwardingObjective.builder()
424 - .withFlag(ForwardingObjective.Flag.VERSATILE)
425 - .withPriority(1000)
426 - .makePermanent()
427 - .withSelector(upstream)
428 - .fromApp(appId)
429 - .withTreatment(upstreamTreatment);
430 - }
431 -
432 - private void processFilteringObjectives(DeviceId devId, PortNumber port, boolean install) {
433 - if (!mastershipService.isLocalMaster(devId)) {
434 - return;
435 - }
436 - DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
437 -
438 - FilteringObjective eapol = (install ? builder.permit() : builder.deny())
439 - .withKey(Criteria.matchInPort(port))
440 - .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
441 - .withMeta(DefaultTrafficTreatment.builder()
442 - .setOutput(PortNumber.CONTROLLER).build())
443 - .fromApp(appId)
444 - .withPriority(1000)
445 - .add(new ObjectiveContext() {
446 - @Override
447 - public void onSuccess(Objective objective) {
448 - log.info("Eapol filter for {} on {} installed.",
449 - devId, port);
450 - }
451 -
452 - @Override
453 - public void onError(Objective objective, ObjectiveError error) {
454 - log.info("Eapol filter for {} on {} failed because {}",
455 - devId, port, error);
456 - }
457 - });
458 -
459 - flowObjectiveService.filter(devId, eapol);
460 -
461 - }
462 -
463 - private class InternalDeviceListener implements DeviceListener {
464 - @Override
465 - public void event(DeviceEvent event) {
466 - DeviceId devId = event.subject().id();
467 - if (!oltData.containsKey(devId)) {
468 - return;
469 - }
470 - switch (event.type()) {
471 - //TODO: Port handling and bookkeeping should be improved once
472 - // olt firmware handles correct behaviour.
473 - case PORT_ADDED:
474 - if (!oltData.get(devId).uplink().equals(event.port().number()) &&
475 - event.port().isEnabled()) {
476 - processFilteringObjectives(devId, event.port().number(), true);
477 - }
478 - break;
479 - case PORT_REMOVED:
480 - AccessDeviceData olt = oltData.get(devId);
481 - VlanId vlan = subscribers.get(new ConnectPoint(devId,
482 - event.port().number()));
483 - unprovisionSubscriber(devId, olt.uplink(),
484 - event.port().number(),
485 - vlan, olt.vlan(), olt.defaultVlan());
486 - if (!oltData.get(devId).uplink().equals(event.port().number()) &&
487 - event.port().isEnabled()) {
488 - processFilteringObjectives(devId, event.port().number(), false);
489 - }
490 - break;
491 - case PORT_UPDATED:
492 - if (oltData.get(devId).uplink().equals(event.port().number())) {
493 - break;
494 - }
495 - if (event.port().isEnabled()) {
496 - processFilteringObjectives(devId, event.port().number(), true);
497 - } else {
498 - processFilteringObjectives(devId, event.port().number(), false);
499 - }
500 - break;
501 - case DEVICE_ADDED:
502 - post(new AccessDeviceEvent(
503 - AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
504 - null, null));
505 - provisionDefaultFlows(devId);
506 - break;
507 - case DEVICE_REMOVED:
508 - post(new AccessDeviceEvent(
509 - AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
510 - null, null));
511 - break;
512 - case DEVICE_AVAILABILITY_CHANGED:
513 - if (deviceService.isAvailable(devId)) {
514 - post(new AccessDeviceEvent(
515 - AccessDeviceEvent.Type.DEVICE_CONNECTED, devId,
516 - null, null));
517 - } else {
518 - post(new AccessDeviceEvent(
519 - AccessDeviceEvent.Type.DEVICE_DISCONNECTED, devId,
520 - null, null));
521 - }
522 - break;
523 - case DEVICE_UPDATED:
524 - case DEVICE_SUSPENDED:
525 - case PORT_STATS_UPDATED:
526 - default:
527 - return;
528 - }
529 - }
530 - }
531 -
532 - private class InternalNetworkConfigListener implements NetworkConfigListener {
533 - @Override
534 - public void event(NetworkConfigEvent event) {
535 - switch (event.type()) {
536 -
537 - case CONFIG_ADDED:
538 - case CONFIG_UPDATED:
539 -
540 - AccessDeviceConfig config =
541 - networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
542 - if (config != null) {
543 - oltData.put(config.getOlt().deviceId(), config.getOlt());
544 - provisionDefaultFlows((DeviceId) event.subject());
545 - }
546 -
547 - break;
548 - case CONFIG_REGISTERED:
549 - case CONFIG_UNREGISTERED:
550 - break;
551 - case CONFIG_REMOVED:
552 - oltData.remove(event.subject());
553 - default:
554 - break;
555 - }
556 - }
557 -
558 - @Override
559 - public boolean isRelevant(NetworkConfigEvent event) {
560 - return event.configClass().equals(CONFIG_CLASS);
561 - }
562 - }
563 -
564 - private void provisionDefaultFlows(DeviceId deviceId) {
565 - if (!mastershipService.isLocalMaster(deviceId)) {
566 - return;
567 - }
568 - List<Port> ports = deviceService.getPorts(deviceId);
569 -
570 - ports.stream()
571 - .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
572 - .filter(p -> p.isEnabled())
573 - .forEach(p -> processFilteringObjectives((DeviceId) p.element().id(),
574 - p.number(), true));
575 -
576 - }
577 -
578 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * OLT application handling PMC OLT hardware.
19 - */
20 -package org.onosproject.olt.impl;
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.olt.rest;
17 -
18 -import javax.ws.rs.DELETE;
19 -import javax.ws.rs.POST;
20 -import javax.ws.rs.Path;
21 -import javax.ws.rs.PathParam;
22 -import javax.ws.rs.Produces;
23 -import javax.ws.rs.core.MediaType;
24 -import javax.ws.rs.core.Response;
25 -
26 -import org.onlab.packet.VlanId;
27 -import org.onosproject.net.ConnectPoint;
28 -import org.onosproject.net.DeviceId;
29 -import org.onosproject.net.PortNumber;
30 -import org.onosproject.olt.AccessDeviceService;
31 -import org.onosproject.rest.AbstractWebResource;
32 -
33 -/**
34 - * OLT REST APIs.
35 - */
36 -
37 -@Path("oltapp")
38 -public class OltWebResource extends AbstractWebResource {
39 -
40 - /**
41 - * Provision a subscriber.
42 - *
43 - * @param device device id
44 - * @param port port number
45 - * @param vlan vlan id
46 - * @return 200 OK
47 - */
48 - @POST
49 - @Produces(MediaType.APPLICATION_JSON)
50 - @Path("{device}/{port}/{vlan}")
51 - public Response provisionSubscriber(
52 - @PathParam("device")String device,
53 - @PathParam("port")long port,
54 - @PathParam("vlan")short vlan) {
55 - AccessDeviceService service = get(AccessDeviceService.class);
56 - DeviceId deviceId = DeviceId.deviceId(device);
57 - PortNumber portNumber = PortNumber.portNumber(port);
58 - VlanId vlanId = VlanId.vlanId(vlan);
59 - ConnectPoint connectPoint = new ConnectPoint(deviceId, portNumber);
60 - service.provisionSubscriber(connectPoint, vlanId);
61 - return ok("").build();
62 - }
63 -
64 - /**
65 - * Remove the provisioning for a subscriber.
66 - *
67 - * @param device device id
68 - * @param port port number
69 - * @return 204 NO CONTENT
70 - */
71 - @DELETE
72 - @Path("{device}/{port}")
73 - public Response removeSubscriber(
74 - @PathParam("device")String device,
75 - @PathParam("port")long port) {
76 - AccessDeviceService service = get(AccessDeviceService.class);
77 - DeviceId deviceId = DeviceId.deviceId(device);
78 - PortNumber portNumber = PortNumber.portNumber(port);
79 - ConnectPoint connectPoint = new ConnectPoint(deviceId, portNumber);
80 - service.removeSubscriber(connectPoint);
81 - return Response.noContent().build();
82 - }
83 -}
1 -/*
2 - * Copyright 2016-present Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -
17 -/**
18 - * REST APIs for the OLT application.
19 - */
20 -package org.onosproject.olt.rest;
1 -<!--
2 - ~ Copyright 2016-present Open Networking Laboratory
3 - ~
4 - ~ Licensed under the Apache License, Version 2.0 (the "License");
5 - ~ you may not use this file except in compliance with the License.
6 - ~ You may obtain a copy of the License at
7 - ~
8 - ~ http://www.apache.org/licenses/LICENSE-2.0
9 - ~
10 - ~ Unless required by applicable law or agreed to in writing, software
11 - ~ distributed under the License is distributed on an "AS IS" BASIS,
12 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - ~ See the License for the specific language governing permissions and
14 - ~ limitations under the License.
15 - -->
16 -<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
17 -
18 - <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
19 - <command>
20 - <action class="org.onosproject.olt.cli.SubscriberAddCommand"/>
21 - <completers>
22 - <ref component-id="deviceIdCompleter"/>
23 - <null/>
24 - </completers>
25 - </command>
26 - <command>
27 - <action class="org.onosproject.olt.cli.SubscriberRemoveCommand"/>
28 - <completers>
29 - <ref component-id="deviceIdCompleter"/>
30 - <null/>
31 - </completers>
32 - </command>
33 - <command>
34 - <action class="org.onosproject.olt.cli.ShowOltCommand"/>
35 - <completers>
36 - <ref component-id="deviceIdCompleter"/>
37 - <null/>
38 - </completers>
39 - </command>
40 - <command>
41 - <action class="org.onosproject.olt.cli.ShowSubscribersCommand"/>
42 - </command>
43 - </command-bundle>
44 -
45 - <bean id="deviceIdCompleter" class="org.onosproject.cli.net.DeviceIdCompleter"/>
46 -</blueprint>
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2016-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
18 - xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
19 - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
20 - id="ONOS" version="2.5">
21 - <display-name>OLT REST API v1.0</display-name>
22 -
23 - <servlet>
24 - <servlet-name>JAX-RS Service</servlet-name>
25 - <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
26 - <init-param>
27 - <param-name>jersey.config.server.provider.classnames</param-name>
28 - <param-value>
29 - org.onosproject.olt.rest.OltWebResource
30 - </param-value>
31 - </init-param>
32 - <load-on-startup>1</load-on-startup>
33 - </servlet>
34 -
35 - <servlet-mapping>
36 - <servlet-name>JAX-RS Service</servlet-name>
37 - <url-pattern>/*</url-pattern>
38 - </servlet-mapping>
39 -</web-app>
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2015-present Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20 - <parent>
21 - <groupId>org.onosproject</groupId>
22 - <artifactId>onos-apps</artifactId>
23 - <version>1.6.0-SNAPSHOT</version>
24 - <relativePath>../pom.xml</relativePath>
25 - </parent>
26 - <modelVersion>4.0.0</modelVersion>
27 -
28 - <artifactId>onos-olt</artifactId>
29 -
30 - <packaging>pom</packaging>
31 - <description>OLT application for CORD</description>
32 -
33 - <modules>
34 - <module>api</module>
35 - <module>app</module>
36 - </modules>
37 -
38 -</project>
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
29 <description>ONOS sample applications</description> 29 <description>ONOS sample applications</description>
30 30
31 <modules> 31 <modules>
32 - <module>aaa</module>
33 <module>acl</module> 32 <module>acl</module>
34 <module>faultmanagement</module> 33 <module>faultmanagement</module>
35 <module>fwd</module> 34 <module>fwd</module>
...@@ -51,14 +50,11 @@ ...@@ -51,14 +50,11 @@
51 <module>pcep-api</module> 50 <module>pcep-api</module>
52 <module>iptopology-api</module> 51 <module>iptopology-api</module>
53 <module>pce</module> 52 <module>pce</module>
54 - <module>olt</module>
55 <module>cip</module> 53 <module>cip</module>
56 <module>flowanalyzer</module> 54 <module>flowanalyzer</module>
57 <module>vtn</module> 55 <module>vtn</module>
58 <module>dhcp</module> 56 <module>dhcp</module>
59 - <module>cordvtn</module>
60 <module>mfwd</module> 57 <module>mfwd</module>
61 - <module>igmp</module>
62 <module>pim</module> 58 <module>pim</module>
63 <module>mlb</module> 59 <module>mlb</module>
64 <module>pathpainter</module> 60 <module>pathpainter</module>
...@@ -66,7 +62,6 @@ ...@@ -66,7 +62,6 @@
66 <module>cpman</module> 62 <module>cpman</module>
67 <module>events</module> 63 <module>events</module>
68 <module>vrouter</module> 64 <module>vrouter</module>
69 - <module>cordmcast</module>
70 <module>vpls</module> 65 <module>vpls</module>
71 <module>openstacknode</module> 66 <module>openstacknode</module>
72 <module>openstacknetworking</module> 67 <module>openstacknetworking</module>
...@@ -75,7 +70,6 @@ ...@@ -75,7 +70,6 @@
75 <module>gangliametrics</module> 70 <module>gangliametrics</module>
76 <module>graphitemetrics</module> 71 <module>graphitemetrics</module>
77 <module>xosclient</module> 72 <module>xosclient</module>
78 - <module>cordconfig</module>
79 <module>scalablegateway</module> 73 <module>scalablegateway</module>
80 </modules> 74 </modules>
81 75
......
...@@ -40,16 +40,12 @@ APPS = [ ...@@ -40,16 +40,12 @@ APPS = [
40 # Apps 40 # Apps
41 '//apps/dhcp:onos-apps-dhcp-oar', 41 '//apps/dhcp:onos-apps-dhcp-oar',
42 '//apps/fwd:onos-apps-fwd-oar', 42 '//apps/fwd:onos-apps-fwd-oar',
43 - '//apps/aaa:onos-apps-aaa-oar',
44 '//apps/acl:onos-apps-acl-oar', 43 '//apps/acl:onos-apps-acl-oar',
45 '//apps/bgprouter:onos-apps-bgprouter-oar', 44 '//apps/bgprouter:onos-apps-bgprouter-oar',
46 '//apps/proxyarp:onos-apps-proxyarp-oar', 45 '//apps/proxyarp:onos-apps-proxyarp-oar',
47 '//apps/segmentrouting:onos-apps-segmentrouting-oar', 46 '//apps/segmentrouting:onos-apps-segmentrouting-oar',
48 '//apps/gangliametrics:onos-apps-gangliametrics-oar', 47 '//apps/gangliametrics:onos-apps-gangliametrics-oar',
49 '//apps/graphitemetrics:onos-apps-graphitemetrics-oar', 48 '//apps/graphitemetrics:onos-apps-graphitemetrics-oar',
50 - '//apps/igmp:onos-apps-igmp-oar',
51 - '//apps/cordmcast:onos-apps-cordmcast-oar',
52 - '//apps/olt:onos-apps-olt-oar',
53 '//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar', 49 '//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar',
54 '//apps/metrics:onos-apps-metrics-oar', 50 '//apps/metrics:onos-apps-metrics-oar',
55 '//apps/mfwd:onos-apps-mfwd-oar', 51 '//apps/mfwd:onos-apps-mfwd-oar',
...@@ -66,7 +62,6 @@ APPS = [ ...@@ -66,7 +62,6 @@ APPS = [
66 '//apps/reactive-routing:onos-apps-reactive-routing-oar', 62 '//apps/reactive-routing:onos-apps-reactive-routing-oar',
67 '//apps/sdnip:onos-apps-sdnip-oar', 63 '//apps/sdnip:onos-apps-sdnip-oar',
68 '//apps/virtualbng:onos-apps-virtualbng-oar', 64 '//apps/virtualbng:onos-apps-virtualbng-oar',
69 - '//apps/cordvtn:onos-apps-cordvtn-oar',
70 '//apps/vpls:onos-apps-vpls-oar', 65 '//apps/vpls:onos-apps-vpls-oar',
71 '//apps/vrouter:onos-apps-vrouter-oar', 66 '//apps/vrouter:onos-apps-vrouter-oar',
72 '//apps/vtn:onos-apps-vtn-oar', 67 '//apps/vtn:onos-apps-vtn-oar',
......