ONOS-5449 Implemented skeleton of OFAgent application
Change-Id: Ie6c719872549a004471e466a43a2b531bc48b231
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFAgent.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFAgent.java
new file mode 100644
index 0000000..b44f48e
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFAgent.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.api;
+
+import io.netty.channel.nio.NioEventLoopGroup;
+import org.onosproject.incubator.net.virtual.NetworkId;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Representation of an OF agent, which brokers virtual devices and external
+ * controllers by handling OpenFlow connections and messages between them.
+ */
+public interface OFAgent {
+
+ /**
+ * Returns the identifier of the virtual network that this agent cares for.
+ *
+ * @return id of the virtual network
+ */
+ NetworkId networkId();
+
+ /**
+ * Returns the external OpenFlow controllers of the virtual network.
+ *
+ * @return set of openflow controllers
+ */
+ Set<OFController> controllers();
+
+ /**
+ * Starts the OpenFlow agent.
+ */
+ void start();
+
+ /**
+ * Stops the OpenFlow agent.
+ */
+ void stop();
+
+ /**
+ * Builder of OF agent entities.
+ */
+ interface Builder {
+
+ /**
+ * Returns new OF agent.
+ *
+ * @return of agent
+ */
+ OFAgent build();
+
+ /**
+ * Returns OF agent builder with the supplied network ID.
+ *
+ * @param networkId id of the virtual network
+ * @return of agent builder
+ */
+ Builder networkId(NetworkId networkId);
+
+ /**
+ * Returns OF agent builder with the supplied network services for the
+ * virtual network.
+ *
+ * @param services network services for the virtual network
+ * @return of agent builder
+ */
+ Builder services(Map<Class<?>, Object> services);
+
+ /**
+ * Returns OF agent builder with the supplied controllers.
+ *
+ * @param controllers set of openflow controllers
+ * @return of agent builder
+ */
+ Builder controllers(Set<OFController> controllers);
+
+ /**
+ * Returns OF agent builder with the supplied event executor.
+ *
+ * @param eventExecutor event executor
+ * @return of agent builder
+ */
+ Builder eventExecutor(ExecutorService eventExecutor);
+
+ /**
+ * Returns OF agent builder with the supplied IO work group.
+ *
+ * @param ioWorker io worker group
+ * @return of agent builder
+ */
+ Builder ioWorker(NioEventLoopGroup ioWorker);
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFAgentService.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFAgentService.java
new file mode 100644
index 0000000..c2b5e47
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFAgentService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.api;
+
+import org.onosproject.incubator.net.virtual.NetworkId;
+
+import java.util.Set;
+
+/**
+ * Service for administering OF agents for a virtual network.
+ */
+public interface OFAgentService {
+
+ /**
+ * Returns the OpenFlow agent list.
+ *
+ * @return set of openflow agents
+ */
+ Set<OFAgent> agents();
+
+ /**
+ * Creates an OpenFlow agent for a given virtual network with given controllers.
+ *
+ * @param networkId id of the virtual network
+ * @param controllers list of controllers
+ */
+ void createAgent(NetworkId networkId, OFController... controllers);
+
+ /**
+ * Removes the OpenFlow agent for the given virtual network.
+ *
+ * @param networkId virtual network identifier
+ */
+ void removeAgent(NetworkId networkId);
+
+ /**
+ * Starts the agent for the given network.
+ *
+ * @param networkId virtual network identifier
+ */
+ void startAgent(NetworkId networkId);
+
+ /**
+ * Stops the agent for the given network.
+ *
+ * @param networkId virtual network identifier
+ */
+ void stopAgent(NetworkId networkId);
+
+ /**
+ * Returns if the agent of the given network is active or not.
+ *
+ * @param networkId network id
+ * @return true if the agent is active
+ */
+ boolean isActive(NetworkId networkId);
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFController.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFController.java
new file mode 100644
index 0000000..fc81b03
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFController.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.api;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+
+/**
+ * Representation of an OF controller.
+ */
+public interface OFController {
+
+ /**
+ * Returns the IP address of the controller.
+ *
+ * @return ip address
+ */
+ IpAddress ip();
+
+ /**
+ * Returns the port number for OpenFlow channel connection.
+ *
+ * @return port number
+ */
+ TpPort port();
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFControllerRoleService.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFControllerRoleService.java
new file mode 100644
index 0000000..1a98618
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFControllerRoleService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.api;
+
+import io.netty.channel.Channel;
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+
+import java.util.Set;
+
+/**
+ * Service for administering the OF role of multiple controllers.
+ */
+public interface OFControllerRoleService {
+
+ /**
+ * Adds a new controller channel.
+ * EQUAL role is set by default.
+ *
+ * @param channel openflow channel
+ */
+ void addControllerChannel(Channel channel);
+
+ /**
+ * Deletes the controller channel.
+ *
+ * @param channel openflow channel
+ */
+ void deleteControllerChannel(Channel channel);
+
+ /**
+ * Returns controller channels.
+ *
+ * @return set of controller channels
+ */
+ Set<Channel> controllerChannels();
+
+ /**
+ * Sets a role of the controller with a given channel.
+ *
+ * @param channel openflow channel
+ * @param role role of the controller
+ */
+ void setRole(Channel channel, OFControllerRole role);
+
+ /**
+ * Returns a role of the controller with a given channel.
+ *
+ * @param channel openflow channel
+ * @return role of the controller
+ */
+ OFControllerRole role(Channel channel);
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitch.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitch.java
new file mode 100644
index 0000000..0252049
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitch.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.api;
+
+import org.onosproject.net.Device;
+
+/**
+ * Representation of virtual OpenFlow switch.
+ */
+public interface OFSwitch extends OFSwitchService, OFControllerRoleService {
+
+ /**
+ * Returns the device information.
+ *
+ * @return virtual device
+ */
+ Device device();
+
+ /**
+ * Returns the capabilities of the switch.
+ *
+ * @return capabilities
+ */
+ OFSwitchCapabilities capabilities();
+
+ /**
+ * Returns if the switch is connected to controllers or not.
+ *
+ * @return true if the switch is connected, false otherwise
+ */
+ boolean isConnected();
+
+ // TODO add builder interface
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchCapabilities.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchCapabilities.java
new file mode 100644
index 0000000..a385e8b
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchCapabilities.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.api;
+
+/**
+ * Representation of capabilities of a virtual OpenFlow switch.
+ */
+public interface OFSwitchCapabilities {
+
+ // TODO implement
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
new file mode 100644
index 0000000..de925b5
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/OFSwitchService.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.api;
+
+import io.netty.channel.Channel;
+import org.onosproject.net.Port;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.packet.InboundPacket;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+/**
+ * Service providing OpenFlow switch operations.
+ */
+public interface OFSwitchService {
+
+ /**
+ * Handles the switch starts.
+ */
+ void started();
+
+ /**
+ * Handles the switch stops.
+ */
+ void stopped();
+
+ /**
+ * Processes a new port of the switch.
+ * It sends out FEATURE_REPLY message to the controllers.
+ *
+ * @param port virtual port
+ */
+ void processPortAdded(Port port);
+
+ /**
+ * Processes port link down.
+ * It sends out PORT_STATUS asynchronous message to the controllers.
+ *
+ * @param port virtual port
+ */
+ void processPortDown(Port port);
+
+ /**
+ * Processes port link down.
+ * It sends out PORT_STATUS asynchronous message to the controllers.
+ *
+ * @param port virtual port
+ */
+ void processPortUp(Port port);
+
+ /**
+ * Processes flow removed.
+ * It sends out FLOW_REMOVED asynchronous message to the controllers.
+ *
+ * @param flowRule removed flow rule
+ */
+ void processFlowRemoved(FlowRule flowRule);
+
+ /**
+ * Processes packet in.
+ * It sends out PACKET_IN asynchronous message to the controllers.
+ *
+ * @param packet inbound packet
+ */
+ void processPacketIn(InboundPacket packet);
+
+ /**
+ * Processes commands from the controllers that modify the state of the switch.
+ * Possible message types include PACKET_OUT, FLOW_MOD, GROUP_MOD,
+ * PORT_MOD, TABLE_MOD. These types of messages can be denied based on a
+ * role of the request controller.
+ *
+ * @param channel received channel
+ * @param msg command message received
+ */
+ void processControllerCommand(Channel channel, OFMessage msg);
+
+ /**
+ * Processes a stats request from the controllers.
+ * Targeted message type is MULTIPART_REQUEST with FLOW, PORT, GROUP,
+ * GROUP_DESC subtypes.
+ *
+ * @param channel received channel
+ * @param msg stats request message received
+ */
+ void processStatsRequest(Channel channel, OFMessage msg);
+
+ /**
+ * Processes a role request from the controllers.
+ * Targeted message type is ROLE_REQUEST.
+ *
+ * @param channel received channel
+ * @param msg role request message received
+ */
+ void processRoleRequest(Channel channel, OFMessage msg);
+
+ /**
+ * Processes a features request from the controllers.
+ *
+ * @param channel received channel
+ * @param msg received features request
+ */
+ void processFeaturesRequest(Channel channel, OFMessage msg);
+
+ /**
+ * Processes LLDP packets from the controller.
+ *
+ * @param channel received channel
+ * @param msg packet out message with lldp
+ */
+ void processLldp(Channel channel, OFMessage msg);
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/api/package-info.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/package-info.java
new file mode 100644
index 0000000..128bc7a
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * OpenFlow agent API definitions.
+ */
+package org.onosproject.ofagent.api;
\ No newline at end of file
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFAgent.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFAgent.java
new file mode 100644
index 0000000..6a6ba06
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFAgent.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.channel.nio.NioEventLoopGroup;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.flow.FlowRuleEvent;
+import org.onosproject.net.flow.FlowRuleListener;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.ofagent.api.OFAgent;
+import org.onosproject.ofagent.api.OFController;
+import org.onosproject.ofagent.api.OFSwitch;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Implementation of OF agent.
+ */
+public final class DefaultOFAgent implements OFAgent {
+
+ private final NetworkId networkId;
+ private final Map<Class<?>, Object> services;
+ private final Set<OFController> controllers;
+ private final ExecutorService eventExecutor;
+ private final NioEventLoopGroup ioWorker;
+
+ private final ConcurrentHashMap<DeviceId, OFSwitch> switchMap = new ConcurrentHashMap<>();
+ private final DeviceListener deviceListener = new InternalDeviceListener();
+ private final FlowRuleListener flowRuleListener = new InternalFlowRuleListener();
+ private final InternalPacketProcessor packetProcessor = new InternalPacketProcessor();
+
+ private DefaultOFAgent(NetworkId networkId,
+ Map<Class<?>, Object> services,
+ Set<OFController> controllers,
+ ExecutorService eventExecutor,
+ NioEventLoopGroup ioWorker) {
+ this.networkId = networkId;
+ this.services = services;
+ this.controllers = controllers;
+ this.eventExecutor = eventExecutor;
+ this.ioWorker = ioWorker;
+ }
+
+ @Override
+ public NetworkId networkId() {
+ return null;
+ }
+
+ @Override
+ public Set<OFController> controllers() {
+ return null;
+ }
+
+ @Override
+ public void start() {
+ // TODO add listeners to the services
+ // TODO connect all virtual devices in this network to the controllers
+ }
+
+ @Override
+ public void stop() {
+ // TODO remove listeners from the services
+ // TODO disconnect all active connections
+ }
+
+ private void connect(OFSwitch ofSwitch, OFController controller) {
+ // TODO connect the switch to the controller
+ }
+
+ private void disconnect(OFSwitch ofSwitch, OFController controller) {
+ // TODO disconnect the controller from the ofSwitch
+ }
+
+ private class InternalFlowRuleListener implements FlowRuleListener {
+
+ @Override
+ public void event(FlowRuleEvent event) {
+ // TODO handle flow rule event
+ }
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ // TODO handle device event
+ // device detected: connect the device to controllers
+ // device removed: disconnect and remove the switch from the map
+ // device state available: connect the switch to the controllers
+ // device state unavailable: disconnect the switch from the controllers
+ // port added: send out features reply
+ // port status change
+ }
+ }
+
+ private class InternalPacketProcessor implements PacketProcessor {
+
+ @Override
+ public void process(PacketContext context) {
+ // TODO handle packet-in
+ }
+ }
+
+ // TODO implement builder
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
new file mode 100644
index 0000000..01068c9
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.channel.Channel;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.ofagent.api.OFSwitch;
+import org.onosproject.ofagent.api.OFSwitchCapabilities;
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.projectfloodlight.openflow.protocol.OFControllerRole.*;
+
+/**
+ * Implementation of OF switch.
+ */
+public final class DefaultOFSwitch implements OFSwitch {
+
+ private static final String ERR_CH_DUPLICATE = "Channel already exists: ";
+ private static final String ERR_CH_NOT_FOUND = "Channel not found: ";
+
+ private final Device device;
+ private final OFSwitchCapabilities capabilities;
+
+ private final ConcurrentHashMap<Channel, OFControllerRole> controllerRoleMap
+ = new ConcurrentHashMap<>();
+
+ private DefaultOFSwitch(Device device, OFSwitchCapabilities capabilities) {
+ this.device = device;
+ this.capabilities = capabilities;
+ }
+
+ // TODO add builder
+
+ @Override
+ public Device device() {
+ return null;
+ }
+
+ @Override
+ public OFSwitchCapabilities capabilities() {
+ return null;
+ }
+
+ @Override
+ public boolean isConnected() {
+ return false;
+ }
+
+ @Override
+ public void started() {
+ // TODO do some initial setups
+ }
+
+ @Override
+ public void stopped() {
+ // TODO implement
+ }
+
+ @Override
+ public void addControllerChannel(Channel channel) {
+ controllerRoleMap.compute(channel, (ch, existing) -> {
+ final String error = ERR_CH_DUPLICATE + channel.remoteAddress();
+ checkArgument(existing == null, error);
+ return ROLE_EQUAL;
+ });
+ }
+
+ @Override
+ public void deleteControllerChannel(Channel channel) {
+ if (controllerRoleMap.remove(channel) == null) {
+ final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
+ throw new IllegalStateException(error);
+ }
+ }
+
+ @Override
+ public void setRole(Channel channel, OFControllerRole role) {
+ controllerRoleMap.compute(channel, (ch, existing) -> {
+ final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
+ checkNotNull(existing, error);
+ return role;
+ });
+ }
+
+ @Override
+ public OFControllerRole role(Channel channel) {
+ OFControllerRole role = controllerRoleMap.get(channel);
+ if (role == null) {
+ final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
+ throw new IllegalStateException(error);
+ }
+ return role;
+ }
+
+ @Override
+ public Set<Channel> controllerChannels() {
+ return null;
+ }
+
+ @Override
+ public void processPortAdded(Port port) {
+ // TODO generate FEATURES_REPLY message and send it to the controller
+ }
+
+ @Override
+ public void processPortDown(Port port) {
+ // TODO generate PORT_STATUS message and send it to the controller
+ }
+
+ @Override
+ public void processPortUp(Port port) {
+ // TODO generate PORT_STATUS message and send it to the controller
+ }
+
+ @Override
+ public void processFlowRemoved(FlowRule flowRule) {
+ // TODO generate FLOW_REMOVED message and send it to the controller
+ }
+
+ @Override
+ public void processPacketIn(InboundPacket packet) {
+ // TODO generate PACKET_IN message and send it to the controller
+ }
+
+ @Override
+ public void processControllerCommand(Channel channel, OFMessage msg) {
+ // TODO process controller command
+ }
+
+ @Override
+ public void processStatsRequest(Channel channel, OFMessage msg) {
+ // TODO process request and send reply
+ }
+
+ @Override
+ public void processRoleRequest(Channel channel, OFMessage msg) {
+ // TODO process role request and send reply
+ }
+
+ @Override
+ public void processFeaturesRequest(Channel channel, OFMessage msg) {
+ // TODO process features request and send reply
+ }
+
+ @Override
+ public void processLldp(Channel channel, OFMessage msg) {
+ // TODO process lldp
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFAgentManager.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFAgentManager.java
new file mode 100644
index 0000000..3005f73
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFAgentManager.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.channel.nio.NioEventLoopGroup;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
+import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
+import org.onosproject.ofagent.api.OFAgent;
+import org.onosproject.ofagent.api.OFAgentService;
+import org.onosproject.ofagent.api.OFController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+
+import static org.onlab.util.BoundedThreadPool.newFixedThreadPool;
+import static org.onlab.util.Tools.groupedThreads;
+
+/**
+ * Implementation of OpenFlow agent service.
+ */
+@Component(immediate = true)
+@Service
+public class OFAgentManager implements OFAgentService {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ // TODO make it to be configurable with component config
+ private static final int NUM_OF_THREADS = 1;
+ private final ExecutorService eventExecutor = newFixedThreadPool(
+ NUM_OF_THREADS,
+ groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
+
+ // TODO change it to ConsistentMap and support multi-instance mode
+ private ConcurrentHashMap<NetworkId, OFAgent> agentMap = new ConcurrentHashMap<>();
+ private NioEventLoopGroup ioWorker;
+
+ @Activate
+ protected void activate() {
+ // TODO listen to the virtual network event
+ ioWorker = new NioEventLoopGroup();
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ ioWorker.shutdownGracefully();
+ eventExecutor.shutdown();
+ log.info("Stopped");
+ }
+
+ @Override
+ public Set<OFAgent> agents() {
+ // TODO return existing agents
+ return null;
+ }
+
+ @Override
+ public void createAgent(NetworkId networkId, OFController... controllers) {
+ // TODO create OFAgent instance with the given network ID, controllers
+ // TODO and device, flowRule, link, and packet service for the virtual network
+ // TODO start the OFAgent only if the virtual network state is active
+ }
+
+ @Override
+ public void removeAgent(NetworkId networkId) {
+ // TODO stop and remove the OFAgent for the network
+ }
+
+ @Override
+ public void startAgent(NetworkId networkId) {
+ // TODO starts the agent for the network
+ }
+
+ @Override
+ public void stopAgent(NetworkId networkId) {
+ // TODO stops the agent for the network
+ }
+
+ @Override
+ public boolean isActive(NetworkId networkId) {
+ // TODO manage the OF agent status
+ return false;
+ }
+
+ private class InternalVirtualNetworkListener implements VirtualNetworkListener {
+
+ @Override
+ public void event(VirtualNetworkEvent event) {
+ // TODO handle virtual network start and stop
+ }
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelHandler.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelHandler.java
new file mode 100644
index 0000000..b077af4
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelHandler.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelDuplexHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.util.ReferenceCountUtil;
+import org.onosproject.ofagent.api.OFSwitch;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of OpenFlow channel handler.
+ * It processes OpenFlow message according to the channel state.
+ */
+public final class OFChannelHandler extends ChannelDuplexHandler {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private final OFSwitch ofSwitch;
+
+ private Channel channel;
+ private ChannelState state;
+
+ private enum ChannelState {
+
+ INIT {
+ @Override
+ void processOFMessage(final OFChannelHandler handler,
+ final OFMessage msg) {
+ // TODO implement
+ }
+ },
+ WAIT_HELLO {
+ @Override
+ void processOFMessage(final OFChannelHandler handler,
+ final OFMessage msg) {
+ // TODO implement
+ }
+ },
+ WAIT_FEATURE_REQUEST {
+ @Override
+ void processOFMessage(final OFChannelHandler handler,
+ final OFMessage msg) {
+ // TODO implement
+ }
+ },
+ ESTABLISHED {
+ @Override
+ void processOFMessage(final OFChannelHandler handler,
+ final OFMessage msg) {
+ // TODO implement
+ // TODO add this channel to ofSwitch role service
+ }
+ };
+
+ abstract void processOFMessage(final OFChannelHandler handler,
+ final OFMessage msg);
+ }
+
+ /**
+ * Default constructor.
+ *
+ * @param ofSwitch openflow switch that owns this channel
+ */
+ public OFChannelHandler(OFSwitch ofSwitch) {
+ this.ofSwitch = ofSwitch;
+ }
+
+ @Override
+ public void channelActive(ChannelHandlerContext ctx) throws Exception {
+ super.channelActive(ctx);
+ this.channel = ctx.channel();
+ }
+
+ @Override
+ public void channelRead(ChannelHandlerContext ctx, Object msg)
+ throws Exception {
+ try {
+ OFMessage ofMsg = (OFMessage) msg;
+ // TODO process OF message
+
+ } finally {
+ ReferenceCountUtil.release(msg);
+ }
+ }
+
+ @Override
+ public void channelReadComplete(ChannelHandlerContext ctx)
+ throws Exception {
+ ctx.flush();
+ }
+
+ @Override
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+ ctx.close();
+ }
+
+ private void setState(ChannelState state) {
+ this.state = state;
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelInitializer.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelInitializer.java
new file mode 100644
index 0000000..a3be413
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelInitializer.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.SocketChannel;
+import org.onosproject.ofagent.api.OFSwitch;
+
+/**
+ * Implementation of OpenFlow channel initializer.
+ */
+public final class OFChannelInitializer extends ChannelInitializer<SocketChannel> {
+
+ private final OFSwitch ofSwitch;
+
+ /**
+ * Default constructor.
+ *
+ * @param ofSwitch openflow switch that owns this channel
+ */
+ public OFChannelInitializer(OFSwitch ofSwitch) {
+ this.ofSwitch = ofSwitch;
+ }
+
+ @Override
+ protected void initChannel(SocketChannel ch) throws Exception {
+
+ // TODO configure OF channel pipeline
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFConnectionHandler.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFConnectionHandler.java
new file mode 100644
index 0000000..27a6bc5
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFConnectionHandler.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.nio.NioEventLoopGroup;
+import org.onosproject.ofagent.api.OFController;
+import org.onosproject.ofagent.api.OFSwitch;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Implementation of OpenFlow connection handler.
+ * It retries a connection for a certain amount of time and then give up.
+ */
+public final class OFConnectionHandler implements ChannelFutureListener {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private static final int MAX_RETRY = 10;
+
+ private final AtomicInteger retryCount = new AtomicInteger();
+ private final OFSwitch ofSwitch;
+ private final OFController controller;
+ private final NioEventLoopGroup workGroup;
+
+ /**
+ * Default constructor.
+ *
+ * @param ofSwitch openflow switch that initiates this connection
+ * @param controller controller to connect
+ * @param workGroup work group for connection
+ */
+ public OFConnectionHandler(OFSwitch ofSwitch, OFController controller,
+ NioEventLoopGroup workGroup) {
+ this.ofSwitch = ofSwitch;
+ this.controller = controller;
+ this.workGroup = workGroup;
+ }
+
+ /**
+ * Creates a connection to the supplied controller.
+ */
+ public void connect() {
+ // TODO initiates a connection to the controller
+ }
+
+ @Override
+ public void operationComplete(ChannelFuture future) throws Exception {
+
+ if (future.isSuccess()) {
+ log.debug("{} is connected to controller {}", ofSwitch.device().id(), controller);
+ // TODO do something for a new connection if there's any
+ } else {
+ log.debug("{} failed to connect {}, retry..", ofSwitch.device().id(), controller);
+ // TODO retry connect if retry count is less than MAX
+ }
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFMessageDecoder.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFMessageDecoder.java
new file mode 100644
index 0000000..79d0f4e
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFMessageDecoder.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+/**
+ * Decodes inbound byte buffer from OpenFlow channel to OFMessage.
+ */
+public final class OFMessageDecoder extends ByteToMessageDecoder {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
+ throws Exception {
+ log.trace("Received message from {}: {}", ctx.channel().remoteAddress(),
+ in.readByte());
+
+ // TODO decode byte message to OFMessage
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFMessageEncoder.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFMessageEncoder.java
new file mode 100644
index 0000000..1a67602
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFMessageEncoder.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.ofagent.impl;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToByteEncoder;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+/**
+ * Encodes OFMessage to a byte buffer.
+ */
+public final class OFMessageEncoder extends MessageToByteEncoder<Iterable<OFMessage>> {
+
+ @Override
+ protected void encode(ChannelHandlerContext ctx, Iterable<OFMessage> msgList, ByteBuf out)
+ throws Exception {
+
+ // TODO encode OFMessage to ByteBuf
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/package-info.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/package-info.java
new file mode 100644
index 0000000..14bdc60
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementation of OpenFlow agent.
+ */
+package org.onosproject.ofagent.impl;
\ No newline at end of file