blob: 94ee992028a01b3060885e4a9e7b8c242487a93a [file] [log] [blame]
Hyunsun Moone7e4bb32016-05-16 04:32:45 -07001/*
Brian O'Connor80dff972017-08-03 22:46:30 -07002 * Copyright 2016-present Open Networking Foundation
Hyunsun Moone7e4bb32016-05-16 04:32:45 -07003 *
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 */
alshabibb4d31712016-06-01 18:51:03 -070016package org.opencord.cordvtn.impl;
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070017
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
24import org.onlab.packet.Ethernet;
25import org.onlab.packet.IPv4;
26import org.onlab.packet.Ip4Address;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.TpPort;
29import org.onlab.packet.VlanId;
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070030import org.onosproject.net.AnnotationKeys;
31import org.onosproject.net.Port;
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070032import org.opencord.cordvtn.api.Constants;
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090033import org.opencord.cordvtn.api.core.CordVtnPipeline;
Hyunsun Moonfd5a24e2016-10-19 19:15:48 -070034import org.opencord.cordvtn.api.node.CordVtnNode;
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070037import org.onosproject.net.DeviceId;
38import org.onosproject.net.PortNumber;
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070039import org.onosproject.net.device.DeviceService;
40import org.onosproject.net.flow.DefaultFlowRule;
41import org.onosproject.net.flow.DefaultTrafficSelector;
42import org.onosproject.net.flow.DefaultTrafficTreatment;
43import org.onosproject.net.flow.FlowRule;
44import org.onosproject.net.flow.FlowRuleOperations;
45import org.onosproject.net.flow.FlowRuleOperationsContext;
46import org.onosproject.net.flow.FlowRuleService;
47import org.onosproject.net.flow.TrafficSelector;
48import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070049import org.slf4j.Logger;
50
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070051
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090052import static com.google.common.base.Preconditions.checkArgument;
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070053import static org.opencord.cordvtn.api.Constants.DEFAULT_TUNNEL;
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090054import static org.opencord.cordvtn.api.node.CordVtnNodeState.COMPLETE;
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070055import static org.slf4j.LoggerFactory.getLogger;
56
57/**
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090058 * Implementation of cordvtn pipeline.
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070059 */
60@Component(immediate = true)
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090061@Service
62public class DefaultCordVtnPipeline implements CordVtnPipeline {
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070063
64 protected final Logger log = getLogger(getClass());
65
66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 protected CoreService coreService;
68
69 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 protected FlowRuleService flowRuleService;
71
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected DeviceService deviceService;
74
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090075 private static final int VXLAN_UDP_PORT = 4789;
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070076
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070077 private ApplicationId appId;
78
79 @Activate
80 protected void activate() {
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070081 appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070082 log.info("Started");
83 }
84
85 @Deactivate
86 protected void deactivate() {
87 log.info("Stopped");
88 }
89
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090090 @Override
91 public void cleanupPipeline() {
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070092 flowRuleService.getFlowRulesById(appId).forEach(flowRule -> processFlowRule(false, flowRule));
93 }
94
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090095 @Override
Hyunsun Moonc031d9b2016-08-04 13:57:22 -070096 public void initPipeline(CordVtnNode node) {
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090097 checkArgument(node.state() == COMPLETE, "Node is not in COMPLETE state");
Hyunsun Moone7e4bb32016-05-16 04:32:45 -070098
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +090099 PortNumber dataPort = getPortNumber(node.integrationBridgeId(), node.dataInterface());
100 PortNumber tunnelPort = getPortNumber(node.integrationBridgeId(), DEFAULT_TUNNEL);
101 PortNumber hostMgmtPort = node.hostManagementInterface() == null ?
102 null : getPortNumber(node.integrationBridgeId(), node.hostManagementInterface());
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700103
104 processTableZero(node.integrationBridgeId(),
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900105 dataPort,
106 node.dataIp().ip(),
107 node.localManagementIp().ip());
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700108
109 processInPortTable(node.integrationBridgeId(),
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900110 tunnelPort,
111 dataPort,
112 hostMgmtPort);
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700113
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900114 processAccessTypeTable(node.integrationBridgeId(), dataPort);
115 processVlanTable(node.integrationBridgeId(), dataPort);
116 }
117
118 @Override
119 public void processFlowRule(boolean install, FlowRule rule) {
120 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
121 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
122
123 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
124 @Override
125 public void onError(FlowRuleOperations ops) {
126 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
127 }
128 }));
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700129 }
130
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700131 private void processTableZero(DeviceId deviceId, PortNumber dataPort, IpAddress dataIp,
132 IpAddress localMgmtIp) {
133 vxlanShuttleRule(deviceId, dataPort, dataIp);
134 localManagementBaseRule(deviceId, localMgmtIp.getIp4Address());
135
136 // take all vlan tagged packet to the VLAN table
137 TrafficSelector selector = DefaultTrafficSelector.builder()
138 .matchVlanId(VlanId.ANY)
139 .build();
140
141 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
142 .transition(TABLE_VLAN)
143 .build();
144
145 FlowRule flowRule = DefaultFlowRule.builder()
146 .fromApp(appId)
147 .withSelector(selector)
148 .withTreatment(treatment)
149 .withPriority(PRIORITY_MANAGEMENT)
150 .forDevice(deviceId)
151 .forTable(TABLE_ZERO)
152 .makePermanent()
153 .build();
154
155 processFlowRule(true, flowRule);
156
157 // take all other packets to the next table
158 selector = DefaultTrafficSelector.builder()
159 .build();
160
161 treatment = DefaultTrafficTreatment.builder()
162 .transition(TABLE_IN_PORT)
163 .build();
164
165 flowRule = DefaultFlowRule.builder()
166 .fromApp(appId)
167 .withSelector(selector)
168 .withTreatment(treatment)
169 .withPriority(PRIORITY_ZERO)
170 .forDevice(deviceId)
171 .forTable(TABLE_ZERO)
172 .makePermanent()
173 .build();
174
175 processFlowRule(true, flowRule);
176 }
177
178 private void vxlanShuttleRule(DeviceId deviceId, PortNumber dataPort, IpAddress dataIp) {
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700179 // take vxlan packet out onto the physical port
180 TrafficSelector selector = DefaultTrafficSelector.builder()
181 .matchInPort(PortNumber.LOCAL)
182 .build();
183
184 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon81a13562016-08-04 13:48:08 -0700185 .setOutput(dataPort)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700186 .build();
187
188 FlowRule flowRule = DefaultFlowRule.builder()
189 .fromApp(appId)
190 .withSelector(selector)
191 .withTreatment(treatment)
192 .withPriority(PRIORITY_HIGH)
193 .forDevice(deviceId)
194 .forTable(TABLE_ZERO)
195 .makePermanent()
196 .build();
197
198 processFlowRule(true, flowRule);
199
200 // take a vxlan encap'd packet through the Linux stack
201 selector = DefaultTrafficSelector.builder()
Hyunsun Moon81a13562016-08-04 13:48:08 -0700202 .matchInPort(dataPort)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700203 .matchEthType(Ethernet.TYPE_IPV4)
204 .matchIPProtocol(IPv4.PROTOCOL_UDP)
205 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
206 .build();
207
208 treatment = DefaultTrafficTreatment.builder()
209 .setOutput(PortNumber.LOCAL)
210 .build();
211
212 flowRule = DefaultFlowRule.builder()
213 .fromApp(appId)
214 .withSelector(selector)
215 .withTreatment(treatment)
216 .withPriority(PRIORITY_HIGH)
217 .forDevice(deviceId)
218 .forTable(TABLE_ZERO)
219 .makePermanent()
220 .build();
221
222 processFlowRule(true, flowRule);
223
224 // take a packet to the data plane ip through Linux stack
225 selector = DefaultTrafficSelector.builder()
Hyunsun Moon81a13562016-08-04 13:48:08 -0700226 .matchInPort(dataPort)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700227 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon81a13562016-08-04 13:48:08 -0700228 .matchIPDst(dataIp.toIpPrefix())
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700229 .build();
230
231 treatment = DefaultTrafficTreatment.builder()
232 .setOutput(PortNumber.LOCAL)
233 .build();
234
235 flowRule = DefaultFlowRule.builder()
236 .fromApp(appId)
237 .withSelector(selector)
238 .withTreatment(treatment)
239 .withPriority(PRIORITY_HIGH)
240 .forDevice(deviceId)
241 .forTable(TABLE_ZERO)
242 .makePermanent()
243 .build();
244
245 processFlowRule(true, flowRule);
246
247 // take an arp packet from physical through Linux stack
248 selector = DefaultTrafficSelector.builder()
Hyunsun Moon81a13562016-08-04 13:48:08 -0700249 .matchInPort(dataPort)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700250 .matchEthType(Ethernet.TYPE_ARP)
Hyunsun Moon81a13562016-08-04 13:48:08 -0700251 .matchArpTpa(dataIp.getIp4Address())
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700252 .build();
253
254 treatment = DefaultTrafficTreatment.builder()
255 .setOutput(PortNumber.LOCAL)
256 .build();
257
258 flowRule = DefaultFlowRule.builder()
259 .fromApp(appId)
260 .withSelector(selector)
261 .withTreatment(treatment)
262 .withPriority(PRIORITY_HIGH)
263 .forDevice(deviceId)
264 .forTable(TABLE_ZERO)
265 .makePermanent()
266 .build();
267
268 processFlowRule(true, flowRule);
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700269 }
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700270
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700271 private void localManagementBaseRule(DeviceId deviceId, Ip4Address localMgmtIp) {
272 TrafficSelector selector = DefaultTrafficSelector.builder()
273 .matchEthType(Ethernet.TYPE_ARP)
274 .matchArpTpa(localMgmtIp)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700275 .build();
276
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700277 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
278 .setOutput(PortNumber.LOCAL)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700279 .build();
280
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700281 FlowRule flowRule = DefaultFlowRule.builder()
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700282 .fromApp(appId)
283 .withSelector(selector)
284 .withTreatment(treatment)
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700285 .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700286 .forDevice(deviceId)
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700287 .forTable(CordVtnPipeline.TABLE_ZERO)
Hyunsun Moonacbc8ef2016-06-21 17:58:45 -0700288 .makePermanent()
289 .build();
290
291 processFlowRule(true, flowRule);
292
293 selector = DefaultTrafficSelector.builder()
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700294 .matchInPort(PortNumber.LOCAL)
295 .matchEthType(Ethernet.TYPE_IPV4)
296 .matchIPSrc(localMgmtIp.toIpPrefix())
Hyunsun Moonacbc8ef2016-06-21 17:58:45 -0700297 .build();
298
299 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon1e88fef2016-08-04 14:00:35 -0700300 .transition(CordVtnPipeline.TABLE_DST)
Hyunsun Moonacbc8ef2016-06-21 17:58:45 -0700301 .build();
302
303 flowRule = DefaultFlowRule.builder()
304 .fromApp(appId)
305 .withSelector(selector)
306 .withTreatment(treatment)
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700307 .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
Hyunsun Moonacbc8ef2016-06-21 17:58:45 -0700308 .forDevice(deviceId)
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700309 .forTable(CordVtnPipeline.TABLE_ZERO)
310 .makePermanent()
311 .build();
312
313 processFlowRule(true, flowRule);
314
315 selector = DefaultTrafficSelector.builder()
316 .matchEthType(Ethernet.TYPE_IPV4)
317 .matchIPDst(localMgmtIp.toIpPrefix())
318 .build();
319
320 treatment = DefaultTrafficTreatment.builder()
321 .setOutput(PortNumber.LOCAL)
322 .build();
323
324 flowRule = DefaultFlowRule.builder()
325 .fromApp(appId)
326 .withSelector(selector)
327 .withTreatment(treatment)
328 .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
329 .forDevice(deviceId)
330 .forTable(CordVtnPipeline.TABLE_ZERO)
331 .makePermanent()
332 .build();
333
334 processFlowRule(true, flowRule);
335
336 selector = DefaultTrafficSelector.builder()
337 .matchInPort(PortNumber.LOCAL)
338 .matchEthType(Ethernet.TYPE_ARP)
339 .matchArpSpa(localMgmtIp)
340 .build();
341
342 treatment = DefaultTrafficTreatment.builder()
343 .setOutput(PortNumber.CONTROLLER)
344 .build();
345
346 flowRule = DefaultFlowRule.builder()
347 .fromApp(appId)
348 .withSelector(selector)
349 .withTreatment(treatment)
350 .withPriority(CordVtnPipeline.PRIORITY_MANAGEMENT)
351 .forDevice(deviceId)
352 .forTable(CordVtnPipeline.TABLE_ZERO)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700353 .makePermanent()
354 .build();
355
356 processFlowRule(true, flowRule);
357 }
358
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700359 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dataPort,
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900360 PortNumber hostMgmtPort) {
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700361 TrafficSelector selector = DefaultTrafficSelector.builder()
362 .matchInPort(tunnelPort)
363 .build();
364
365 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
366 .transition(TABLE_TUNNEL_IN)
367 .build();
368
369 FlowRule flowRule = DefaultFlowRule.builder()
370 .fromApp(appId)
371 .withSelector(selector)
372 .withTreatment(treatment)
373 .withPriority(PRIORITY_DEFAULT)
374 .forDevice(deviceId)
375 .forTable(TABLE_IN_PORT)
376 .makePermanent()
377 .build();
378
379 processFlowRule(true, flowRule);
380
381 selector = DefaultTrafficSelector.builder()
Hyunsun Moon81a13562016-08-04 13:48:08 -0700382 .matchInPort(dataPort)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700383 .build();
384
385 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon1e88fef2016-08-04 14:00:35 -0700386 .transition(TABLE_DST)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700387 .build();
388
389 flowRule = DefaultFlowRule.builder()
390 .fromApp(appId)
391 .withSelector(selector)
392 .withTreatment(treatment)
393 .withPriority(PRIORITY_DEFAULT)
394 .forDevice(deviceId)
395 .forTable(TABLE_IN_PORT)
396 .makePermanent()
397 .build();
398
399 processFlowRule(true, flowRule);
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700400
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900401 if (hostMgmtPort != null) {
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700402 selector = DefaultTrafficSelector.builder()
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900403 .matchInPort(hostMgmtPort)
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700404 .build();
405
406 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon1e88fef2016-08-04 14:00:35 -0700407 .transition(TABLE_DST)
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700408 .build();
409
410 flowRule = DefaultFlowRule.builder()
411 .fromApp(appId)
412 .withSelector(selector)
413 .withTreatment(treatment)
414 .withPriority(PRIORITY_DEFAULT)
415 .forDevice(deviceId)
416 .forTable(TABLE_IN_PORT)
417 .makePermanent()
418 .build();
419
420 processFlowRule(true, flowRule);
421 }
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700422 }
423
Hyunsun Moon81a13562016-08-04 13:48:08 -0700424 private void processAccessTypeTable(DeviceId deviceId, PortNumber dataPort) {
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700425 TrafficSelector selector = DefaultTrafficSelector.builder()
426 .build();
427
428 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon81a13562016-08-04 13:48:08 -0700429 .setOutput(dataPort)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700430 .build();
431
432 FlowRule flowRule = DefaultFlowRule.builder()
433 .fromApp(appId)
434 .withSelector(selector)
435 .withTreatment(treatment)
436 .withPriority(PRIORITY_ZERO)
437 .forDevice(deviceId)
Hyunsun Moon1e88fef2016-08-04 14:00:35 -0700438 .forTable(TABLE_ACCESS)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700439 .makePermanent()
440 .build();
441
442 processFlowRule(true, flowRule);
443 }
444
Hyunsun Moon81a13562016-08-04 13:48:08 -0700445 private void processVlanTable(DeviceId deviceId, PortNumber dataPort) {
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700446 // for traffic going out to WAN, strip vid 500 and take through data plane interface
447 TrafficSelector selector = DefaultTrafficSelector.builder()
448 .matchVlanId(VLAN_WAN)
449 .build();
450
451 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
452 .popVlan()
Hyunsun Moon81a13562016-08-04 13:48:08 -0700453 .setOutput(dataPort)
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700454 .build();
455
456 FlowRule flowRule = DefaultFlowRule.builder()
457 .fromApp(appId)
458 .withSelector(selector)
459 .withTreatment(treatment)
460 .withPriority(PRIORITY_DEFAULT)
461 .forDevice(deviceId)
462 .forTable(TABLE_VLAN)
463 .makePermanent()
464 .build();
465
466 processFlowRule(true, flowRule);
467
468 selector = DefaultTrafficSelector.builder()
469 .matchVlanId(VLAN_WAN)
470 .matchEthType(Ethernet.TYPE_ARP)
471 .build();
472
473 treatment = DefaultTrafficTreatment.builder()
474 .setOutput(PortNumber.CONTROLLER)
475 .build();
476
477 flowRule = DefaultFlowRule.builder()
478 .fromApp(appId)
479 .withSelector(selector)
480 .withTreatment(treatment)
481 .withPriority(PRIORITY_HIGH)
482 .forDevice(deviceId)
483 .forTable(TABLE_VLAN)
484 .makePermanent()
485 .build();
486
487 processFlowRule(true, flowRule);
488 }
489
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900490 private PortNumber getPortNumber(DeviceId deviceId, String portName) {
491 return deviceService.getPorts(deviceId).stream()
Hyunsun Moonc031d9b2016-08-04 13:57:22 -0700492 .filter(p -> p.annotations().value(AnnotationKeys.PORT_NAME).equals(portName) &&
493 p.isEnabled())
494 .map(Port::number)
Hyunsun Moon2c3f0ee2017-04-06 16:47:21 +0900495 .findAny().orElse(null);
Hyunsun Moonacbc8ef2016-06-21 17:58:45 -0700496 }
Hyunsun Moone7e4bb32016-05-16 04:32:45 -0700497}