Committed by
Thomas Vachuska
[ONOS-2337,ONOS-2338,ONOS-2339]Pcep Controller
Change-Id: I27fee4669ec923a55d83993b493699c1c46a1b36
Showing
14 changed files
with
1746 additions
and
10 deletions
... | @@ -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 | ... | ... |
pcep/ctl/pom.xml
0 → 100644
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 | +} |
pcep/ctl/src/main/java/org/onosproject/pcep/controller/impl/PcepClientControllerImpl.java
0 → 100644
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 | +} |
-
Please register or login to post a comment