2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.impl.connection.listener;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.util.concurrent.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.JdkFutureAdapters;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.net.InetSocketAddress;
16 import java.util.concurrent.Future;
17 import java.util.concurrent.TimeUnit;
18 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
19 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
20 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInputBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoOutput;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
27 import org.opendaylight.yangtools.yang.common.RpcError;
28 import org.opendaylight.yangtools.yang.common.RpcResult;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
35 public class SystemNotificationsListenerImpl implements SystemNotificationsListener {
37 private ConnectionContext connectionContext;
38 private static final Logger LOG = LoggerFactory.getLogger(SystemNotificationsListenerImpl.class);
40 static final long MAX_ECHO_REPLY_TIMEOUT = 2000;
44 * @param connectionContext
46 public SystemNotificationsListenerImpl(ConnectionContext connectionContext) {
47 this.connectionContext = connectionContext;
51 public void onDisconnectEvent(DisconnectEvent notification) {
52 // TODO Auto-generated method stub
57 public void onSwitchIdleEvent(SwitchIdleEvent notification) {
58 new Thread(new Runnable() {
61 boolean shouldBeDisconnected = true;
63 final InetSocketAddress remoteAddress = connectionContext.getConnectionAdapter().getRemoteAddress();
65 if (ConnectionContext.CONNECTION_STATE.WORKING.equals(connectionContext.getConnectionState())) {
66 FeaturesReply features = connectionContext.getFeatures();
68 "first idle state occured, node={}|auxId={}",
69 remoteAddress, features.getAuxiliaryId());
70 connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.TIMEOUTING);
71 EchoInputBuilder builder = new EchoInputBuilder();
72 builder.setVersion(features.getVersion());
74 builder.setXid(xid.getValue());
76 Future<RpcResult<EchoOutput>> echoReplyFuture = connectionContext.getConnectionAdapter()
77 .echo(builder.build());
80 RpcResult<EchoOutput> echoReplyValue = echoReplyFuture.get(MAX_ECHO_REPLY_TIMEOUT, TimeUnit.MILLISECONDS);
81 if (echoReplyValue.isSuccessful()) {
82 connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.WORKING);
83 shouldBeDisconnected = false;
85 for (RpcError replyError : echoReplyValue
87 Throwable cause = replyError.getCause();
88 LOG.warn("while receiving echoReply [{}] in TIMEOUTING state {} ",
91 LOG.trace("while receiving echoReply [{}] in TIMEOUTING state ..", remoteAddress, cause);
94 } catch (Exception e) {
95 LOG.warn("while waiting for echoReply in TIMEOUTING state: {}", e.getMessage());
96 LOG.trace("while waiting for echoReply in TIMEOUTING state ..", remoteAddress, e);
99 if (shouldBeDisconnected) {
106 private void disconnect() {
107 final ConnectionAdapter connectionAdapter = connectionContext.getConnectionAdapter();
109 if (null != connectionContext.getFeatures() && null != connectionContext.getFeatures().getAuxiliaryId()) {
110 auxId = connectionContext.getFeatures().getAuxiliaryId();
112 final Short auxiliaryId = auxId;
113 final InetSocketAddress remoteAddress = connectionAdapter.getRemoteAddress();
115 LOG.trace("disconnecting: node={}|auxId={}|connection state = {}",
118 connectionContext.getConnectionState());
120 ListenableFuture<Boolean> result = null;
121 if (connectionAdapter.isAlive()) {
122 result = JdkFutureAdapters.listenInPoolThread(connectionAdapter.disconnect());
124 LOG.debug("connection already disconnected");
125 result = Futures.immediateFuture(true);
127 connectionContext.setConnectionState(ConnectionContext.CONNECTION_STATE.RIP);
128 Futures.addCallback(result, new FutureCallback<Boolean>() {
130 public void onSuccess(final Boolean aBoolean) {
131 LOG.debug("Connection node={}|auxId={}|connection state = {}, closed successfully:{}.",
134 connectionContext.getConnectionState(),
139 public void onFailure(final Throwable throwable) {
140 LOG.debug("Connection node={}|auxId={}|connection state = {} close failed.",
143 connectionContext.getConnectionState());
147 connectionContext.propagateClosingConnection();