blob: 4c5b0b778ac418fdb0f34bc815f16f95564ddf35 [file] [log] [blame]
sanghodbee2332017-05-18 09:59:16 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
sanghodbee2332017-05-18 09:59:16 +09003 *
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
17package org.onosproject.openstacknetworking.impl;
18
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.net.DeviceId;
28import org.onosproject.net.flow.DefaultFlowRule;
29import org.onosproject.net.flow.DefaultTrafficSelector;
30import org.onosproject.net.flow.DefaultTrafficTreatment;
31import org.onosproject.net.flow.FlowRule;
32import org.onosproject.net.flow.FlowRuleOperations;
33import org.onosproject.net.flow.FlowRuleOperationsContext;
34import org.onosproject.net.flow.FlowRuleService;
35import org.onosproject.net.flow.TrafficSelector;
36import org.onosproject.net.flow.TrafficTreatment;
sanghodbee2332017-05-18 09:59:16 +090037import org.onosproject.openstacknetworking.api.Constants;
38import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090039import org.onosproject.openstacknode.api.OpenstackNode;
40import org.onosproject.openstacknode.api.OpenstackNodeEvent;
41import org.onosproject.openstacknode.api.OpenstackNodeListener;
42import org.onosproject.openstacknode.api.OpenstackNodeService;
sanghodbee2332017-05-18 09:59:16 +090043import org.slf4j.Logger;
44
45import java.util.concurrent.ExecutorService;
46import java.util.concurrent.Executors;
47
48import static org.onlab.util.Tools.groupedThreads;
49import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
50import static org.slf4j.LoggerFactory.getLogger;
51
52/**
53 * Sets flow rules directly using FlowRuleService.
54 */
55@Service
56@Component(immediate = true)
57public class OpenstackFlowRuleManager implements OpenstackFlowRuleService {
58
59 private final Logger log = getLogger(getClass());
60
61 private static final int DROP_PRIORITY = 0;
62 private static final int HIGH_PRIORITY = 30000;
sanghodc375372017-06-08 10:41:30 +090063 private static final int TIMEOUT_SNAT_RULE = 60;
sanghodbee2332017-05-18 09:59:16 +090064
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected FlowRuleService flowRuleService;
67
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
69 protected CoreService coreService;
70
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected OpenstackNodeService osNodeService;
73
74 private final ExecutorService deviceEventExecutor =
75 Executors.newSingleThreadExecutor(groupedThreads("openstacknetworking", "device-event"));
Hyunsun Moon0d457362017-06-27 17:19:41 +090076 private final OpenstackNodeListener internalNodeListener = new InternalOpenstackNodeListener();
sanghodbee2332017-05-18 09:59:16 +090077
78 private ApplicationId appId;
79
80 @Activate
81 protected void activate() {
82 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
83 coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
84 osNodeService.addListener(internalNodeListener);
85
sanghoc395d0f2017-07-11 10:05:25 +090086 osNodeService.completeNodes(OpenstackNode.NodeType.COMPUTE)
87 .forEach(node -> initializePipeline(node.intgBridge()));
88
sanghodbee2332017-05-18 09:59:16 +090089 log.info("Started");
90 }
91
92 @Deactivate
93 protected void deactivate() {
94 osNodeService.removeListener(internalNodeListener);
95 deviceEventExecutor.shutdown();
96
97 log.info("Stopped");
98 }
99
sanghodc375372017-06-08 10:41:30 +0900100
sanghodbee2332017-05-18 09:59:16 +0900101 @Override
sanghodc375372017-06-08 10:41:30 +0900102 public void setRule(ApplicationId appId,
103 DeviceId deviceId,
104 TrafficSelector selector,
105 TrafficTreatment treatment,
106 int priority,
107 int tableType,
108 boolean install) {
sanghodbee2332017-05-18 09:59:16 +0900109
sanghodc375372017-06-08 10:41:30 +0900110 FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder()
sanghodbee2332017-05-18 09:59:16 +0900111 .forDevice(deviceId)
sanghodc375372017-06-08 10:41:30 +0900112 .withSelector(selector)
113 .withTreatment(treatment)
114 .withPriority(priority)
115 .fromApp(appId)
sanghodbee2332017-05-18 09:59:16 +0900116 .forTable(tableType);
117
sanghodc375372017-06-08 10:41:30 +0900118 if (priority == Constants.PRIORITY_SNAT_RULE) {
119 flowRuleBuilder.makeTemporary(TIMEOUT_SNAT_RULE);
sanghodbee2332017-05-18 09:59:16 +0900120 } else {
sanghodc375372017-06-08 10:41:30 +0900121 flowRuleBuilder.makePermanent();
sanghodbee2332017-05-18 09:59:16 +0900122 }
123
sanghodc375372017-06-08 10:41:30 +0900124 applyRule(flowRuleBuilder.build(), install);
sanghodbee2332017-05-18 09:59:16 +0900125 }
126
sanghodc375372017-06-08 10:41:30 +0900127 private void applyRule(FlowRule flowRule, boolean install) {
sanghodbee2332017-05-18 09:59:16 +0900128 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
129
130 flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
131
132 flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
133 @Override
134 public void onSuccess(FlowRuleOperations ops) {
135 log.debug("Provisioned vni or forwarding table");
136 }
137
138 @Override
139 public void onError(FlowRuleOperations ops) {
Jian Li7f70bb72018-07-06 23:35:30 +0900140 log.debug("Failed to provision vni or forwarding table");
sanghodbee2332017-05-18 09:59:16 +0900141 }
142 }));
143 }
144
145 private void initializePipeline(DeviceId deviceId) {
Jian Li87ded822018-07-02 18:31:22 +0900146 // for inbound table transition
147 connectTables(deviceId, Constants.STAT_INBOUND_TABLE, Constants.VTAP_INBOUND_TABLE);
148 connectTables(deviceId, Constants.VTAP_INBOUND_TABLE, Constants.DHCP_ARP_TABLE);
149
150 // for vTag and ACL table transition
Jian Li70a2c3f2018-04-13 17:26:31 +0900151 connectTables(deviceId, Constants.DHCP_ARP_TABLE, Constants.VTAG_TABLE);
152 connectTables(deviceId, Constants.VTAG_TABLE, Constants.ACL_TABLE);
sanghodbee2332017-05-18 09:59:16 +0900153 connectTables(deviceId, Constants.ACL_TABLE, Constants.JUMP_TABLE);
Jian Li87ded822018-07-02 18:31:22 +0900154
155 // for JUMP table transition
156 // we need JUMP table for bypassing routing table which contains large
157 // amount of flow rules which might cause performance degradation during
158 // table lookup
sanghodbee2332017-05-18 09:59:16 +0900159 setupJumpTable(deviceId);
Jian Li87ded822018-07-02 18:31:22 +0900160
161 // for outbound table transition
162 connectTables(deviceId, Constants.STAT_OUTBOUND_TABLE, Constants.VTAP_OUTBOUND_TABLE);
163 connectTables(deviceId, Constants.VTAP_OUTBOUND_TABLE, Constants.FORWARDING_TABLE);
164
165 // for FLAT outbound table transition
166 connectTables(deviceId, Constants.STAT_FLAT_OUTBOUND_TABLE, Constants.VTAP_FLAT_OUTBOUND_TABLE);
167 connectTables(deviceId, Constants.VTAP_FLAT_OUTBOUND_TABLE, Constants.FLAT_TABLE);
sanghodbee2332017-05-18 09:59:16 +0900168 }
169
sangho3dd2a8b2017-07-19 15:54:31 +0900170 @Override
171 public void connectTables(DeviceId deviceId, int fromTable, int toTable) {
sanghodbee2332017-05-18 09:59:16 +0900172 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
173 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
174
175 treatment.transition(toTable);
176
177 FlowRule flowRule = DefaultFlowRule.builder()
178 .forDevice(deviceId)
179 .withSelector(selector.build())
180 .withTreatment(treatment.build())
181 .withPriority(DROP_PRIORITY)
182 .fromApp(appId)
183 .makePermanent()
184 .forTable(fromTable)
185 .build();
186
sanghodc375372017-06-08 10:41:30 +0900187 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900188 }
189
sangho3dd2a8b2017-07-19 15:54:31 +0900190 @Override
191 public void setUpTableMissEntry(DeviceId deviceId, int table) {
sanghodbee2332017-05-18 09:59:16 +0900192 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
193 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
194
195 treatment.drop();
196
197 FlowRule flowRule = DefaultFlowRule.builder()
198 .forDevice(deviceId)
199 .withSelector(selector.build())
200 .withTreatment(treatment.build())
201 .withPriority(DROP_PRIORITY)
202 .fromApp(appId)
203 .makePermanent()
204 .forTable(table)
205 .build();
206
sanghodc375372017-06-08 10:41:30 +0900207 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900208 }
209
210 private void setupJumpTable(DeviceId deviceId) {
211 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
212 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
213
214 selector.matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
215 treatment.transition(Constants.ROUTING_TABLE);
216
217 FlowRule flowRule = DefaultFlowRule.builder()
218 .forDevice(deviceId)
219 .withSelector(selector.build())
220 .withTreatment(treatment.build())
221 .withPriority(HIGH_PRIORITY)
222 .fromApp(appId)
223 .makePermanent()
224 .forTable(Constants.JUMP_TABLE)
225 .build();
226
sanghodc375372017-06-08 10:41:30 +0900227 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900228
229 selector = DefaultTrafficSelector.builder();
230 treatment = DefaultTrafficTreatment.builder();
231
Jian Li8abf2fe2018-06-12 18:42:30 +0900232 treatment.transition(Constants.STAT_OUTBOUND_TABLE);
sanghodbee2332017-05-18 09:59:16 +0900233
234 flowRule = DefaultFlowRule.builder()
235 .forDevice(deviceId)
236 .withSelector(selector.build())
237 .withTreatment(treatment.build())
238 .withPriority(DROP_PRIORITY)
239 .fromApp(appId)
240 .makePermanent()
241 .forTable(Constants.JUMP_TABLE)
242 .build();
243
sanghodc375372017-06-08 10:41:30 +0900244 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900245 }
246
247 private class InternalOpenstackNodeListener implements OpenstackNodeListener {
248
249 @Override
250 public void event(OpenstackNodeEvent event) {
251 OpenstackNode osNode = event.subject();
252 // TODO check leadership of the node and make only the leader process
253
254 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900255 case OPENSTACK_NODE_COMPLETE:
sanghodbee2332017-05-18 09:59:16 +0900256 deviceEventExecutor.execute(() -> {
257 log.info("COMPLETE node {} is detected", osNode.hostname());
sanghodc375372017-06-08 10:41:30 +0900258 processCompleteNode(event.subject());
sanghodbee2332017-05-18 09:59:16 +0900259 });
260 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900261 case OPENSTACK_NODE_CREATED:
262 case OPENSTACK_NODE_UPDATED:
263 case OPENSTACK_NODE_REMOVED:
264 case OPENSTACK_NODE_INCOMPLETE:
sanghodbee2332017-05-18 09:59:16 +0900265 default:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900266 // do nothing
sanghodbee2332017-05-18 09:59:16 +0900267 break;
268 }
269 }
270
271 private void processCompleteNode(OpenstackNode osNode) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900272 if (osNode.type().equals(OpenstackNode.NodeType.COMPUTE)) {
273 initializePipeline(osNode.intgBridge());
sanghodbee2332017-05-18 09:59:16 +0900274 }
275 }
276 }
277}