blob: 4258321f95e467f30c1d71e95068fb001bdf27d3 [file] [log] [blame]
Hyunsun Moon90163ba2016-10-12 13:35:14 -07001/*
2 * Copyright 2017-present 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 */
16package org.onosproject.ofagent.impl;
17
Daniel Parkbe6b6732016-11-11 15:52:19 +090018import com.google.common.collect.Lists;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070019import io.netty.channel.Channel;
20import org.onosproject.net.Device;
Daniel Parkbe6b6732016-11-11 15:52:19 +090021import org.onosproject.net.DeviceId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070022import org.onosproject.net.Port;
23import org.onosproject.net.flow.FlowRule;
24import org.onosproject.net.packet.InboundPacket;
25import org.onosproject.ofagent.api.OFSwitch;
26import org.onosproject.ofagent.api.OFSwitchCapabilities;
27import org.projectfloodlight.openflow.protocol.OFControllerRole;
Daniel Parkbe6b6732016-11-11 15:52:19 +090028import org.projectfloodlight.openflow.protocol.OFEchoReply;
29import org.projectfloodlight.openflow.protocol.OFEchoRequest;
30import org.projectfloodlight.openflow.protocol.OFFactories;
31import org.projectfloodlight.openflow.protocol.OFFactory;
32import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
33import org.projectfloodlight.openflow.protocol.OFHello;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070034import org.projectfloodlight.openflow.protocol.OFMessage;
Daniel Parkbe6b6732016-11-11 15:52:19 +090035import org.projectfloodlight.openflow.protocol.OFVersion;
36import org.projectfloodlight.openflow.types.DatapathId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070037
Daniel Parkbe6b6732016-11-11 15:52:19 +090038import java.util.List;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070039import java.util.Set;
40import java.util.concurrent.ConcurrentHashMap;
41
42import static com.google.common.base.Preconditions.checkArgument;
43import static com.google.common.base.Preconditions.checkNotNull;
44import static org.projectfloodlight.openflow.protocol.OFControllerRole.*;
45
46/**
47 * Implementation of OF switch.
48 */
49public final class DefaultOFSwitch implements OFSwitch {
50
51 private static final String ERR_CH_DUPLICATE = "Channel already exists: ";
52 private static final String ERR_CH_NOT_FOUND = "Channel not found: ";
Daniel Parkbe6b6732016-11-11 15:52:19 +090053 private static final long NUM_BUFFERS = 1024;
54 private static final short NUM_TABLES = 3;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070055
56 private final Device device;
57 private final OFSwitchCapabilities capabilities;
Daniel Parkbe6b6732016-11-11 15:52:19 +090058 private final DatapathId datapathId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070059
60 private final ConcurrentHashMap<Channel, OFControllerRole> controllerRoleMap
61 = new ConcurrentHashMap<>();
62
Daniel Parkbe6b6732016-11-11 15:52:19 +090063 protected static final OFFactory FACTORY = OFFactories.getFactory(OFVersion.OF_13);
64 private int handshakeTransactionIds;
65
66 public DefaultOFSwitch(Device device, OFSwitchCapabilities capabilities) {
Hyunsun Moon90163ba2016-10-12 13:35:14 -070067 this.device = device;
68 this.capabilities = capabilities;
Daniel Parkbe6b6732016-11-11 15:52:19 +090069 datapathId = getDpidFromDeviceId(device.id());
70 handshakeTransactionIds = -1;
71
Hyunsun Moon90163ba2016-10-12 13:35:14 -070072 }
73
74 // TODO add builder
75
76 @Override
77 public Device device() {
Daniel Parkbe6b6732016-11-11 15:52:19 +090078 return device;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070079 }
80
81 @Override
82 public OFSwitchCapabilities capabilities() {
Daniel Parkbe6b6732016-11-11 15:52:19 +090083 return capabilities;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070084 }
85
86 @Override
87 public boolean isConnected() {
Daniel Parkbe6b6732016-11-11 15:52:19 +090088 return !controllerChannels().isEmpty();
Hyunsun Moon90163ba2016-10-12 13:35:14 -070089 }
90
91 @Override
92 public void started() {
93 // TODO do some initial setups
94 }
95
96 @Override
97 public void stopped() {
98 // TODO implement
99 }
100
101 @Override
102 public void addControllerChannel(Channel channel) {
103 controllerRoleMap.compute(channel, (ch, existing) -> {
104 final String error = ERR_CH_DUPLICATE + channel.remoteAddress();
105 checkArgument(existing == null, error);
106 return ROLE_EQUAL;
107 });
108 }
109
110 @Override
111 public void deleteControllerChannel(Channel channel) {
112 if (controllerRoleMap.remove(channel) == null) {
113 final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
114 throw new IllegalStateException(error);
115 }
116 }
117
118 @Override
119 public void setRole(Channel channel, OFControllerRole role) {
120 controllerRoleMap.compute(channel, (ch, existing) -> {
121 final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
122 checkNotNull(existing, error);
123 return role;
124 });
125 }
126
127 @Override
128 public OFControllerRole role(Channel channel) {
129 OFControllerRole role = controllerRoleMap.get(channel);
130 if (role == null) {
131 final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
132 throw new IllegalStateException(error);
133 }
134 return role;
135 }
136
137 @Override
138 public Set<Channel> controllerChannels() {
139 return null;
140 }
141
142 @Override
143 public void processPortAdded(Port port) {
144 // TODO generate FEATURES_REPLY message and send it to the controller
145 }
146
147 @Override
148 public void processPortDown(Port port) {
149 // TODO generate PORT_STATUS message and send it to the controller
150 }
151
152 @Override
153 public void processPortUp(Port port) {
154 // TODO generate PORT_STATUS message and send it to the controller
155 }
156
157 @Override
158 public void processFlowRemoved(FlowRule flowRule) {
159 // TODO generate FLOW_REMOVED message and send it to the controller
160 }
161
162 @Override
163 public void processPacketIn(InboundPacket packet) {
164 // TODO generate PACKET_IN message and send it to the controller
165 }
166
167 @Override
168 public void processControllerCommand(Channel channel, OFMessage msg) {
169 // TODO process controller command
170 }
171
172 @Override
173 public void processStatsRequest(Channel channel, OFMessage msg) {
174 // TODO process request and send reply
175 }
176
177 @Override
178 public void processRoleRequest(Channel channel, OFMessage msg) {
179 // TODO process role request and send reply
180 }
181
182 @Override
183 public void processFeaturesRequest(Channel channel, OFMessage msg) {
184 // TODO process features request and send reply
Daniel Parkbe6b6732016-11-11 15:52:19 +0900185 List<OFMessage> ofMessageList = Lists.newArrayList();
186
187 OFFeaturesReply.Builder frBuilder = FACTORY.buildFeaturesReply()
188 .setDatapathId(datapathId)
189 .setNBuffers(NUM_BUFFERS)
190 .setNTables(NUM_TABLES)
191 .setCapabilities(capabilities.ofSwitchCapabilities())
192 .setXid(msg.getXid());
193
194 ofMessageList.add(frBuilder.build());
195 channel.write(ofMessageList);
196
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700197 }
198
199 @Override
200 public void processLldp(Channel channel, OFMessage msg) {
201 // TODO process lldp
202 }
Daniel Parkbe6b6732016-11-11 15:52:19 +0900203
204 @Override
205 public void sendOfHello(Channel channel) {
206 List<OFMessage> ofMessageList = Lists.newArrayList();
207 OFHello.Builder ofHello = FACTORY.buildHello()
208 .setXid(this.handshakeTransactionIds--);
209
210 ofMessageList.add(ofHello.build());
211 channel.write(ofMessageList);
212 }
213
214 @Override
215 public void processEchoRequest(Channel channel, OFMessage msg) {
216 List<OFMessage> ofMessageList = Lists.newArrayList();
217 OFEchoReply.Builder echoBuilder = FACTORY.buildEchoReply()
218 .setXid(msg.getXid())
219 .setData(((OFEchoRequest) msg).getData());
220
221 ofMessageList.add(echoBuilder.build());
222 channel.write(ofMessageList);
223 }
224
225 private DatapathId getDpidFromDeviceId(DeviceId deviceId) {
226 String deviceIdToString = deviceId.toString().split(":")[1];
227
228 assert (deviceIdToString.length() == 16);
229
230 String resultedHexString = new String();
231 for (int i = 0; i < 8; i++) {
232 resultedHexString = resultedHexString + deviceIdToString.charAt(2 * i)
233 + deviceIdToString.charAt(2 * i + 1);
234 if (i != 7) {
235 resultedHexString += ":";
236 }
237 }
238 return DatapathId.of(resultedHexString);
239 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700240}