blob: 878fae0e9defbc5b3f0a22b45f39d50e28ba2821 [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
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090018import com.google.common.collect.ImmutableSet;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070019import io.netty.channel.Channel;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070020import org.onosproject.net.Port;
21import org.onosproject.net.flow.FlowRule;
22import org.onosproject.net.packet.InboundPacket;
23import org.onosproject.ofagent.api.OFSwitch;
24import org.onosproject.ofagent.api.OFSwitchCapabilities;
25import org.projectfloodlight.openflow.protocol.OFControllerRole;
Daniel Parkbe6b6732016-11-11 15:52:19 +090026import org.projectfloodlight.openflow.protocol.OFEchoReply;
27import org.projectfloodlight.openflow.protocol.OFEchoRequest;
28import org.projectfloodlight.openflow.protocol.OFFactories;
29import org.projectfloodlight.openflow.protocol.OFFactory;
30import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
31import org.projectfloodlight.openflow.protocol.OFHello;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070032import org.projectfloodlight.openflow.protocol.OFMessage;
Daniel Parkbe6b6732016-11-11 15:52:19 +090033import org.projectfloodlight.openflow.protocol.OFVersion;
34import org.projectfloodlight.openflow.types.DatapathId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070035
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090036import java.util.Collections;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070037import java.util.Set;
38import java.util.concurrent.ConcurrentHashMap;
39
40import static com.google.common.base.Preconditions.checkArgument;
41import static com.google.common.base.Preconditions.checkNotNull;
42import static org.projectfloodlight.openflow.protocol.OFControllerRole.*;
43
44/**
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090045 * Implementation of the default OpenFlow switch.
Hyunsun Moon90163ba2016-10-12 13:35:14 -070046 */
47public final class DefaultOFSwitch implements OFSwitch {
48
49 private static final String ERR_CH_DUPLICATE = "Channel already exists: ";
50 private static final String ERR_CH_NOT_FOUND = "Channel not found: ";
Daniel Parkbe6b6732016-11-11 15:52:19 +090051 private static final long NUM_BUFFERS = 1024;
52 private static final short NUM_TABLES = 3;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070053
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090054 private final DatapathId dpId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070055 private final OFSwitchCapabilities capabilities;
56
57 private final ConcurrentHashMap<Channel, OFControllerRole> controllerRoleMap
58 = new ConcurrentHashMap<>();
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090059 private static final OFFactory FACTORY = OFFactories.getFactory(OFVersion.OF_13);
Hyunsun Moon90163ba2016-10-12 13:35:14 -070060
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090061 private int handshakeTransactionIds = -1;
Daniel Parkbe6b6732016-11-11 15:52:19 +090062
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090063 private DefaultOFSwitch(DatapathId dpid, OFSwitchCapabilities capabilities) {
64 this.dpId = dpid;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070065 this.capabilities = capabilities;
66 }
67
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090068 public static DefaultOFSwitch of(DatapathId dpid, OFSwitchCapabilities capabilities) {
69 checkNotNull(dpid, "DPID cannot be null");
70 checkNotNull(capabilities, "OF capabilities cannot be null");
71 return new DefaultOFSwitch(dpid, capabilities);
72 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -070073
74 @Override
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090075 public DatapathId dpid() {
76 return this.dpId;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070077 }
78
79 @Override
80 public OFSwitchCapabilities capabilities() {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +090081 return this.capabilities;
Hyunsun Moon90163ba2016-10-12 13:35:14 -070082 }
83
84 @Override
85 public void addControllerChannel(Channel channel) {
86 controllerRoleMap.compute(channel, (ch, existing) -> {
87 final String error = ERR_CH_DUPLICATE + channel.remoteAddress();
88 checkArgument(existing == null, error);
89 return ROLE_EQUAL;
90 });
91 }
92
93 @Override
94 public void deleteControllerChannel(Channel channel) {
95 if (controllerRoleMap.remove(channel) == null) {
96 final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
97 throw new IllegalStateException(error);
98 }
99 }
100
101 @Override
102 public void setRole(Channel channel, OFControllerRole role) {
103 controllerRoleMap.compute(channel, (ch, existing) -> {
104 final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
105 checkNotNull(existing, error);
106 return role;
107 });
108 }
109
110 @Override
111 public OFControllerRole role(Channel channel) {
112 OFControllerRole role = controllerRoleMap.get(channel);
113 if (role == null) {
114 final String error = ERR_CH_NOT_FOUND + channel.remoteAddress();
115 throw new IllegalStateException(error);
116 }
117 return role;
118 }
119
120 @Override
121 public Set<Channel> controllerChannels() {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900122 return ImmutableSet.copyOf(controllerRoleMap.keySet());
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700123 }
124
125 @Override
126 public void processPortAdded(Port port) {
127 // TODO generate FEATURES_REPLY message and send it to the controller
128 }
129
130 @Override
131 public void processPortDown(Port port) {
132 // TODO generate PORT_STATUS message and send it to the controller
133 }
134
135 @Override
136 public void processPortUp(Port port) {
137 // TODO generate PORT_STATUS message and send it to the controller
138 }
139
140 @Override
141 public void processFlowRemoved(FlowRule flowRule) {
142 // TODO generate FLOW_REMOVED message and send it to the controller
143 }
144
145 @Override
146 public void processPacketIn(InboundPacket packet) {
147 // TODO generate PACKET_IN message and send it to the controller
148 }
149
150 @Override
151 public void processControllerCommand(Channel channel, OFMessage msg) {
152 // TODO process controller command
153 }
154
155 @Override
156 public void processStatsRequest(Channel channel, OFMessage msg) {
157 // TODO process request and send reply
158 }
159
160 @Override
161 public void processRoleRequest(Channel channel, OFMessage msg) {
162 // TODO process role request and send reply
163 }
164
165 @Override
166 public void processFeaturesRequest(Channel channel, OFMessage msg) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900167 OFFeaturesReply ofFeaturesReply = FACTORY.buildFeaturesReply()
168 .setDatapathId(dpId)
Daniel Parkbe6b6732016-11-11 15:52:19 +0900169 .setNBuffers(NUM_BUFFERS)
170 .setNTables(NUM_TABLES)
171 .setCapabilities(capabilities.ofSwitchCapabilities())
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900172 .setXid(msg.getXid())
173 .build();
174 channel.writeAndFlush(Collections.singletonList(ofFeaturesReply));
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700175 }
176
177 @Override
178 public void processLldp(Channel channel, OFMessage msg) {
179 // TODO process lldp
180 }
Daniel Parkbe6b6732016-11-11 15:52:19 +0900181
182 @Override
183 public void sendOfHello(Channel channel) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900184 OFHello ofHello = FACTORY.buildHello()
185 .setXid(this.handshakeTransactionIds--)
186 .build();
187 channel.writeAndFlush(Collections.singletonList(ofHello));
Daniel Parkbe6b6732016-11-11 15:52:19 +0900188 }
189
190 @Override
191 public void processEchoRequest(Channel channel, OFMessage msg) {
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900192 OFEchoReply ofEchoReply = FACTORY.buildEchoReply()
Daniel Parkbe6b6732016-11-11 15:52:19 +0900193 .setXid(msg.getXid())
Hyunsun Moonf4ba44f2017-03-14 03:25:52 +0900194 .setData(((OFEchoRequest) msg).getData())
195 .build();
196 channel.writeAndFlush(Collections.singletonList(ofEchoReply));
Daniel Parkbe6b6732016-11-11 15:52:19 +0900197 }
Hyunsun Moon90163ba2016-10-12 13:35:14 -0700198}