blob: 8b931157bd81426cfad291b51e5759b4e3c3a0aa [file] [log] [blame]
sanghodbee2332017-05-18 09:59:16 +09001/*
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 */
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
86 log.info("Started");
87 }
88
89 @Deactivate
90 protected void deactivate() {
91 osNodeService.removeListener(internalNodeListener);
92 deviceEventExecutor.shutdown();
93
94 log.info("Stopped");
95 }
96
sanghodc375372017-06-08 10:41:30 +090097
sanghodbee2332017-05-18 09:59:16 +090098 @Override
sanghodc375372017-06-08 10:41:30 +090099 public void setRule(ApplicationId appId,
100 DeviceId deviceId,
101 TrafficSelector selector,
102 TrafficTreatment treatment,
103 int priority,
104 int tableType,
105 boolean install) {
sanghodbee2332017-05-18 09:59:16 +0900106
sanghodc375372017-06-08 10:41:30 +0900107 FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder()
sanghodbee2332017-05-18 09:59:16 +0900108 .forDevice(deviceId)
sanghodc375372017-06-08 10:41:30 +0900109 .withSelector(selector)
110 .withTreatment(treatment)
111 .withPriority(priority)
112 .fromApp(appId)
sanghodbee2332017-05-18 09:59:16 +0900113 .forTable(tableType);
114
sanghodc375372017-06-08 10:41:30 +0900115 if (priority == Constants.PRIORITY_SNAT_RULE) {
116 flowRuleBuilder.makeTemporary(TIMEOUT_SNAT_RULE);
sanghodbee2332017-05-18 09:59:16 +0900117 } else {
sanghodc375372017-06-08 10:41:30 +0900118 flowRuleBuilder.makePermanent();
sanghodbee2332017-05-18 09:59:16 +0900119 }
120
sanghodc375372017-06-08 10:41:30 +0900121 applyRule(flowRuleBuilder.build(), install);
sanghodbee2332017-05-18 09:59:16 +0900122 }
123
sanghodc375372017-06-08 10:41:30 +0900124 private void applyRule(FlowRule flowRule, boolean install) {
sanghodbee2332017-05-18 09:59:16 +0900125 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
126
127 flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
128
129 flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
130 @Override
131 public void onSuccess(FlowRuleOperations ops) {
132 log.debug("Provisioned vni or forwarding table");
133 }
134
135 @Override
136 public void onError(FlowRuleOperations ops) {
137 log.debug("Failed to privision vni or forwarding table");
138 }
139 }));
140 }
141
142 private void initializePipeline(DeviceId deviceId) {
143 connectTables(deviceId, Constants.SRC_VNI_TABLE, Constants.ACL_TABLE);
144 connectTables(deviceId, Constants.ACL_TABLE, Constants.JUMP_TABLE);
sanghodbee2332017-05-18 09:59:16 +0900145 setupJumpTable(deviceId);
146 }
147
148 private void connectTables(DeviceId deviceId, int fromTable, int toTable) {
149 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
150 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
151
152 treatment.transition(toTable);
153
154 FlowRule flowRule = DefaultFlowRule.builder()
155 .forDevice(deviceId)
156 .withSelector(selector.build())
157 .withTreatment(treatment.build())
158 .withPriority(DROP_PRIORITY)
159 .fromApp(appId)
160 .makePermanent()
161 .forTable(fromTable)
162 .build();
163
sanghodc375372017-06-08 10:41:30 +0900164 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900165 }
166
167 private void setUpTableMissEntry(DeviceId deviceId, int table) {
168 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
169 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
170
171 treatment.drop();
172
173 FlowRule flowRule = DefaultFlowRule.builder()
174 .forDevice(deviceId)
175 .withSelector(selector.build())
176 .withTreatment(treatment.build())
177 .withPriority(DROP_PRIORITY)
178 .fromApp(appId)
179 .makePermanent()
180 .forTable(table)
181 .build();
182
sanghodc375372017-06-08 10:41:30 +0900183 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900184 }
185
186 private void setupJumpTable(DeviceId deviceId) {
187 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
188 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
189
190 selector.matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
191 treatment.transition(Constants.ROUTING_TABLE);
192
193 FlowRule flowRule = DefaultFlowRule.builder()
194 .forDevice(deviceId)
195 .withSelector(selector.build())
196 .withTreatment(treatment.build())
197 .withPriority(HIGH_PRIORITY)
198 .fromApp(appId)
199 .makePermanent()
200 .forTable(Constants.JUMP_TABLE)
201 .build();
202
sanghodc375372017-06-08 10:41:30 +0900203 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900204
205 selector = DefaultTrafficSelector.builder();
206 treatment = DefaultTrafficTreatment.builder();
207
208 treatment.transition(Constants.FORWARDING_TABLE);
209
210 flowRule = DefaultFlowRule.builder()
211 .forDevice(deviceId)
212 .withSelector(selector.build())
213 .withTreatment(treatment.build())
214 .withPriority(DROP_PRIORITY)
215 .fromApp(appId)
216 .makePermanent()
217 .forTable(Constants.JUMP_TABLE)
218 .build();
219
sanghodc375372017-06-08 10:41:30 +0900220 applyRule(flowRule, true);
sanghodbee2332017-05-18 09:59:16 +0900221 }
222
223 private class InternalOpenstackNodeListener implements OpenstackNodeListener {
224
225 @Override
226 public void event(OpenstackNodeEvent event) {
227 OpenstackNode osNode = event.subject();
228 // TODO check leadership of the node and make only the leader process
229
230 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900231 case OPENSTACK_NODE_COMPLETE:
sanghodbee2332017-05-18 09:59:16 +0900232 deviceEventExecutor.execute(() -> {
233 log.info("COMPLETE node {} is detected", osNode.hostname());
sanghodc375372017-06-08 10:41:30 +0900234 processCompleteNode(event.subject());
sanghodbee2332017-05-18 09:59:16 +0900235 });
236 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900237 case OPENSTACK_NODE_CREATED:
238 case OPENSTACK_NODE_UPDATED:
239 case OPENSTACK_NODE_REMOVED:
240 case OPENSTACK_NODE_INCOMPLETE:
sanghodbee2332017-05-18 09:59:16 +0900241 default:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900242 // do nothing
sanghodbee2332017-05-18 09:59:16 +0900243 break;
244 }
245 }
246
247 private void processCompleteNode(OpenstackNode osNode) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900248 if (osNode.type().equals(OpenstackNode.NodeType.COMPUTE)) {
249 initializePipeline(osNode.intgBridge());
sanghodbee2332017-05-18 09:59:16 +0900250 }
251 }
252 }
253}