blob: cbf356942a7a21cc05a6ce72f0d689041b377414 [file] [log] [blame]
Hyunsun Moon90163ba2016-10-12 13:35:14 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Hyunsun Moon90163ba2016-10-12 13:35:14 -07003 *
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 */
16package org.onosproject.ofagent.impl;
17
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090018import io.netty.channel.Channel;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070019import io.netty.channel.ChannelDuplexHandler;
20import io.netty.channel.ChannelHandlerContext;
Daniel Parkbe6b6732016-11-11 15:52:19 +090021import io.netty.handler.timeout.ReadTimeoutException;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070022import org.onosproject.ofagent.api.OFSwitch;
Daniel Parkbe6b6732016-11-11 15:52:19 +090023import org.projectfloodlight.openflow.protocol.OFErrorMsg;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070024import org.projectfloodlight.openflow.protocol.OFMessage;
25import org.slf4j.Logger;
26import org.slf4j.LoggerFactory;
27
Daniel Parkbe6b6732016-11-11 15:52:19 +090028import java.io.IOException;
29import java.nio.channels.ClosedChannelException;
Daniel Parkbe6b6732016-11-11 15:52:19 +090030import java.util.concurrent.RejectedExecutionException;
31
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090032import static org.onosproject.ofagent.impl.OFChannelHandler.ChannelState.INIT;
33
Hyunsun Moon90163ba2016-10-12 13:35:14 -070034/**
35 * Implementation of OpenFlow channel handler.
36 * It processes OpenFlow message according to the channel state.
37 */
38public final class OFChannelHandler extends ChannelDuplexHandler {
39
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090040 private static final String MSG_CHANNEL_STATE = "Set channel(%s) state: %s";
41
Hyunsun Moon90163ba2016-10-12 13:35:14 -070042 private final Logger log = LoggerFactory.getLogger(getClass());
43 private final OFSwitch ofSwitch;
44
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090045 private Channel channel;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070046 private ChannelState state;
47
Daniel Parkbe6b6732016-11-11 15:52:19 +090048 enum ChannelState {
Hyunsun Moon90163ba2016-10-12 13:35:14 -070049
50 INIT {
51 @Override
52 void processOFMessage(final OFChannelHandler handler,
53 final OFMessage msg) {
Claudine Chiue2d5acc2017-06-08 22:49:21 -040054 logProcessOFMessageDetails(handler, msg, this);
Hyunsun Moon90163ba2016-10-12 13:35:14 -070055 // TODO implement
56 }
57 },
58 WAIT_HELLO {
59 @Override
60 void processOFMessage(final OFChannelHandler handler,
61 final OFMessage msg) {
Claudine Chiue2d5acc2017-06-08 22:49:21 -040062 logProcessOFMessageDetails(handler, msg, this);
Daniel Parkbe6b6732016-11-11 15:52:19 +090063 switch (msg.getType()) {
64 case HELLO:
65 handler.setState(ChannelState.WAIT_FEATURE_REQUEST);
66 break;
67 default:
68 handler.illegalMessageReceived(msg);
69 break;
70 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -070071 }
72 },
73 WAIT_FEATURE_REQUEST {
74 @Override
75 void processOFMessage(final OFChannelHandler handler,
76 final OFMessage msg) {
Claudine Chiue2d5acc2017-06-08 22:49:21 -040077 logProcessOFMessageDetails(handler, msg, this);
Daniel Parkbe6b6732016-11-11 15:52:19 +090078 switch (msg.getType()) {
79 case FEATURES_REQUEST:
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090080 handler.ofSwitch.processFeaturesRequest(handler.channel, msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +090081 handler.setState(ChannelState.ESTABLISHED);
82 break;
83 case ECHO_REQUEST:
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090084 handler.ofSwitch.processEchoRequest(handler.channel, msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +090085 break;
86 case ERROR:
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090087 handler.logErrorClose((OFErrorMsg) msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +090088 break;
89 default:
90 handler.illegalMessageReceived(msg);
91 break;
92
93 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -070094 }
95 },
96 ESTABLISHED {
97 @Override
98 void processOFMessage(final OFChannelHandler handler,
99 final OFMessage msg) {
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400100 logProcessOFMessageDetails(handler, msg, this);
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700101 // TODO implement
102 // TODO add this channel to ofSwitch role service
Daniel Parkbe6b6732016-11-11 15:52:19 +0900103 switch (msg.getType()) {
104 case STATS_REQUEST:
105 //TODO implement
106 //TODO: use vNetService to build OFPortDesc.
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400107 handler.ofSwitch.processStatsRequest(handler.channel, msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900108 break;
109 case SET_CONFIG:
110 //TODO implement
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400111 handler.ofSwitch.processSetConfigMessage(handler.channel, msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900112 break;
113 case GET_CONFIG_REQUEST:
114 //TODO implement
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400115 handler.ofSwitch.processGetConfigRequest(handler.channel, msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900116 break;
117 case BARRIER_REQUEST:
118 //TODO implement
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400119 handler.ofSwitch.processBarrierRequest(handler.channel, msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900120 break;
121 case ECHO_REQUEST:
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900122 handler.ofSwitch.processEchoRequest(handler.channel, msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900123 break;
Claudine Chiu7c6d51c2017-06-15 23:13:51 -0400124 case ROLE_REQUEST:
125 handler.ofSwitch.processRoleRequest(handler.channel, msg);
126 break;
Daniel Parkbe6b6732016-11-11 15:52:19 +0900127 case ERROR:
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900128 handler.logErrorClose((OFErrorMsg) msg);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900129 break;
130 default:
131 handler.unhandledMessageReceived(msg);
132 break;
133 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700134 }
135 };
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900136
137 abstract void processOFMessage(final OFChannelHandler handler, final OFMessage msg);
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400138
139 private static void logProcessOFMessageDetails(final OFChannelHandler handler,
140 final OFMessage msg, ChannelState chnState) {
141 handler.log.trace("Channel state: {} dpid: {} processOFMessage type: {} nsg: {}",
142 chnState, handler.ofSwitch.dpid(), msg.getType(), msg);
143 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700144 }
145
146 /**
147 * Default constructor.
148 *
149 * @param ofSwitch openflow switch that owns this channel
150 */
151 public OFChannelHandler(OFSwitch ofSwitch) {
Daniel Parkbe6b6732016-11-11 15:52:19 +0900152 super();
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700153 this.ofSwitch = ofSwitch;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900154 setState(INIT);
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700155 }
156
157 @Override
158 public void channelActive(ChannelHandlerContext ctx) throws Exception {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900159 this.channel = ctx.channel();
160 // FIXME move this to channel handler and add channel when OF handshake is done
161 ofSwitch.addControllerChannel(channel);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900162 try {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900163 ofSwitch.sendOfHello(channel);
164 log.trace("Send OF_13 Hello to {}", channel.remoteAddress());
Daniel Parkbe6b6732016-11-11 15:52:19 +0900165 setState(ChannelState.WAIT_HELLO);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900166 } catch (Exception ex) {
167 log.error("Failed sending OF_13 Hello to {} for {}", channel.remoteAddress(), ex.getMessage());
Daniel Parkbe6b6732016-11-11 15:52:19 +0900168 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700169 }
170
171 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900172 public void channelInactive(ChannelHandlerContext ctx) {
173 ofSwitch.deleteControllerChannel(channel);
174 log.info("Device {} disconnected from controller {}", ofSwitch.dpid(), channel.remoteAddress());
175 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700176
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900177 @Override
178 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Daniel Parkbe6b6732016-11-11 15:52:19 +0900179 try {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900180 state.processOFMessage(this, (OFMessage) msg);
181 } catch (Exception ex) {
182 ctx.fireExceptionCaught(ex);
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700183 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700184 }
185
186 @Override
187 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
Daniel Parkbe6b6732016-11-11 15:52:19 +0900188 if (cause instanceof ReadTimeoutException) {
189 log.error("Connection closed because of ReadTimeoutException {}", cause.getMessage());
190 } else if (cause instanceof ClosedChannelException) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900191 log.error("ClosedChannelException occurred");
Daniel Parkbe6b6732016-11-11 15:52:19 +0900192 return;
193 } else if (cause instanceof RejectedExecutionException) {
194 log.error("Could not process message: queue full");
195 } else if (cause instanceof IOException) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900196 log.error("IOException occurred");
Daniel Parkbe6b6732016-11-11 15:52:19 +0900197 } else {
198 log.error("Error while processing message from switch {}", cause.getMessage());
199 }
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900200 channel.close();
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700201 }
202
203 private void setState(ChannelState state) {
204 this.state = state;
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900205 if (state != INIT) {
206 log.debug(String.format(MSG_CHANNEL_STATE, channel.remoteAddress(), state.name()));
207 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700208 }
Daniel Parkbe6b6732016-11-11 15:52:19 +0900209
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900210 private void logErrorClose(OFErrorMsg errorMsg) {
Daniel Parkbe6b6732016-11-11 15:52:19 +0900211 log.error("{} from switch {} in state {}",
212 errorMsg,
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900213 ofSwitch.dpid(),
Daniel Parkbe6b6732016-11-11 15:52:19 +0900214 state);
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900215 channel.close();
Daniel Parkbe6b6732016-11-11 15:52:19 +0900216 }
217
218 private void illegalMessageReceived(OFMessage ofMessage) {
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400219 log.warn("Controller should never send message {} to switch {} in current state {}",
220 ofMessage.getType(), ofSwitch.dpid(), state);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900221 }
222
223 private void unhandledMessageReceived(OFMessage ofMessage) {
Claudine Chiue2d5acc2017-06-08 22:49:21 -0400224 log.warn("Unexpected message {} received for switch {} in state {}",
225 ofMessage.getType(), ofSwitch.dpid(), state);
Daniel Parkbe6b6732016-11-11 15:52:19 +0900226 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700227}