bbc58a8c273b6f9aa89d855d09b2cbd21f94ddbd
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / connection / ConnectionContextImpl.java
1 /**
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  * <p/>
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
7  */
8 package org.opendaylight.openflowplugin.impl.connection;
9
10 import java.math.BigInteger;
11 import java.net.InetSocketAddress;
12 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
13 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
14 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
15 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
16 import org.opendaylight.openflowplugin.api.openflow.connection.HandshakeContext;
17 import org.opendaylight.openflowplugin.api.openflow.connection.OutboundQueueProvider;
18 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceDisconnectedHandler;
19 import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.SessionStatistics;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 /**
26  *
27  */
28 public class ConnectionContextImpl implements ConnectionContext {
29
30     private final ConnectionAdapter connectionAdapter;
31     private CONNECTION_STATE connectionState;
32     private FeaturesReply featuresReply;
33     private NodeId nodeId;
34     private DeviceDisconnectedHandler deviceDisconnectedHandler;
35     private static final Logger LOG = LoggerFactory.getLogger(ConnectionContextImpl.class);
36     private OutboundQueueProvider outboundQueueProvider;
37     private OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration;
38     private HandshakeContext handshakeContext;
39
40     /**
41      * @param connectionAdapter
42      */
43     public ConnectionContextImpl(final ConnectionAdapter connectionAdapter) {
44         this.connectionAdapter = connectionAdapter;
45     }
46
47     @Override
48     public ConnectionAdapter getConnectionAdapter() {
49         return connectionAdapter;
50     }
51
52     @Override
53     public OutboundQueue getOutboundQueueProvider() {
54         return this.outboundQueueProvider;
55     }
56
57     @Override
58     public void setOutboundQueueProvider(final OutboundQueueProvider outboundQueueProvider) {
59         this.outboundQueueProvider = outboundQueueProvider;
60     }
61
62     @Override
63     public CONNECTION_STATE getConnectionState() {
64         return connectionState;
65     }
66
67     @Override
68     public NodeId getNodeId() {
69         return nodeId;
70     }
71
72     @Override
73     public void setNodeId(final NodeId nodeId) {
74         this.nodeId = nodeId;
75     }
76
77     @Override
78     public FeaturesReply getFeatures() {
79         return featuresReply;
80     }
81
82     @Override
83     public void setDeviceDisconnectedHandler(final DeviceDisconnectedHandler deviceDisconnectedHandler) {
84         this.deviceDisconnectedHandler = deviceDisconnectedHandler;
85     }
86
87     @Override
88     public void setFeatures(final FeaturesReply featuresReply) {
89         this.featuresReply = featuresReply;
90     }
91
92     @Override
93     public void closeConnection(boolean propagate) {
94         if (null == nodeId){
95             SessionStatistics.countEvent(connectionAdapter.getRemoteAddress().toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
96         } else {
97             SessionStatistics.countEvent(nodeId.toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
98         }
99         final BigInteger datapathId = featuresReply != null ? featuresReply.getDatapathId() : BigInteger.ZERO;
100         LOG.debug("Actively closing connection: {}, datapathId:{}.",
101                 connectionAdapter.getRemoteAddress(), datapathId);
102         connectionState = ConnectionContext.CONNECTION_STATE.RIP;
103
104         unregisterOutboundQueue();
105         closeHandshakeContext();
106
107         if (getConnectionAdapter().isAlive()) {
108             getConnectionAdapter().disconnect();
109         }
110
111         if (propagate) {
112             propagateDeviceDisconnectedEvent();
113         }
114     }
115
116     private void closeHandshakeContext() {
117         if (handshakeContext != null) {
118             try {
119                 handshakeContext.close();
120             } catch (Exception e) {
121                 LOG.info("handshake context closing failed: ", e);
122             } finally {
123                 handshakeContext = null;
124             }
125         }
126     }
127
128     @Override
129     public void onConnectionClosed() {
130         if (null == nodeId){
131             SessionStatistics.countEvent(connectionAdapter.getRemoteAddress().toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_DEVICE);
132         } else {
133             SessionStatistics.countEvent(nodeId.toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_DEVICE);
134         }
135         connectionState = ConnectionContext.CONNECTION_STATE.RIP;
136
137         final InetSocketAddress remoteAddress = connectionAdapter.getRemoteAddress();
138         final Short auxiliaryId;
139         if (null != getFeatures() && null != getFeatures().getAuxiliaryId()) {
140             auxiliaryId = getFeatures().getAuxiliaryId();
141         } else {
142             auxiliaryId = 0;
143         }
144
145         LOG.debug("disconnecting: node={}|auxId={}|connection state = {}",
146                 remoteAddress,
147                 auxiliaryId,
148                 getConnectionState());
149
150         unregisterOutboundQueue();
151         closeHandshakeContext();
152         propagateDeviceDisconnectedEvent();
153     }
154
155     private void propagateDeviceDisconnectedEvent() {
156         if (null != deviceDisconnectedHandler) {
157             final BigInteger datapathId = featuresReply != null ? featuresReply.getDatapathId() : BigInteger.ZERO;
158             LOG.debug("Propagating connection closed event: {}, datapathId:{}.",
159                     connectionAdapter.getRemoteAddress(), datapathId);
160             deviceDisconnectedHandler.onDeviceDisconnected(this);
161         }
162     }
163
164     @Override
165     public void setOutboundQueueHandleRegistration(OutboundQueueHandlerRegistration<OutboundQueueProvider> outboundQueueHandlerRegistration) {
166         this.outboundQueueHandlerRegistration = outboundQueueHandlerRegistration;
167     }
168
169     private void unregisterOutboundQueue() {
170         if (outboundQueueHandlerRegistration != null) {
171             outboundQueueHandlerRegistration.close();
172             outboundQueueHandlerRegistration = null;
173         }
174     }
175
176     @Override
177     public void changeStateToHandshaking() {
178         connectionState = CONNECTION_STATE.HANDSHAKING;
179     }
180
181     @Override
182     public void changeStateToTimeouting() {
183         connectionState = CONNECTION_STATE.TIMEOUTING;
184     }
185
186     @Override
187     public void changeStateToWorking() {
188         connectionState = CONNECTION_STATE.WORKING;
189     }
190
191     @Override
192     public void setHandshakeContext(HandshakeContext handshakeContext) {
193         this.handshakeContext = handshakeContext;
194     }
195 }