SureshBR
Committed by Thomas Vachuska

[ONOS-2337,ONOS-2338,ONOS-2339]Pcep Controller

Change-Id: I27fee4669ec923a55d83993b493699c1c46a1b36
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 */ 15 */
16 package org.onosproject.pcep.controller; 16 package org.onosproject.pcep.controller;
17 17
18 -import java.util.List; 18 +import java.util.Collection;
19 19
20 import org.onosproject.pcepio.protocol.PcepMessage; 20 import org.onosproject.pcepio.protocol.PcepMessage;
21 21
...@@ -31,7 +31,7 @@ public interface PcepClientController { ...@@ -31,7 +31,7 @@ public interface PcepClientController {
31 * 31 *
32 * @return list of PcepClient elements 32 * @return list of PcepClient elements
33 */ 33 */
34 - public List<PcepClient> getClients(); 34 + Collection<PcepClient> getClients();
35 35
36 /** 36 /**
37 * Returns the actual pcc client for the given ip address. 37 * Returns the actual pcc client for the given ip address.
...@@ -39,7 +39,7 @@ public interface PcepClientController { ...@@ -39,7 +39,7 @@ public interface PcepClientController {
39 * @param pccId the id of the pcc client to fetch 39 * @param pccId the id of the pcc client to fetch
40 * @return the interface to this pcc client 40 * @return the interface to this pcc client
41 */ 41 */
42 - public PcepClient getClient(PccId pccId); 42 + PcepClient getClient(PccId pccId);
43 43
44 /** 44 /**
45 * Register a listener for meta events that occur to pcep 45 * Register a listener for meta events that occur to pcep
...@@ -47,28 +47,28 @@ public interface PcepClientController { ...@@ -47,28 +47,28 @@ public interface PcepClientController {
47 * 47 *
48 * @param listener the listener to notify 48 * @param listener the listener to notify
49 */ 49 */
50 - public void addListener(PcepClientListener listener); 50 + void addListener(PcepClientListener listener);
51 51
52 /** 52 /**
53 * Unregister a listener. 53 * Unregister a listener.
54 * 54 *
55 * @param listener the listener to unregister 55 * @param listener the listener to unregister
56 */ 56 */
57 - public void removeListener(PcepClientListener listener); 57 + void removeListener(PcepClientListener listener);
58 58
59 /** 59 /**
60 * Register a listener for OF msg events. 60 * Register a listener for OF msg events.
61 * 61 *
62 * @param listener the listener to notify 62 * @param listener the listener to notify
63 */ 63 */
64 - public void addEventListener(PcepEventListener listener); 64 + void addEventListener(PcepEventListener listener);
65 65
66 /** 66 /**
67 * Unregister a listener. 67 * Unregister a listener.
68 * 68 *
69 * @param listener the listener to unregister 69 * @param listener the listener to unregister
70 */ 70 */
71 - public void removeEventListener(PcepEventListener listener); 71 + void removeEventListener(PcepEventListener listener);
72 72
73 /** 73 /**
74 * Send a message to a particular pcc client. 74 * Send a message to a particular pcc client.
...@@ -76,7 +76,7 @@ public interface PcepClientController { ...@@ -76,7 +76,7 @@ public interface PcepClientController {
76 * @param pccId the id of the client to send message. 76 * @param pccId the id of the client to send message.
77 * @param msg the message to send 77 * @param msg the message to send
78 */ 78 */
79 - public void writeMessage(PccId pccId, PcepMessage msg); 79 + void writeMessage(PccId pccId, PcepMessage msg);
80 80
81 /** 81 /**
82 * Process a message and notify the appropriate listeners. 82 * Process a message and notify the appropriate listeners.
...@@ -84,10 +84,10 @@ public interface PcepClientController { ...@@ -84,10 +84,10 @@ public interface PcepClientController {
84 * @param pccId id of the client the message arrived on 84 * @param pccId id of the client the message arrived on
85 * @param msg the message to process. 85 * @param msg the message to process.
86 */ 86 */
87 - public void processClientMessage(PccId pccId, PcepMessage msg); 87 + void processClientMessage(PccId pccId, PcepMessage msg);
88 88
89 /** 89 /**
90 * Close all connected PCC clients. 90 * Close all connected PCC clients.
91 */ 91 */
92 - public void closeConnectedClients(); 92 + void closeConnectedClients();
93 } 93 }
......
...@@ -42,6 +42,27 @@ public interface PcepPacketStats { ...@@ -42,6 +42,27 @@ public interface PcepPacketStats {
42 public int wrongPacketCount(); 42 public int wrongPacketCount();
43 43
44 /** 44 /**
45 + * Increments the received packet counter.
46 + */
47 + public void addInPacket();
48 +
49 + /**
50 + * Increments the sent packet counter.
51 + */
52 + public void addOutPacket();
53 +
54 + /**
55 + * Increments the sent packet counter by specified value.
56 + * @param value of no of packets sent
57 + */
58 + public void addOutPacket(int value);
59 +
60 + /**
61 + * Increments the wrong packet counter.
62 + */
63 + public void addWrongPacket();
64 +
65 + /**
45 * Returns the time value. 66 * Returns the time value.
46 * 67 *
47 * @return long value of time 68 * @return long value of time
......
1 +<!--
2 + ~ Copyright 2014 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 +<project xmlns="http://maven.apache.org/POM/4.0.0"
17 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
18 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
19 + <modelVersion>4.0.0</modelVersion>
20 +
21 + <parent>
22 + <groupId>org.onosproject</groupId>
23 + <artifactId>onos-pcep-controller</artifactId>
24 + <version>1.3.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
26 + </parent>
27 +
28 + <artifactId>onos-pcep-controller-impl</artifactId>
29 + <packaging>bundle</packaging>
30 +
31 + <description>ONOS PCEP controller subsystem API</description>
32 +
33 + <dependencies>
34 + <dependency>
35 + <!-- FIXME once experimenter gets merged to upstream -->
36 + <groupId>org.onosproject</groupId>
37 + <artifactId>onos-pcep-controller-api</artifactId>
38 + </dependency>
39 + <dependency>
40 + <groupId>io.netty</groupId>
41 + <artifactId>netty</artifactId>
42 + </dependency>
43 + <dependency>
44 + <groupId>org.apache.felix</groupId>
45 + <artifactId>org.apache.felix.scr.annotations</artifactId>
46 + </dependency>
47 + <dependency>
48 + <groupId>org.osgi</groupId>
49 + <artifactId>org.osgi.compendium</artifactId>
50 + </dependency>
51 + <dependency>
52 + <groupId>org.onosproject</groupId>
53 + <artifactId>onlab-misc</artifactId>
54 + </dependency>
55 + </dependencies>
56 +
57 + <build>
58 + <plugins>
59 + <plugin>
60 + <groupId>org.apache.felix</groupId>
61 + <artifactId>maven-scr-plugin</artifactId>
62 + </plugin>
63 + </plugins>
64 + </build>
65 +
66 +</project>
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
17 +
18 +import static org.onlab.util.Tools.groupedThreads;
19 +
20 +import java.lang.management.ManagementFactory;
21 +import java.lang.management.RuntimeMXBean;
22 +import java.net.InetSocketAddress;
23 +import java.util.HashMap;
24 +import java.util.Map;
25 +import java.util.concurrent.Executors;
26 +
27 +import org.jboss.netty.bootstrap.ServerBootstrap;
28 +import org.jboss.netty.channel.ChannelPipelineFactory;
29 +import org.jboss.netty.channel.group.ChannelGroup;
30 +import org.jboss.netty.channel.group.DefaultChannelGroup;
31 +import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
32 +import org.onosproject.pcep.controller.PccId;
33 +import org.onosproject.pcep.controller.PcepPacketStats;
34 +import org.onosproject.pcep.controller.driver.PcepAgent;
35 +import org.onosproject.pcep.controller.driver.PcepClientDriver;
36 +import org.onosproject.pcepio.protocol.PcepFactories;
37 +import org.onosproject.pcepio.protocol.PcepFactory;
38 +import org.onosproject.pcepio.protocol.PcepVersion;
39 +import org.slf4j.Logger;
40 +import org.slf4j.LoggerFactory;
41 +
42 +/**
43 + * The main controller class. Handles all setup and network listeners -
44 + * Distributed ownership control of pcc through IControllerRegistryService
45 + */
46 +public class Controller {
47 +
48 + private static final Logger log = LoggerFactory.getLogger(Controller.class);
49 +
50 + private static final PcepFactory FACTORY1 = PcepFactories.getFactory(PcepVersion.PCEP_1);
51 +
52 + private ChannelGroup cg;
53 +
54 + // Configuration options
55 + private int pcepPort = 4189;
56 + private int workerThreads = 10;
57 +
58 + // Start time of the controller
59 + private long systemStartTime;
60 +
61 + private PcepAgent agent;
62 +
63 + private NioServerSocketChannelFactory execFactory;
64 +
65 + // Perf. related configuration
66 + private static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
67 +
68 + /**
69 + * Returns factory version for processing pcep messages.
70 + *
71 + * @return instance of factory version
72 + */
73 + public PcepFactory getPcepMessageFactory1() {
74 + return FACTORY1;
75 + }
76 +
77 + /**
78 + * To get system start time.
79 + *
80 + * @return system start time in milliseconds
81 + */
82 + public long getSystemStartTime() {
83 + return (this.systemStartTime);
84 + }
85 +
86 + /**
87 + * Tell controller that we're ready to accept pcc connections.
88 + */
89 + public void run() {
90 + try {
91 + final ServerBootstrap bootstrap = createServerBootStrap();
92 +
93 + bootstrap.setOption("reuseAddr", true);
94 + bootstrap.setOption("child.keepAlive", true);
95 + bootstrap.setOption("child.tcpNoDelay", true);
96 + bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
97 +
98 + ChannelPipelineFactory pfact = new PcepPipelineFactory(this);
99 +
100 + bootstrap.setPipelineFactory(pfact);
101 + InetSocketAddress sa = new InetSocketAddress(pcepPort);
102 + cg = new DefaultChannelGroup();
103 + cg.add(bootstrap.bind(sa));
104 + log.info("Listening for PCC connection on {}", sa);
105 + } catch (Exception e) {
106 + throw new RuntimeException(e);
107 + }
108 + }
109 +
110 + /**
111 + * Creates server boot strap.
112 + *
113 + * @return ServerBootStrap
114 + */
115 + private ServerBootstrap createServerBootStrap() {
116 + if (workerThreads == 0) {
117 + execFactory = new NioServerSocketChannelFactory(
118 + Executors.newCachedThreadPool(groupedThreads("onos/pcep", "boss-%d")),
119 + Executors.newCachedThreadPool(groupedThreads("onos/pcep", "worker-%d")));
120 + return new ServerBootstrap(execFactory);
121 + } else {
122 + execFactory = new NioServerSocketChannelFactory(
123 + Executors.newCachedThreadPool(groupedThreads("onos/pcep", "boss-%d")),
124 + Executors.newCachedThreadPool(groupedThreads("onos/pcep", "worker-%d")), workerThreads);
125 + return new ServerBootstrap(execFactory);
126 + }
127 + }
128 +
129 + /**
130 + * Initialize internal data structures.
131 + */
132 + public void init() {
133 + // These data structures are initialized here because other
134 + // module's startUp() might be called before ours
135 + this.systemStartTime = System.currentTimeMillis();
136 + }
137 +
138 + public Map<String, Long> getMemory() {
139 + Map<String, Long> m = new HashMap<>();
140 + Runtime runtime = Runtime.getRuntime();
141 + m.put("total", runtime.totalMemory());
142 + m.put("free", runtime.freeMemory());
143 + return m;
144 + }
145 +
146 + public Long getUptime() {
147 + RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
148 + return rb.getUptime();
149 + }
150 +
151 + /**
152 + * Creates instance of Pcep client.
153 + *
154 + * @param pccId pcc identifier
155 + * @param sessionID session id
156 + * @param pv pcep version
157 + * @param pktStats pcep packet statistics
158 + * @return instance of PcepClient
159 + */
160 + protected PcepClientDriver getPcepClientInstance(PccId pccId, int sessionID, PcepVersion pv,
161 + PcepPacketStats pktStats) {
162 + PcepClientDriver pcepClientDriver = new PcepClientImpl();
163 + pcepClientDriver.init(pccId, pv, pktStats);
164 + pcepClientDriver.setAgent(agent);
165 + return pcepClientDriver;
166 + }
167 +
168 + /**
169 + * Starts the pcep controller.
170 + *
171 + * @param ag Pcep agent
172 + */
173 + public void start(PcepAgent ag) {
174 + log.info("Started");
175 + this.agent = ag;
176 + this.init();
177 + this.run();
178 + }
179 +
180 + /**
181 + * Stops the pcep controller.
182 + */
183 + public void stop() {
184 + log.info("Stopped");
185 + execFactory.shutdown();
186 + cg.close();
187 + }
188 +}
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
18 +
19 +import java.io.IOException;
20 +import java.net.InetSocketAddress;
21 +import java.net.SocketAddress;
22 +import java.nio.channels.ClosedChannelException;
23 +import java.util.Collections;
24 +import java.util.Date;
25 +import java.util.LinkedList;
26 +import java.util.List;
27 +import java.util.ListIterator;
28 +import java.util.concurrent.RejectedExecutionException;
29 +
30 +import org.jboss.netty.channel.Channel;
31 +import org.jboss.netty.channel.ChannelHandlerContext;
32 +import org.jboss.netty.channel.ChannelStateEvent;
33 +import org.jboss.netty.channel.ExceptionEvent;
34 +import org.jboss.netty.channel.MessageEvent;
35 +import org.jboss.netty.handler.timeout.IdleState;
36 +import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
37 +import org.jboss.netty.handler.timeout.IdleStateEvent;
38 +import org.jboss.netty.handler.timeout.IdleStateHandler;
39 +import org.jboss.netty.handler.timeout.ReadTimeoutException;
40 +import org.onlab.packet.IpAddress;
41 +import org.onosproject.pcep.controller.PccId;
42 +import org.onosproject.pcep.controller.driver.PcepClientDriver;
43 +import org.onosproject.pcepio.exceptions.PcepParseException;
44 +import org.onosproject.pcepio.protocol.PcepError;
45 +import org.onosproject.pcepio.protocol.PcepErrorInfo;
46 +import org.onosproject.pcepio.protocol.PcepErrorMsg;
47 +import org.onosproject.pcepio.protocol.PcepErrorObject;
48 +import org.onosproject.pcepio.protocol.PcepFactory;
49 +import org.onosproject.pcepio.protocol.PcepMessage;
50 +import org.onosproject.pcepio.protocol.PcepOpenMsg;
51 +import org.onosproject.pcepio.protocol.PcepOpenObject;
52 +import org.onosproject.pcepio.protocol.PcepType;
53 +import org.onosproject.pcepio.protocol.PcepVersion;
54 +import org.onosproject.pcepio.types.ErrorObjListWithOpen;
55 +import org.onosproject.pcepio.types.PceccCapabilityTlv;
56 +import org.onosproject.pcepio.types.StatefulPceCapabilityTlv;
57 +import org.onosproject.pcepio.types.PcepErrorDetailInfo;
58 +import org.onosproject.pcepio.types.PcepValueType;
59 +import org.slf4j.Logger;
60 +import org.slf4j.LoggerFactory;
61 +
62 +/**
63 + * Channel handler deals with the pcc client connection and dispatches
64 + * messages from client to the appropriate locations.
65 + */
66 +class PcepChannelHandler extends IdleStateAwareChannelHandler {
67 + static final byte DEADTIMER_MAXIMUM_VALUE = (byte) 0xFF;
68 + static final byte KEEPALIVE_MULTIPLE_FOR_DEADTIMER = 4;
69 + private static final Logger log = LoggerFactory.getLogger(PcepChannelHandler.class);
70 + private final Controller controller;
71 + private PcepClientDriver pc;
72 + private PccId thispccId;
73 + private Channel channel;
74 + private byte sessionId = 0;
75 + private byte keepAliveTime;
76 + private byte deadTime;
77 + private PcepPacketStatsImpl pcepPacketStats;
78 + static final int MAX_WRONG_COUNT_PACKET = 5;
79 + static final int BYTE_MASK = 0xFF;
80 +
81 + // State needs to be volatile because the HandshakeTimeoutHandler
82 + // needs to check if the handshake is complete
83 + private volatile ChannelState state;
84 +
85 + // When a pcc client with a ip addresss is found (i.e we already have a
86 + // connected client with the same ip), the new client is immediately
87 + // disconnected. At that point netty callsback channelDisconnected() which
88 + // proceeds to cleaup client state - we need to ensure that it does not cleanup
89 + // client state for the older (still connected) client
90 + private volatile Boolean duplicatePccIdFound;
91 +
92 + //Indicates the pcep version used by this pcc client
93 + protected PcepVersion pcepVersion;
94 + protected PcepFactory factory1;
95 +
96 + /**
97 + * Create a new unconnected PcepChannelHandler.
98 + * @param controller parent controller
99 + */
100 + PcepChannelHandler(Controller controller) {
101 + this.controller = controller;
102 + this.state = ChannelState.INIT;
103 + factory1 = controller.getPcepMessageFactory1();
104 + duplicatePccIdFound = Boolean.FALSE;
105 + pcepPacketStats = new PcepPacketStatsImpl();
106 + }
107 +
108 + /**
109 + * To disconnect a PCC.
110 + */
111 + public void disconnectClient() {
112 + pc.disconnectClient();
113 + }
114 +
115 + //*************************
116 + // Channel State Machine
117 + //*************************
118 +
119 + /**
120 + * The state machine for handling the client/channel state. All state
121 + * transitions should happen from within the state machine (and not from other
122 + * parts of the code)
123 + */
124 + enum ChannelState {
125 + /**
126 + * Initial state before channel is connected.
127 + */
128 + INIT(false) {
129 +
130 + },
131 + /**
132 + * Once the session is established, wait for open message.
133 + */
134 + OPENWAIT(false) {
135 + @Override
136 + void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
137 +
138 + log.debug("Message received in OPEN WAIT State");
139 +
140 + //check for open message
141 + if (m.getType() != PcepType.OPEN) {
142 + // When the message type is not open message increment the wrong packet statistics
143 + h.processUnknownMsg();
144 + log.debug("message is not OPEN message");
145 + } else {
146 +
147 + h.pcepPacketStats.addInPacket();
148 + PcepOpenMsg pOpenmsg = (PcepOpenMsg) m;
149 + // do Capability validation.
150 + if (h.capabilityValidation(pOpenmsg)) {
151 + log.debug("Sending handshake OPEN message");
152 + h.sessionId = pOpenmsg.getPcepOpenObject().getSessionId();
153 + h.pcepVersion = pOpenmsg.getPcepOpenObject().getVersion();
154 +
155 + //setting keepalive and deadTimer
156 + byte yKeepalive = pOpenmsg.getPcepOpenObject().getKeepAliveTime();
157 + byte yDeadTimer = pOpenmsg.getPcepOpenObject().getDeadTime();
158 + h.keepAliveTime = yKeepalive;
159 + if (yKeepalive < yDeadTimer) {
160 + h.deadTime = yDeadTimer;
161 + } else {
162 + if (DEADTIMER_MAXIMUM_VALUE > (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER)) {
163 + h.deadTime = (byte) (yKeepalive * KEEPALIVE_MULTIPLE_FOR_DEADTIMER);
164 + } else {
165 + h.deadTime = DEADTIMER_MAXIMUM_VALUE;
166 + }
167 + }
168 + h.sendHandshakeOpenMessage();
169 + h.pcepPacketStats.addOutPacket();
170 + h.setState(KEEPWAIT);
171 + } else {
172 + log.debug("Capability validation failed. Sending PCEP-ERROR message to PCC.");
173 + // Send PCEP-ERROR message.
174 + PcepErrorMsg errMsg = h.getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_2,
175 + PcepErrorDetailInfo.ERROR_VALUE_2);
176 + h.channel.write(Collections.singletonList(errMsg));
177 + }
178 + }
179 + }
180 + },
181 + /**
182 + * Once the open messages are exchanged, wait for keep alive message.
183 + */
184 + KEEPWAIT(false) {
185 + @Override
186 + void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
187 + log.debug("message received in KEEPWAIT state");
188 + //check for keep alive message
189 + if (m.getType() != PcepType.KEEP_ALIVE) {
190 + // When the message type is not keep alive message increment the wrong packet statistics
191 + h.processUnknownMsg();
192 + log.debug("message is not KEEPALIVE message");
193 + } else {
194 + // Set the client connected status
195 + h.pcepPacketStats.addInPacket();
196 + final SocketAddress address = h.channel.getRemoteAddress();
197 + if (!(address instanceof InetSocketAddress)) {
198 + throw new IOException("Invalid client connection. Pcc is indentifed based on IP");
199 + }
200 + log.debug("sending keep alive message in KEEPWAIT state");
201 +
202 + final InetSocketAddress inetAddress = (InetSocketAddress) address;
203 + h.thispccId = PccId.pccId(IpAddress.valueOf(inetAddress.getAddress()));
204 + h.pc = h.controller.getPcepClientInstance(h.thispccId, h.sessionId, h.pcepVersion,
205 + h.pcepPacketStats);
206 + // set the status of pcc as connected
207 + h.pc.setConnected(true);
208 + h.pc.setChannel(h.channel);
209 +
210 + // set any other specific parameters to the pcc
211 + h.pc.setPcVersion(h.pcepVersion);
212 + h.pc.setPcSessionId(h.sessionId);
213 + h.pc.setPcKeepAliveTime(h.keepAliveTime);
214 + h.pc.setPcDeadTime(h.deadTime);
215 + int keepAliveTimer = h.keepAliveTime & BYTE_MASK;
216 + int deadTimer = h.deadTime & BYTE_MASK;
217 + if (0 == h.keepAliveTime) {
218 + h.deadTime = 0;
219 + }
220 + // handle keep alive and dead time
221 + if (keepAliveTimer != PcepPipelineFactory.DEFAULT_KEEP_ALIVE_TIME
222 + || deadTimer != PcepPipelineFactory.DEFAULT_DEAD_TIME) {
223 +
224 + h.channel.getPipeline().replace("idle", "idle",
225 + new IdleStateHandler(PcepPipelineFactory.TIMER, deadTimer, keepAliveTimer, 0));
226 + }
227 + log.debug("Dead timer : " + deadTimer);
228 + log.debug("Keep alive time : " + keepAliveTimer);
229 +
230 + //set the state handshake completion.
231 + h.sendKeepAliveMessage();
232 + h.pcepPacketStats.addOutPacket();
233 + h.setHandshakeComplete(true);
234 +
235 + if (!h.pc.connectClient()) {
236 + disconnectDuplicate(h);
237 + } else {
238 + h.setState(ESTABLISHED);
239 + }
240 + }
241 + }
242 + },
243 + /**
244 + * Once the keep alive messages are exchanged, the state is established.
245 + */
246 + ESTABLISHED(true) {
247 + @Override
248 + void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
249 +
250 + //h.channel.getPipeline().remove("waittimeout");
251 + log.debug("Message received in established state " + m.getType());
252 + //dispatch the message
253 + h.dispatchMessage(m);
254 + }
255 + };
256 + private boolean handshakeComplete;
257 +
258 + ChannelState(boolean handshakeComplete) {
259 + this.handshakeComplete = handshakeComplete;
260 + }
261 +
262 + void processPcepMessage(PcepChannelHandler h, PcepMessage m) throws IOException, PcepParseException {
263 + // do nothing
264 + }
265 +
266 + /**
267 + * Is this a state in which the handshake has completed.
268 + *
269 + * @return true if the handshake is complete
270 + */
271 + public boolean isHandshakeComplete() {
272 + return this.handshakeComplete;
273 + }
274 +
275 + protected void disconnectDuplicate(PcepChannelHandler h) {
276 + log.error("Duplicated Pcc IP or incompleted cleanup - " + "disconnecting channel {}",
277 + h.getClientInfoString());
278 + h.duplicatePccIdFound = Boolean.TRUE;
279 + h.channel.disconnect();
280 + }
281 +
282 + /**
283 + * Sets handshake complete status.
284 + *
285 + * @param handshakeComplete status of handshake
286 + */
287 + public void setHandshakeComplete(boolean handshakeComplete) {
288 + this.handshakeComplete = handshakeComplete;
289 + }
290 +
291 + }
292 +
293 + @Override
294 + public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
295 + channel = e.getChannel();
296 + log.info("PCC connected from {}", channel.getRemoteAddress());
297 +
298 + // Wait for open message from pcc client
299 + setState(ChannelState.OPENWAIT);
300 + }
301 +
302 + @Override
303 + public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
304 + log.info("Pcc disconnected callback for pc:{}. Cleaning up ...", getClientInfoString());
305 + if (thispccId != null) {
306 + if (!duplicatePccIdFound) {
307 + // if the disconnected client (on this ChannelHandler)
308 + // was not one with a duplicate-dpid, it is safe to remove all
309 + // state for it at the controller. Notice that if the disconnected
310 + // client was a duplicate-ip, calling the method below would clear
311 + // all state for the original client (with the same ip),
312 + // which we obviously don't want.
313 + log.debug("{}:removal called", getClientInfoString());
314 + if (pc != null) {
315 + pc.removeConnectedClient();
316 + }
317 + } else {
318 + // A duplicate was disconnected on this ChannelHandler,
319 + // this is the same client reconnecting, but the original state was
320 + // not cleaned up - XXX check liveness of original ChannelHandler
321 + log.debug("{}:duplicate found", getClientInfoString());
322 + duplicatePccIdFound = Boolean.FALSE;
323 + }
324 + } else {
325 + log.warn("no pccip in channelHandler registered for " + "disconnected client {}", getClientInfoString());
326 + }
327 + }
328 +
329 + @Override
330 + public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
331 + PcepErrorMsg errMsg;
332 + log.info("exceptionCaught: " + e.toString());
333 +
334 + if (e.getCause() instanceof ReadTimeoutException) {
335 + if (ChannelState.OPENWAIT == state) {
336 + // When ReadTimeout timer is expired in OPENWAIT state, it is considered
337 + // OpenWait timer.
338 + errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_2);
339 + log.debug("Sending PCEP-ERROR message to PCC.");
340 + channel.write(Collections.singletonList(errMsg));
341 + channel.close();
342 + state = ChannelState.INIT;
343 + return;
344 + } else if (ChannelState.KEEPWAIT == state) {
345 + // When ReadTimeout timer is expired in KEEPWAIT state, is is considered
346 + // KeepWait timer.
347 + errMsg = getErrorMsg(PcepErrorDetailInfo.ERROR_TYPE_1, PcepErrorDetailInfo.ERROR_VALUE_7);
348 + log.debug("Sending PCEP-ERROR message to PCC.");
349 + channel.write(Collections.singletonList(errMsg));
350 + channel.close();
351 + state = ChannelState.INIT;
352 + return;
353 + }
354 + } else if (e.getCause() instanceof ClosedChannelException) {
355 + log.debug("Channel for pc {} already closed", getClientInfoString());
356 + } else if (e.getCause() instanceof IOException) {
357 + log.error("Disconnecting client {} due to IO Error: {}", getClientInfoString(), e.getCause().getMessage());
358 + if (log.isDebugEnabled()) {
359 + // still print stack trace if debug is enabled
360 + log.debug("StackTrace for previous Exception: ", e.getCause());
361 + }
362 + channel.close();
363 + } else if (e.getCause() instanceof PcepParseException) {
364 + PcepParseException errMsgParse = (PcepParseException) e.getCause();
365 + byte errorType = errMsgParse.getErrorType();
366 + byte errorValue = errMsgParse.getErrorValue();
367 +
368 + if ((errorType == (byte) 0x0) && (errorValue == (byte) 0x0)) {
369 + processUnknownMsg();
370 + } else {
371 + errMsg = getErrorMsg(errorType, errorValue);
372 + log.debug("Sending PCEP-ERROR message to PCC.");
373 + channel.write(Collections.singletonList(errMsg));
374 + }
375 + } else if (e.getCause() instanceof RejectedExecutionException) {
376 + log.warn("Could not process message: queue full");
377 + } else {
378 + log.error("Error while processing message from client " + getClientInfoString() + "state " + this.state);
379 + channel.close();
380 + }
381 + }
382 +
383 + @Override
384 + public String toString() {
385 + return getClientInfoString();
386 + }
387 +
388 + @Override
389 + public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception {
390 + if (!isHandshakeComplete()) {
391 + return;
392 + }
393 +
394 + if (e.getState() == IdleState.READER_IDLE) {
395 + // When no message is received on channel for read timeout, then close
396 + // the channel
397 + log.info("Disconnecting client {} due to read timeout", getClientInfoString());
398 + ctx.getChannel().close();
399 + } else if (e.getState() == IdleState.WRITER_IDLE) {
400 + // Send keep alive message
401 + log.debug("Sending keep alive message due to IdleState timeout " + pc.toString());
402 + pc.sendMessage(Collections.singletonList(pc.factory().buildKeepaliveMsg().build()));
403 + }
404 + }
405 +
406 + @Override
407 + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
408 + if (e.getMessage() instanceof List) {
409 + @SuppressWarnings("unchecked")
410 + List<PcepMessage> msglist = (List<PcepMessage>) e.getMessage();
411 + for (PcepMessage pm : msglist) {
412 + // Do the actual packet processing
413 + state.processPcepMessage(this, pm);
414 + }
415 + } else {
416 + state.processPcepMessage(this, (PcepMessage) e.getMessage());
417 + }
418 + }
419 +
420 + /**
421 + * To set the handshake status.
422 + *
423 + * @param handshakeComplete value is handshake status
424 + */
425 + public void setHandshakeComplete(boolean handshakeComplete) {
426 + this.state.setHandshakeComplete(handshakeComplete);
427 + }
428 +
429 + /**
430 + * Is this a state in which the handshake has completed.
431 + *
432 + * @return true if the handshake is complete
433 + */
434 + public boolean isHandshakeComplete() {
435 + return this.state.isHandshakeComplete();
436 + }
437 +
438 + /**
439 + * To handle the pcep message.
440 + *
441 + * @param m pcep message
442 + */
443 + private void dispatchMessage(PcepMessage m) {
444 + pc.handleMessage(m);
445 + }
446 +
447 + /**
448 + * Return a string describing this client based on the already available
449 + * information (ip address and/or remote socket).
450 + *
451 + * @return display string
452 + */
453 + private String getClientInfoString() {
454 + if (pc != null) {
455 + return pc.toString();
456 + }
457 + String channelString;
458 + if (channel == null || channel.getRemoteAddress() == null) {
459 + channelString = "?";
460 + } else {
461 + channelString = channel.getRemoteAddress().toString();
462 + }
463 + String pccIpString;
464 + // TODO : implement functionality to get pcc id string
465 + pccIpString = "?";
466 + return String.format("[%s PCCIP[%s]]", channelString, pccIpString);
467 + }
468 +
469 + /**
470 + * Update the channels state. Only called from the state machine.
471 + *
472 + * @param state
473 + */
474 + private void setState(ChannelState state) {
475 + this.state = state;
476 + }
477 +
478 + /**
479 + * Send handshake open message.
480 + *
481 + * @throws IOException,PcepParseException
482 + */
483 + private void sendHandshakeOpenMessage() throws IOException, PcepParseException {
484 + PcepOpenObject pcepOpenobj = factory1.buildOpenObject()
485 + .setSessionId(sessionId)
486 + .setKeepAliveTime(keepAliveTime)
487 + .setDeadTime(deadTime)
488 + .build();
489 + PcepMessage msg = factory1.buildOpenMsg()
490 + .setPcepOpenObj(pcepOpenobj)
491 + .build();
492 + log.debug("Sending OPEN message to {}", channel.getRemoteAddress());
493 + channel.write(Collections.singletonList(msg));
494 + }
495 +
496 + /**
497 + * Capability Validation.
498 + *
499 + * @param pOpenmsg pcep open message
500 + * @return success or failure
501 + */
502 + private boolean capabilityValidation(PcepOpenMsg pOpenmsg) {
503 + LinkedList<PcepValueType> tlvList = pOpenmsg.getPcepOpenObject().getOptionalTlv();
504 + boolean bFoundPceccCapability = false;
505 + boolean bFoundStatefulPceCapability = false;
506 + boolean bFoundPcInstantiationCapability = false;
507 +
508 + ListIterator<PcepValueType> listIterator = tlvList.listIterator();
509 + while (listIterator.hasNext()) {
510 + PcepValueType tlv = listIterator.next();
511 +
512 + switch (tlv.getType()) {
513 + case PceccCapabilityTlv.TYPE:
514 + bFoundPceccCapability = true;
515 + break;
516 + case StatefulPceCapabilityTlv.TYPE:
517 + bFoundStatefulPceCapability = true;
518 + StatefulPceCapabilityTlv stetefulPcCapTlv = (StatefulPceCapabilityTlv) tlv;
519 + if (stetefulPcCapTlv.getIFlag()) {
520 + bFoundPcInstantiationCapability = true;
521 + }
522 + break;
523 + default:
524 + continue;
525 + }
526 + }
527 +
528 + return (bFoundPceccCapability && bFoundStatefulPceCapability && bFoundPcInstantiationCapability) ? true : false;
529 + }
530 +
531 + /**
532 + * Send keep alive message.
533 + *
534 + * @throws IOException when channel is disconnected
535 + * @throws PcepParseException while building keep alive message
536 + */
537 + private void sendKeepAliveMessage() throws IOException, PcepParseException {
538 + PcepMessage msg = factory1.buildKeepaliveMsg().build();
539 + log.debug("Sending KEEPALIVE message to {}", channel.getRemoteAddress());
540 + channel.write(Collections.singletonList(msg));
541 + }
542 +
543 + /**
544 + * Send error message and close channel with pcc.
545 + */
546 + private void sendErrMsgAndCloseChannel() {
547 + // TODO send error message
548 + channel.close();
549 + }
550 +
551 + /**
552 + * Send error message when an invalid message is received.
553 + *
554 + * @throws PcepParseException while building error message
555 + */
556 + private void sendErrMsgForInvalidMsg() throws PcepParseException {
557 + byte errorType = 0x02;
558 + byte errorValue = 0x00;
559 + PcepErrorMsg errMsg = getErrorMsg(errorType, errorValue);
560 + channel.write(Collections.singletonList(errMsg));
561 + }
562 +
563 + /**
564 + * Builds pcep error message based on error value and error type.
565 + *
566 + * @param errorType pcep error type
567 + * @param errorValue pcep error value
568 + * @return pcep error message
569 + * @throws PcepParseException while bulding error message
570 + */
571 + public PcepErrorMsg getErrorMsg(byte errorType, byte errorValue) throws PcepParseException {
572 + LinkedList<PcepErrorObject> llerrObj = new LinkedList<PcepErrorObject>();
573 + PcepErrorMsg errMsg;
574 +
575 + PcepErrorObject errObj = factory1.buildPcepErrorObject()
576 + .setErrorValue(errorValue)
577 + .setErrorType(errorType)
578 + .build();
579 +
580 + llerrObj.add(errObj);
581 +
582 + if (state == ChannelState.OPENWAIT) {
583 + //If Error caught in Openmessage
584 + PcepOpenObject openObj = null;
585 + ErrorObjListWithOpen errorObjListWithOpen = null;
586 +
587 + if (0 != sessionId) {
588 + openObj = factory1.buildOpenObject().setSessionId(sessionId).build();
589 + errorObjListWithOpen = new ErrorObjListWithOpen(llerrObj, openObj);
590 + } else {
591 + errorObjListWithOpen = new ErrorObjListWithOpen(llerrObj, null);
592 + }
593 +
594 + errMsg = factory1.buildPcepErrorMsg()
595 + .setErrorObjListWithOpen(errorObjListWithOpen)
596 + .build();
597 + } else {
598 +
599 + //If Error caught in other than Openmessage
600 + LinkedList<PcepError> llPcepErr = new LinkedList<PcepError>();
601 +
602 + PcepError pcepErr = factory1.buildPcepError()
603 + .setErrorObjList(llerrObj)
604 + .build();
605 +
606 + llPcepErr.add(pcepErr);
607 +
608 + PcepErrorInfo errInfo = factory1.buildPcepErrorInfo()
609 + .setPcepErrorList(llPcepErr)
610 + .build();
611 +
612 + errMsg = factory1.buildPcepErrorMsg()
613 + .setPcepErrorInfo(errInfo)
614 + .build();
615 + }
616 + return errMsg;
617 + }
618 +
619 + /**
620 + * Process unknown pcep message received.
621 + *
622 + * @throws PcepParseException while building pcep error message
623 + */
624 + public void processUnknownMsg() throws PcepParseException {
625 + Date now = null;
626 + if (pcepPacketStats.wrongPacketCount() == 0) {
627 + now = new Date();
628 + pcepPacketStats.setTime(now.getTime());
629 + pcepPacketStats.addWrongPacket();
630 + sendErrMsgForInvalidMsg();
631 + }
632 +
633 + if (pcepPacketStats.wrongPacketCount() > 1) {
634 + Date lastest = new Date();
635 + pcepPacketStats.addWrongPacket();
636 + //converting to seconds
637 + if (((lastest.getTime() - pcepPacketStats.getTime()) / 1000) > 60) {
638 + now = lastest;
639 + pcepPacketStats.setTime(now.getTime());
640 + pcepPacketStats.resetWrongPacket();
641 + pcepPacketStats.addWrongPacket();
642 + } else if (((int) (lastest.getTime() - now.getTime()) / 1000) < 60) {
643 + if (MAX_WRONG_COUNT_PACKET <= pcepPacketStats.wrongPacketCount()) {
644 + //reset once wrong packet count reaches MAX_WRONG_COUNT_PACKET
645 + pcepPacketStats.resetWrongPacket();
646 + // max wrong packets received send error message and close the session
647 + sendErrMsgAndCloseChannel();
648 + }
649 + }
650 + }
651 + }
652 +}
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
17 +
18 +import static org.onlab.util.Tools.groupedThreads;
19 +
20 +import java.util.Collection;
21 +import java.util.Collections;
22 +import java.util.HashSet;
23 +import java.util.Set;
24 +import java.util.concurrent.ConcurrentHashMap;
25 +import java.util.concurrent.ExecutorService;
26 +import java.util.concurrent.Executors;
27 +import java.util.concurrent.locks.Lock;
28 +import java.util.concurrent.locks.ReentrantLock;
29 +
30 +import org.apache.felix.scr.annotations.Activate;
31 +import org.apache.felix.scr.annotations.Component;
32 +import org.apache.felix.scr.annotations.Deactivate;
33 +import org.apache.felix.scr.annotations.Service;
34 +import org.onosproject.net.driver.DriverService;
35 +import org.onosproject.pcep.controller.PccId;
36 +import org.onosproject.pcep.controller.PcepClient;
37 +import org.onosproject.pcep.controller.PcepClientController;
38 +import org.onosproject.pcep.controller.PcepClientListener;
39 +import org.onosproject.pcep.controller.PcepEventListener;
40 +import org.onosproject.pcep.controller.driver.PcepAgent;
41 +import org.onosproject.pcepio.protocol.PcepMessage;
42 +import org.slf4j.Logger;
43 +import org.slf4j.LoggerFactory;
44 +
45 +import com.google.common.collect.Sets;
46 +
47 +@Component(immediate = true)
48 +@Service
49 +public class PcepClientControllerImpl implements PcepClientController {
50 +
51 + private static final Logger log = LoggerFactory.getLogger(PcepClientControllerImpl.class);
52 +
53 + //@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 + protected DriverService driverService;
55 +
56 + private final ExecutorService executorMsgs =
57 + Executors.newFixedThreadPool(32, groupedThreads("onos/pcep", "event-stats-%d"));
58 +
59 + private final ExecutorService executorBarrier =
60 + Executors.newFixedThreadPool(4, groupedThreads("onos/pcep", "event-barrier-%d"));
61 +
62 + protected ConcurrentHashMap<PccId, PcepClient> connectedClients =
63 + new ConcurrentHashMap<PccId, PcepClient>();
64 +
65 + protected PcepClientAgent agent = new PcepClientAgent();
66 + protected Set<PcepClientListener> pcepClientListener = new HashSet<>();
67 +
68 + protected Set<PcepEventListener> pcepEventListener = Sets.newHashSet();
69 +
70 + private final Controller ctrl = new Controller();
71 +
72 + @Activate
73 + public void activate() {
74 + ctrl.start(agent);
75 + log.info("Started");
76 + }
77 +
78 + @Deactivate
79 + public void deactivate() {
80 + // Close all connected clients
81 + closeConnectedClients();
82 + ctrl.stop();
83 + log.info("Stopped");
84 + }
85 +
86 + @Override
87 + public Collection<PcepClient> getClients() {
88 + return connectedClients.values();
89 + }
90 +
91 + @Override
92 + public PcepClient getClient(PccId pccId) {
93 + return connectedClients.get(pccId);
94 + }
95 +
96 + @Override
97 + public void addListener(PcepClientListener listener) {
98 + if (!pcepClientListener.contains(listener)) {
99 + this.pcepClientListener.add(listener);
100 + }
101 + }
102 +
103 + @Override
104 + public void removeListener(PcepClientListener listener) {
105 + this.pcepClientListener.remove(listener);
106 + }
107 +
108 + @Override
109 + public void addEventListener(PcepEventListener listener) {
110 + pcepEventListener.add(listener);
111 + }
112 +
113 + @Override
114 + public void removeEventListener(PcepEventListener listener) {
115 + pcepEventListener.remove(listener);
116 + }
117 +
118 + @Override
119 + public void writeMessage(PccId pccId, PcepMessage msg) {
120 + this.getClient(pccId).sendMessage(msg);
121 + }
122 +
123 + @Override
124 + public void processClientMessage(PccId pccId, PcepMessage msg) {
125 + PcepClient pc = getClient(pccId);
126 +
127 + switch (msg.getType()) {
128 + case NONE:
129 + break;
130 + case OPEN:
131 + break;
132 + case KEEP_ALIVE:
133 + break;
134 + case PATH_COMPUTATION_REQUEST:
135 + break;
136 + case PATH_COMPUTATION_REPLY:
137 + break;
138 + case NOTIFICATION:
139 + break;
140 + case ERROR:
141 + break;
142 + case CLOSE:
143 + log.info("Sending Close Message to {" + pccId.toString() + "}");
144 + pc.sendMessage(Collections.singletonList(pc.factory().buildCloseMsg().build()));
145 + //now disconnect client
146 + pc.disconnectClient();
147 + break;
148 + case REPORT:
149 + for (PcepEventListener l : pcepEventListener) {
150 + l.handleMessage(pccId, msg);
151 + }
152 + break;
153 + case UPDATE:
154 + for (PcepEventListener l : pcepEventListener) {
155 + l.handleMessage(pccId, msg);
156 + }
157 + break;
158 + case INITIATE:
159 + for (PcepEventListener l : pcepEventListener) {
160 + l.handleMessage(pccId, msg);
161 + }
162 + break;
163 + case LABEL_UPDATE:
164 + break;
165 + case MAX:
166 + break;
167 + case END:
168 + break;
169 + default:
170 + break;
171 + }
172 + }
173 +
174 + @Override
175 + public void closeConnectedClients() {
176 + PcepClient pc;
177 + for (PccId id : connectedClients.keySet()) {
178 + pc = getClient(id);
179 + pc.disconnectClient();
180 + }
181 + }
182 +
183 + /**
184 + * Implementation of an Pcep Agent which is responsible for
185 + * keeping track of connected clients and the state in which
186 + * they are.
187 + */
188 + public class PcepClientAgent implements PcepAgent {
189 +
190 + private final Logger log = LoggerFactory.getLogger(PcepClientAgent.class);
191 + private final Lock clientLock = new ReentrantLock();
192 +
193 + @Override
194 + public boolean addConnectedClient(PccId pccId, PcepClient pc) {
195 +
196 + if (connectedClients.get(pccId) != null) {
197 + log.error("Trying to add connectedClient but found a previous "
198 + + "value for pcc ip: {}", pccId.toString());
199 + return false;
200 + } else {
201 + log.debug("Added Client {}", pccId.toString());
202 + connectedClients.put(pccId, pc);
203 + for (PcepClientListener l : pcepClientListener) {
204 + l.clientConnected(pccId);
205 + }
206 + return true;
207 + }
208 + }
209 +
210 + @Override
211 + public boolean validActivation(PccId pccId) {
212 + if (connectedClients.get(pccId) == null) {
213 + log.error("Trying to activate client but is not in "
214 + + "connected client: pccIp {}. Aborting ..", pccId.toString());
215 + return false;
216 + }
217 +
218 + return true;
219 + }
220 +
221 + @Override
222 + public void removeConnectedClient(PccId pccId) {
223 +
224 + connectedClients.remove(pccId);
225 + for (PcepClientListener l : pcepClientListener) {
226 + log.warn("removal for {}", pccId.toString());
227 + l.clientDisconnected(pccId);
228 + }
229 + }
230 +
231 + @Override
232 + public void processPcepMessage(PccId pccId, PcepMessage m) {
233 + processClientMessage(pccId, m);
234 + }
235 + }
236 +}
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
18 +
19 +import java.net.InetSocketAddress;
20 +import java.net.SocketAddress;
21 +import java.util.Collections;
22 +import java.util.List;
23 +import java.util.concurrent.RejectedExecutionException;
24 +
25 +import org.jboss.netty.channel.Channel;
26 +import org.onlab.packet.IpAddress;
27 +import org.onosproject.pcep.controller.PccId;
28 +import org.onosproject.pcep.controller.PcepPacketStats;
29 +import org.onosproject.pcep.controller.driver.PcepAgent;
30 +import org.onosproject.pcep.controller.driver.PcepClientDriver;
31 +import org.onosproject.pcepio.protocol.PcepFactories;
32 +import org.onosproject.pcepio.protocol.PcepFactory;
33 +import org.onosproject.pcepio.protocol.PcepMessage;
34 +import org.onosproject.pcepio.protocol.PcepVersion;
35 +import org.slf4j.Logger;
36 +import org.slf4j.LoggerFactory;
37 +
38 +import com.google.common.base.MoreObjects;
39 +
40 +/**
41 + * An abstract representation of an OpenFlow switch. Can be extended by others
42 + * to serve as a base for their vendor specific representation of a switch.
43 + */
44 +public class PcepClientImpl implements PcepClientDriver {
45 +
46 + protected final Logger log = LoggerFactory.getLogger(PcepClientImpl.class);
47 +
48 + private static final String SHUTDOWN_MSG = "Worker has already been shutdown";
49 +
50 + private Channel channel;
51 + protected String channelId;
52 +
53 + private boolean connected;
54 + protected boolean startDriverHandshakeCalled = false;
55 + protected boolean isHandShakeComplete = false;
56 + protected boolean isSyncComplete = false;
57 + private PccId pccId;
58 + private PcepAgent agent;
59 +
60 + private PcepVersion pcepVersion;
61 + private byte keepAliveTime;
62 + private byte deadTime;
63 + private byte sessionId;
64 + private PcepPacketStatsImpl pktStats;
65 +
66 + @Override
67 + public void init(PccId pccId, PcepVersion pcepVersion, PcepPacketStats pktStats) {
68 + this.pccId = pccId;
69 + this.pcepVersion = pcepVersion;
70 + this.pktStats = (PcepPacketStatsImpl) pktStats;
71 + }
72 +
73 + @Override
74 + public final void disconnectClient() {
75 + this.channel.close();
76 + }
77 +
78 + @Override
79 + public final void sendMessage(PcepMessage m) {
80 + log.debug("Sending message to {}", channel.getRemoteAddress());
81 + try {
82 + channel.write(Collections.singletonList(m));
83 + this.pktStats.addOutPacket();
84 + } catch (RejectedExecutionException e) {
85 + log.warn(e.getMessage());
86 + if (!e.getMessage().contains(SHUTDOWN_MSG)) {
87 + throw e;
88 + }
89 + }
90 + }
91 +
92 + @Override
93 + public final void sendMessage(List<PcepMessage> msgs) {
94 + try {
95 + channel.write(msgs);
96 + this.pktStats.addOutPacket(msgs.size());
97 + } catch (RejectedExecutionException e) {
98 + log.warn(e.getMessage());
99 + if (!e.getMessage().contains(SHUTDOWN_MSG)) {
100 + throw e;
101 + }
102 + }
103 + }
104 +
105 + @Override
106 + public final boolean isConnected() {
107 + return this.connected;
108 + }
109 +
110 + @Override
111 + public final void setConnected(boolean connected) {
112 + this.connected = connected;
113 + };
114 +
115 + @Override
116 + public final void setChannel(Channel channel) {
117 + this.channel = channel;
118 + final SocketAddress address = channel.getRemoteAddress();
119 + if (address instanceof InetSocketAddress) {
120 + final InetSocketAddress inetAddress = (InetSocketAddress) address;
121 + final IpAddress ipAddress = IpAddress.valueOf(inetAddress.getAddress());
122 + if (ipAddress.isIp4()) {
123 + channelId = ipAddress.toString() + ':' + inetAddress.getPort();
124 + } else {
125 + channelId = '[' + ipAddress.toString() + "]:" + inetAddress.getPort();
126 + }
127 + }
128 + };
129 +
130 + @Override
131 + public String channelId() {
132 + return channelId;
133 + }
134 +
135 + @Override
136 + public final PccId getPccId() {
137 + return this.pccId;
138 + }
139 +
140 + @Override
141 + public final String getStringId() {
142 + return this.pccId.toString();
143 + }
144 +
145 + @Override
146 + public final void setPcVersion(PcepVersion pcepVersion) {
147 + this.pcepVersion = pcepVersion;
148 + }
149 +
150 + @Override
151 + public void setPcKeepAliveTime(byte keepAliveTime) {
152 + this.keepAliveTime = keepAliveTime;
153 + }
154 +
155 + @Override
156 + public void setPcDeadTime(byte deadTime) {
157 + this.deadTime = deadTime;
158 + }
159 +
160 + @Override
161 + public void setPcSessionId(byte sessionId) {
162 + this.sessionId = sessionId;
163 + }
164 +
165 + @Override
166 + public void setIsSyncComplete(boolean value) {
167 + this.isSyncComplete = value;
168 + }
169 +
170 + @Override
171 + public boolean isSyncComplete() {
172 + return isSyncComplete;
173 + }
174 +
175 + @Override
176 + public final void handleMessage(PcepMessage m) {
177 + this.pktStats.addInPacket();
178 + this.agent.processPcepMessage(pccId, m);
179 + }
180 +
181 + @Override
182 + public final boolean connectClient() {
183 + return this.agent.addConnectedClient(pccId, this);
184 + }
185 +
186 + @Override
187 + public final void removeConnectedClient() {
188 + this.agent.removeConnectedClient(pccId);
189 + }
190 +
191 + @Override
192 + public PcepFactory factory() {
193 + return PcepFactories.getFactory(pcepVersion);
194 + }
195 +
196 + @Override
197 + public boolean isHandshakeComplete() {
198 + return isHandShakeComplete;
199 + }
200 +
201 + @Override
202 + public final void setAgent(PcepAgent ag) {
203 + if (this.agent == null) {
204 + this.agent = ag;
205 + }
206 + }
207 +
208 + @Override
209 + public boolean isOptical() {
210 + return false;
211 + }
212 +
213 + @Override
214 + public String toString() {
215 + return MoreObjects.toStringHelper(getClass())
216 + .add("channel", channelId())
217 + .add("pccId", getPccId())
218 + .toString();
219 + }
220 +}
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
17 +
18 +import java.util.LinkedList;
19 +import java.util.List;
20 +
21 +import org.jboss.netty.buffer.ChannelBuffer;
22 +import org.jboss.netty.channel.Channel;
23 +import org.jboss.netty.channel.ChannelHandlerContext;
24 +import org.jboss.netty.handler.codec.frame.FrameDecoder;
25 +import org.onosproject.pcepio.protocol.PcepFactories;
26 +import org.onosproject.pcepio.protocol.PcepMessage;
27 +import org.onosproject.pcepio.protocol.PcepMessageReader;
28 +import org.onosproject.pcepio.util.HexDump;
29 +import org.slf4j.Logger;
30 +import org.slf4j.LoggerFactory;
31 +
32 +/**
33 + * Decode an pcep message from a Channel, for use in a netty pipeline.
34 + */
35 +public class PcepMessageDecoder extends FrameDecoder {
36 +
37 + protected static final Logger log = LoggerFactory.getLogger(PcepMessageDecoder.class);
38 +
39 + @Override
40 + protected Object decode(ChannelHandlerContext ctx, Channel channel,
41 + ChannelBuffer buffer) throws Exception {
42 + log.debug("Message received.");
43 + if (!channel.isConnected()) {
44 + log.info("Channel is not connected.");
45 + // In testing, I see decode being called AFTER decode last.
46 + // This check avoids that from reading corrupted frames
47 + return null;
48 + }
49 +
50 + HexDump.pcepHexDump(buffer);
51 +
52 + // Note that a single call to decode results in reading a single
53 + // PcepMessage from the channel buffer, which is passed on to, and processed
54 + // by, the controller (in PcepChannelHandler).
55 + // This is different from earlier behavior (with the original pcepIO),
56 + // where we parsed all the messages in the buffer, before passing on
57 + // a list of the parsed messages to the controller.
58 + // The performance *may or may not* not be as good as before.
59 + PcepMessageReader<PcepMessage> reader = PcepFactories.getGenericReader();
60 + List<PcepMessage> msgList = new LinkedList<PcepMessage>();
61 +
62 + while (buffer.readableBytes() > 0) {
63 + PcepMessage message = reader.readFrom(buffer);
64 + msgList.add(message);
65 + }
66 + return msgList;
67 + }
68 +}
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
17 +
18 +import java.util.List;
19 +
20 +import org.jboss.netty.buffer.ChannelBuffer;
21 +import org.jboss.netty.buffer.ChannelBuffers;
22 +import org.jboss.netty.channel.Channel;
23 +import org.jboss.netty.channel.ChannelHandlerContext;
24 +import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
25 +import org.onosproject.pcepio.protocol.PcepMessage;
26 +import org.onosproject.pcepio.util.HexDump;
27 +import org.slf4j.Logger;
28 +import org.slf4j.LoggerFactory;
29 +
30 +/**
31 + * Encode an pcep message for output into a ChannelBuffer, for use in a
32 + * netty pipeline.
33 + */
34 +public class PcepMessageEncoder extends OneToOneEncoder {
35 + protected static final Logger log = LoggerFactory.getLogger(PcepMessageEncoder.class);
36 +
37 + @Override
38 + protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
39 + log.debug("Sending message");
40 + if (!(msg instanceof List)) {
41 + log.debug("Invalid msg.");
42 + return msg;
43 + }
44 +
45 + @SuppressWarnings("unchecked")
46 + List<PcepMessage> msglist = (List<PcepMessage>) msg;
47 +
48 + ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
49 +
50 + for (PcepMessage pm : msglist) {
51 + pm.writeTo(buf);
52 + }
53 +
54 + HexDump.pcepHexDump(buf);
55 +
56 + return buf;
57 + }
58 +}
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
17 +
18 +
19 +import org.onosproject.pcep.controller.PcepPacketStats;
20 +/**
21 + * A representation of a packet context which allows any provider
22 + * to view a packet in event, but may block the response to the
23 + * event if blocked has been called. This packet context can be used
24 + * to react to the packet in event with a packet out.
25 + */
26 +public class PcepPacketStatsImpl implements PcepPacketStats {
27 +
28 + private int inPacketCount;
29 + private int outPacketCount;
30 + private int wrongPacketCount;
31 + private long time;
32 +
33 + public PcepPacketStatsImpl() {
34 + this.inPacketCount = 0;
35 + this.outPacketCount = 0;
36 + this.wrongPacketCount = 0;
37 + this.time = 0;
38 + }
39 +
40 + @Override
41 + public int outPacketCount() {
42 + return outPacketCount;
43 + }
44 +
45 + @Override
46 + public int inPacketCount() {
47 + return inPacketCount;
48 + }
49 +
50 + @Override
51 + public int wrongPacketCount() {
52 + return wrongPacketCount;
53 + }
54 +
55 + /**
56 + * Increments the received packet counter.
57 + */
58 + public void addInPacket() {
59 + this.inPacketCount++;
60 + }
61 +
62 + /**
63 + * Increments the sent packet counter.
64 + */
65 + public void addOutPacket() {
66 + this.outPacketCount++;
67 + }
68 +
69 + /**
70 + * Increments the sent packet counter by specified value.
71 + *
72 + * @param value of no of packets sent
73 + */
74 + public void addOutPacket(int value) {
75 + this.outPacketCount = this.outPacketCount + value;
76 + }
77 +
78 + /**
79 + * Increments the wrong packet counter.
80 + */
81 + public void addWrongPacket() {
82 + this.wrongPacketCount++;
83 + }
84 +
85 + public void resetWrongPacket() {
86 + this.wrongPacketCount = 0;
87 + }
88 +
89 + @Override
90 + public long getTime() {
91 + return this.time;
92 + }
93 +
94 + /**
95 + * Sets the time value.
96 + *
97 + * @param time long value of time
98 + */
99 + public void setTime(long time) {
100 + this.time = time;
101 + }
102 +}
1 +/*
2 + * Copyright 2015 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.pcep.controller.impl;
18 +
19 +import org.jboss.netty.channel.ChannelPipeline;
20 +import org.jboss.netty.channel.ChannelPipelineFactory;
21 +import org.jboss.netty.channel.Channels;
22 +import org.jboss.netty.handler.timeout.IdleStateHandler;
23 +import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
24 +import org.jboss.netty.util.ExternalResourceReleasable;
25 +import org.jboss.netty.util.HashedWheelTimer;
26 +import org.jboss.netty.util.Timer;
27 +
28 +/**
29 + * Creates a ChannelPipeline for a server-side pcep channel.
30 + */
31 +public class PcepPipelineFactory
32 + implements ChannelPipelineFactory, ExternalResourceReleasable {
33 +
34 + protected Controller controller;
35 + static final Timer TIMER = new HashedWheelTimer();
36 + protected IdleStateHandler idleHandler;
37 + protected ReadTimeoutHandler readTimeoutHandler;
38 + static final int DEFAULT_KEEP_ALIVE_TIME = 30;
39 + static final int DEFAULT_DEAD_TIME = 120;
40 + static final int DEFAULT_WAIT_TIME = 60;
41 +
42 + public PcepPipelineFactory(Controller controller) {
43 + super();
44 + this.controller = controller;
45 + this.idleHandler = new IdleStateHandler(TIMER, DEFAULT_DEAD_TIME, DEFAULT_KEEP_ALIVE_TIME, 0);
46 + this.readTimeoutHandler = new ReadTimeoutHandler(TIMER, DEFAULT_WAIT_TIME);
47 + }
48 +
49 + @Override
50 + public ChannelPipeline getPipeline() throws Exception {
51 + PcepChannelHandler handler = new PcepChannelHandler(controller);
52 +
53 + ChannelPipeline pipeline = Channels.pipeline();
54 + pipeline.addLast("pcepmessagedecoder", new PcepMessageDecoder());
55 + pipeline.addLast("pcepmessageencoder", new PcepMessageEncoder());
56 + pipeline.addLast("idle", idleHandler);
57 + pipeline.addLast("waittimeout", readTimeoutHandler);
58 + pipeline.addLast("handler", handler);
59 + return pipeline;
60 + }
61 +
62 + @Override
63 + public void releaseExternalResources() {
64 + TIMER.stop();
65 + }
66 +}
1 +/*
2 + * Copyright 2015 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 the PCEP controller subsystem.
19 + */
20 +package org.onosproject.pcep.controller.impl;
1 +package org.onosproject.pcepio.util;
2 +
3 +import org.jboss.netty.buffer.ChannelBuffer;
4 +import org.slf4j.Logger;
5 +import org.slf4j.LoggerFactory;
6 +
7 +public final class HexDump {
8 + protected static final Logger log = LoggerFactory.getLogger(HexDump.class);
9 +
10 + private HexDump() {
11 + }
12 +
13 + public static void pcepHexDump(ChannelBuffer buff) {
14 +
15 + log.debug("==================== HEX DUMP ======================");
16 + try {
17 + byte[] yTemp;
18 + yTemp = buff.array();
19 +
20 + int iStartIndex = buff.readerIndex();
21 + int iEndIndex = buff.writerIndex();
22 + do {
23 + StringBuilder sb = new StringBuilder();
24 + for (int k = 0; (k < 16) && (iStartIndex < iEndIndex); ++k) {
25 + if (0 == k % 4) {
26 + sb.append(String.format(" ")); //blank after 4 bytes
27 + }
28 + sb.append(String.format("%02X ", yTemp[iStartIndex++]));
29 + }
30 + log.debug(sb.toString());
31 + } while (iStartIndex < iEndIndex);
32 + } catch (Exception e) {
33 + log.error("[HexDump] Invalid buffer: " + e.toString());
34 + }
35 +
36 + log.debug("===================================================");
37 + }
38 +}
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
33 33
34 <modules> 34 <modules>
35 <module>api</module> 35 <module>api</module>
36 + <module>ctl</module>
36 <module>pcepio</module> 37 <module>pcepio</module>
37 </modules> 38 </modules>
38 39
......