blob: 36767ea02760db951f60ee636fd93cd72ec277a1 [file] [log] [blame]
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001/*
2 * Copyright 2015 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.cordvtn;
17
Hyunsun Moonba290072015-12-16 20:53:23 -080018import com.google.common.collect.Lists;
19import com.google.common.collect.Maps;
20import org.onlab.packet.Ethernet;
Hyunsun Moon3467a262016-01-14 16:56:26 -080021import org.onlab.packet.IPv4;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080022import org.onlab.packet.Ip4Address;
Hyunsun Moonba290072015-12-16 20:53:23 -080023import org.onlab.packet.Ip4Prefix;
24import org.onlab.packet.IpAddress;
25import org.onlab.packet.IpPrefix;
26import org.onlab.packet.MacAddress;
Hyunsun Moon3467a262016-01-14 16:56:26 -080027import org.onlab.packet.TpPort;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080028import org.onlab.util.ItemNotFoundException;
29import org.onosproject.core.ApplicationId;
Hyunsun Moonba290072015-12-16 20:53:23 -080030import org.onosproject.core.DefaultGroupId;
31import org.onosproject.core.GroupId;
32import org.onosproject.mastership.MastershipService;
33import org.onosproject.net.Device;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080034import org.onosproject.net.DeviceId;
Hyunsun Moonba290072015-12-16 20:53:23 -080035import org.onosproject.net.Host;
Hyunsun Moon2bf68e72016-01-15 11:41:14 -080036import org.onosproject.net.Port;
Hyunsun Moonba290072015-12-16 20:53:23 -080037import org.onosproject.net.PortNumber;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080038import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
Hyunsun Moonba290072015-12-16 20:53:23 -080039import org.onosproject.net.device.DeviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080040import org.onosproject.net.driver.DefaultDriverData;
41import org.onosproject.net.driver.DefaultDriverHandler;
42import org.onosproject.net.driver.Driver;
43import org.onosproject.net.driver.DriverHandler;
44import org.onosproject.net.driver.DriverService;
Hyunsun Moonba290072015-12-16 20:53:23 -080045import org.onosproject.net.flow.DefaultFlowRule;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080046import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
Hyunsun Moonba290072015-12-16 20:53:23 -080048import org.onosproject.net.flow.FlowRule;
49import org.onosproject.net.flow.FlowRuleOperations;
50import org.onosproject.net.flow.FlowRuleOperationsContext;
51import org.onosproject.net.flow.FlowRuleService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080052import org.onosproject.net.flow.TrafficSelector;
53import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moonba290072015-12-16 20:53:23 -080054import org.onosproject.net.flow.criteria.Criterion;
55import org.onosproject.net.flow.criteria.EthCriterion;
56import org.onosproject.net.flow.criteria.IPCriterion;
57import org.onosproject.net.flow.criteria.PortCriterion;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080058import org.onosproject.net.flow.instructions.ExtensionPropertyException;
59import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moonba290072015-12-16 20:53:23 -080060import org.onosproject.net.flow.instructions.Instruction;
61import org.onosproject.net.flow.instructions.Instructions;
62import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
63import org.onosproject.net.group.DefaultGroupBucket;
64import org.onosproject.net.group.DefaultGroupDescription;
65import org.onosproject.net.group.DefaultGroupKey;
66import org.onosproject.net.group.Group;
67import org.onosproject.net.group.GroupBucket;
68import org.onosproject.net.group.GroupBuckets;
69import org.onosproject.net.group.GroupDescription;
70import org.onosproject.net.group.GroupKey;
71import org.onosproject.net.group.GroupService;
72import org.onosproject.openstackswitching.OpenstackNetwork;
73import org.onosproject.openstackswitching.OpenstackSubnet;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080074import org.slf4j.Logger;
75
Hyunsun Moonee37c442016-01-07 01:32:31 -080076import java.util.ArrayList;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080077import java.util.List;
Hyunsun Moonba290072015-12-16 20:53:23 -080078import java.util.Map;
Hyunsun Moonba290072015-12-16 20:53:23 -080079import java.util.Objects;
80import java.util.Set;
81import java.util.stream.Collectors;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080082
Hyunsun Moon05f528a2015-11-04 17:34:35 -080083import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moonba290072015-12-16 20:53:23 -080084import static org.onosproject.net.Device.Type.SWITCH;
85import static org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT;
86import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
87import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_SRC;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080088import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
Hyunsun Moonba290072015-12-16 20:53:23 -080089import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080090import static org.slf4j.LoggerFactory.getLogger;
91
92/**
Hyunsun Moonba290072015-12-16 20:53:23 -080093 * Populates rules for CORD VTN service.
Hyunsun Moon05f528a2015-11-04 17:34:35 -080094 */
Hyunsun Moonba290072015-12-16 20:53:23 -080095public class CordVtnRuleInstaller {
96
Hyunsun Moon05f528a2015-11-04 17:34:35 -080097 protected final Logger log = getLogger(getClass());
98
Hyunsun Moon3467a262016-01-14 16:56:26 -080099 private static final int TABLE_FIRST = 0;
100 private static final int TABLE_IN_PORT = 1;
101 private static final int TABLE_ACCESS_TYPE = 2;
102 private static final int TABLE_IN_SERVICE = 3;
103 private static final int TABLE_DST_IP = 4;
104 private static final int TABLE_TUNNEL_IN = 5;
Hyunsun Moonba290072015-12-16 20:53:23 -0800105
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800106 private static final int DEFAULT_PRIORITY = 5000;
Hyunsun Moonba290072015-12-16 20:53:23 -0800107 private static final int LOWER_PRIORITY = 4000;
108 private static final int LOWEST_PRIORITY = 0;
Hyunsun Moon3467a262016-01-14 16:56:26 -0800109 private static final int HIGHER_PRIORITY = 50000;
110
111 private static final int VXLAN_UDP_PORT = 4789;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800112
113 private final ApplicationId appId;
Hyunsun Moonba290072015-12-16 20:53:23 -0800114 private final FlowRuleService flowRuleService;
115 private final DeviceService deviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800116 private final DriverService driverService;
Hyunsun Moonba290072015-12-16 20:53:23 -0800117 private final GroupService groupService;
118 private final MastershipService mastershipService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800119 private final String tunnelType;
120
121 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800122 * Creates a new rule populator.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800123 *
124 * @param appId application id
Hyunsun Moonba290072015-12-16 20:53:23 -0800125 * @param flowRuleService flow rule service
126 * @param deviceService device service
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800127 * @param driverService driver service
128 * @param tunnelType tunnel type
129 */
130 public CordVtnRuleInstaller(ApplicationId appId,
Hyunsun Moonba290072015-12-16 20:53:23 -0800131 FlowRuleService flowRuleService,
132 DeviceService deviceService,
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800133 DriverService driverService,
Hyunsun Moonba290072015-12-16 20:53:23 -0800134 GroupService groupService,
135 MastershipService mastershipService,
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800136 String tunnelType) {
137 this.appId = appId;
Hyunsun Moonba290072015-12-16 20:53:23 -0800138 this.flowRuleService = flowRuleService;
139 this.deviceService = deviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800140 this.driverService = driverService;
Hyunsun Moonba290072015-12-16 20:53:23 -0800141 this.groupService = groupService;
142 this.mastershipService = mastershipService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800143 this.tunnelType = checkNotNull(tunnelType);
144 }
145
146 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800147 * Installs table miss rule to a give device.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800148 *
Hyunsun Moonba290072015-12-16 20:53:23 -0800149 * @param deviceId device id to install the rules
Hyunsun Moon3467a262016-01-14 16:56:26 -0800150 * @param phyPortName physical port name
151 * @param localIp local data plane ip address
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800152 */
Hyunsun Moon3467a262016-01-14 16:56:26 -0800153 public void init(DeviceId deviceId, String phyPortName, IpAddress localIp) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800154 // default is drop packets which can be accomplished without
155 // a table miss entry for all table.
Hyunsun Moon3467a262016-01-14 16:56:26 -0800156 PortNumber tunnelPort = getTunnelPort(deviceId);
157 PortNumber phyPort = getPhyPort(deviceId, phyPortName);
158
159 processFirstTable(deviceId, phyPort, localIp);
160 processInPortTable(deviceId, tunnelPort, phyPort);
161 processAccessTypeTable(deviceId, phyPort);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800162 }
163
164 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800165 * Populates basic rules that connect a VM to the other VMs in the system.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800166 *
Hyunsun Moonba290072015-12-16 20:53:23 -0800167 * @param host host
168 * @param hostIp host ip
169 * @param tunnelIp tunnel ip
170 * @param vNet openstack network
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800171 */
Hyunsun Moonba290072015-12-16 20:53:23 -0800172 public void populateBasicConnectionRules(Host host, IpAddress hostIp, IpAddress tunnelIp,
173 OpenstackNetwork vNet) {
174 // TODO we can get host ip from host.ip() after applying NetworkConfig host provider
175 checkNotNull(host);
176 checkNotNull(vNet);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800177
Hyunsun Moonba290072015-12-16 20:53:23 -0800178 DeviceId deviceId = host.location().deviceId();
179 if (!mastershipService.isLocalMaster(deviceId)) {
180 return;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800181 }
182
Hyunsun Moonba290072015-12-16 20:53:23 -0800183 PortNumber inPort = host.location().port();
184 MacAddress dstMac = host.mac();
185 long tunnelId = Long.parseLong(vNet.segmentId());
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800186
Hyunsun Moonba290072015-12-16 20:53:23 -0800187 OpenstackSubnet subnet = vNet.subnets().stream()
188 .findFirst()
189 .orElse(null);
190
191 if (subnet == null) {
192 log.error("Failed to get subnet for {}", host.id());
193 return;
194 }
195
196 populateLocalInPortRule(deviceId, inPort, hostIp);
197 populateDirectAccessRule(Ip4Prefix.valueOf(subnet.cidr()), Ip4Prefix.valueOf(subnet.cidr()));
198 populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
199 populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800200 }
201
202 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800203 * Removes basic rules related to a given flow information.
204 *
205 * @param host host to be removed
206 */
207 public void removeBasicConnectionRules(Host host) {
208 checkNotNull(host);
209
210 DeviceId deviceId = host.location().deviceId();
211 MacAddress mac = host.mac();
212 PortNumber port = host.location().port();
213 IpAddress ip = host.ipAddresses().stream().findFirst().orElse(null);
214
215 if (!mastershipService.isLocalMaster(deviceId)) {
216 return;
217 }
218
219 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
220 if (flowRule.deviceId().equals(deviceId)) {
221 PortNumber inPort = getInPort(flowRule);
222 if (inPort != null && inPort.equals(port)) {
223 processFlowRule(false, flowRule);
224 continue;
225 }
226 }
227
228 MacAddress dstMac = getDstMacFromTreatment(flowRule);
229 if (dstMac != null && dstMac.equals(mac)) {
230 processFlowRule(false, flowRule);
231 continue;
232 }
233
234 dstMac = getDstMacFromSelector(flowRule);
235 if (dstMac != null && dstMac.equals(mac)) {
236 processFlowRule(false, flowRule);
237 continue;
238 }
239
240 IpPrefix dstIp = getDstIpFromSelector(flowRule);
241 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
242 processFlowRule(false, flowRule);
243 }
Hyunsun Moonba290072015-12-16 20:53:23 -0800244 }
245
246 // TODO uninstall same network access rule in access table if no vm exists in the network
247 }
248
249 /**
Hyunsun Moonee37c442016-01-07 01:32:31 -0800250 * Populates service dependency rules.
251 *
252 * @param tService tenant cord service
253 * @param pService provider cord service
254 */
255 public void populateServiceDependencyRules(CordService tService, CordService pService) {
256 checkNotNull(tService);
257 checkNotNull(pService);
258
259 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
260 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
261 Ip4Address serviceIp = pService.serviceIp().getIp4Address();
262
263 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
264 Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
265
266 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
267 GroupId groupId = createServiceGroup(device.id(), pService);
268 outGroups.put(device.id(), groupId);
269
270 Set<PortNumber> vms = tService.hosts().keySet()
271 .stream()
272 .filter(host -> host.location().deviceId().equals(device.id()))
273 .map(host -> host.location().port())
274 .collect(Collectors.toSet());
275 inPorts.put(device.id(), vms);
276 }
277
278 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
279 populateDirectAccessRule(srcRange, dstRange);
280 populateInServiceRule(inPorts, outGroups);
281 }
282
283 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800284 * Removes service dependency rules.
285 *
286 * @param tService tenant cord service
287 * @param pService provider cord service
288 */
289 public void removeServiceDependencyRules(CordService tService, CordService pService) {
290 checkNotNull(tService);
291 checkNotNull(pService);
292
293 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
294 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
295 IpPrefix serviceIp = pService.serviceIp().toIpPrefix();
296
297 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
298 GroupKey groupKey = new DefaultGroupKey(pService.id().id().getBytes());
299
300 deviceService.getAvailableDevices(SWITCH).forEach(device -> {
301 Group group = groupService.getGroup(device.id(), groupKey);
302 if (group != null) {
303 outGroups.put(device.id(), group.id());
304 }
305 });
306
307 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
308 IpPrefix dstIp = getDstIpFromSelector(flowRule);
309 IpPrefix srcIp = getSrcIpFromSelector(flowRule);
310
311 if (dstIp != null && dstIp.equals(serviceIp)) {
312 processFlowRule(false, flowRule);
313 continue;
314 }
315
316 if (dstIp != null && srcIp != null) {
317 if (dstIp.equals(dstRange) && srcIp.equals(srcRange)) {
318 processFlowRule(false, flowRule);
319 continue;
320 }
321
322 if (dstIp.equals(srcRange) && srcIp.equals(dstRange)) {
323 processFlowRule(false, flowRule);
324 continue;
325 }
326 }
327
328 GroupId groupId = getGroupIdFromTreatment(flowRule);
329 if (groupId != null && groupId.equals(outGroups.get(flowRule.deviceId()))) {
330 processFlowRule(false, flowRule);
331 }
332 }
333
334 // TODO remove the group if it is not in use
335 }
336
337 /**
Hyunsun Moonee37c442016-01-07 01:32:31 -0800338 * Updates group buckets for a given service to all devices.
339 *
340 * @param service cord service
341 */
342 public void updateServiceGroup(CordService service) {
343 checkNotNull(service);
344
345 GroupKey groupKey = getGroupKey(service.id());
346
347 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
348 DeviceId deviceId = device.id();
349 if (!mastershipService.isLocalMaster(deviceId)) {
350 continue;
351 }
352
353 Group group = groupService.getGroup(deviceId, groupKey);
354 if (group == null) {
355 log.debug("No group exists for service {} in {}", service.id(), deviceId);
356 continue;
357 }
358
359 List<GroupBucket> oldBuckets = group.buckets().buckets();
360 List<GroupBucket> newBuckets = getServiceGroupBuckets(
361 deviceId, service.segmentationId(), service.hosts()).buckets();
362
363 if (oldBuckets.equals(newBuckets)) {
364 continue;
365 }
366
367 List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
368 bucketsToRemove.removeAll(newBuckets);
369 if (!bucketsToRemove.isEmpty()) {
370 groupService.removeBucketsFromGroup(
371 deviceId,
372 groupKey,
373 new GroupBuckets(bucketsToRemove),
374 groupKey, appId);
375 }
376
377 List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
378 bucketsToAdd.removeAll(oldBuckets);
379 if (!bucketsToAdd.isEmpty()) {
380 groupService.addBucketsToGroup(
381 deviceId,
382 groupKey,
383 new GroupBuckets(bucketsToAdd),
384 groupKey, appId);
385 }
386 }
387 }
388
389 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800390 * Populates default rules on the first table.
391 * The rules are for shuttling vxlan-encapped packets and supporting physical
392 * network connectivity.
Hyunsun Moonba290072015-12-16 20:53:23 -0800393 *
394 * @param deviceId device id
Hyunsun Moon3467a262016-01-14 16:56:26 -0800395 * @param phyPort physical port number
396 * @param localIp local data plane ip address
Hyunsun Moonba290072015-12-16 20:53:23 -0800397 */
Hyunsun Moon3467a262016-01-14 16:56:26 -0800398 private void processFirstTable(DeviceId deviceId, PortNumber phyPort, IpAddress localIp) {
399 // take vxlan packet out onto the physical port
400 TrafficSelector selector = DefaultTrafficSelector.builder()
401 .matchInPort(PortNumber.LOCAL)
402 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800403
Hyunsun Moon3467a262016-01-14 16:56:26 -0800404 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
405 .setOutput(phyPort)
406 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800407
Hyunsun Moon3467a262016-01-14 16:56:26 -0800408 FlowRule flowRule = DefaultFlowRule.builder()
409 .fromApp(appId)
410 .withSelector(selector)
411 .withTreatment(treatment)
412 .withPriority(HIGHER_PRIORITY)
413 .forDevice(deviceId)
414 .forTable(TABLE_FIRST)
415 .makePermanent()
416 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800417
Hyunsun Moon3467a262016-01-14 16:56:26 -0800418 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800419
Hyunsun Moon3467a262016-01-14 16:56:26 -0800420 // take a vxlan encap'd packet through the Linux stack
421 selector = DefaultTrafficSelector.builder()
422 .matchInPort(phyPort)
423 .matchEthType(Ethernet.TYPE_IPV4)
424 .matchIPProtocol(IPv4.PROTOCOL_UDP)
425 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
426 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800427
Hyunsun Moon3467a262016-01-14 16:56:26 -0800428 treatment = DefaultTrafficTreatment.builder()
429 .setOutput(PortNumber.LOCAL)
430 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800431
Hyunsun Moon3467a262016-01-14 16:56:26 -0800432 flowRule = DefaultFlowRule.builder()
433 .fromApp(appId)
434 .withSelector(selector)
435 .withTreatment(treatment)
436 .withPriority(HIGHER_PRIORITY)
437 .forDevice(deviceId)
438 .forTable(TABLE_FIRST)
439 .makePermanent()
440 .build();
441
442 processFlowRule(true, flowRule);
443
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800444 // take a packet to the local ip through Linux stack
445 selector = DefaultTrafficSelector.builder()
446 .matchInPort(phyPort)
447 .matchEthType(Ethernet.TYPE_IPV4)
448 .matchIPDst(localIp.toIpPrefix())
449 .build();
450
451 treatment = DefaultTrafficTreatment.builder()
452 .setOutput(PortNumber.LOCAL)
453 .build();
454
455 flowRule = DefaultFlowRule.builder()
456 .fromApp(appId)
457 .withSelector(selector)
458 .withTreatment(treatment)
459 .withPriority(HIGHER_PRIORITY)
460 .forDevice(deviceId)
461 .forTable(TABLE_FIRST)
462 .makePermanent()
463 .build();
464
465 processFlowRule(true, flowRule);
466
467 // take an arp packet from physical through Linux stack
468 selector = DefaultTrafficSelector.builder()
469 .matchInPort(phyPort)
470 .matchEthType(Ethernet.TYPE_ARP)
471 .build();
472
473 treatment = DefaultTrafficTreatment.builder()
474 .setOutput(PortNumber.LOCAL)
475 .build();
476
477 flowRule = DefaultFlowRule.builder()
478 .fromApp(appId)
479 .withSelector(selector)
480 .withTreatment(treatment)
481 .withPriority(HIGHER_PRIORITY)
482 .forDevice(deviceId)
483 .forTable(TABLE_FIRST)
484 .makePermanent()
485 .build();
486
487 processFlowRule(true, flowRule);
488
Hyunsun Moon3467a262016-01-14 16:56:26 -0800489 // take all else to the next table
490 selector = DefaultTrafficSelector.builder()
491 .build();
492
493 treatment = DefaultTrafficTreatment.builder()
494 .transition(TABLE_IN_PORT)
495 .build();
496
497 flowRule = DefaultFlowRule.builder()
498 .fromApp(appId)
499 .withSelector(selector)
500 .withTreatment(treatment)
501 .withPriority(LOWEST_PRIORITY)
502 .forDevice(deviceId)
503 .forTable(TABLE_FIRST)
504 .makePermanent()
505 .build();
506
507 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800508 }
509
510 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800511 * Forward table miss packets in ACCESS_TYPE table to physical port.
Hyunsun Moonba290072015-12-16 20:53:23 -0800512 *
513 * @param deviceId device id
Hyunsun Moon3467a262016-01-14 16:56:26 -0800514 * @param phyPort physical port number
Hyunsun Moonba290072015-12-16 20:53:23 -0800515 */
Hyunsun Moon3467a262016-01-14 16:56:26 -0800516 private void processAccessTypeTable(DeviceId deviceId, PortNumber phyPort) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800517 TrafficSelector selector = DefaultTrafficSelector.builder()
518 .build();
519
520 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon3467a262016-01-14 16:56:26 -0800521 .setOutput(phyPort)
Hyunsun Moonba290072015-12-16 20:53:23 -0800522 .build();
523
524 FlowRule flowRule = DefaultFlowRule.builder()
525 .fromApp(appId)
526 .withSelector(selector)
527 .withTreatment(treatment)
528 .withPriority(LOWEST_PRIORITY)
529 .forDevice(deviceId)
530 .forTable(TABLE_ACCESS_TYPE)
531 .makePermanent()
532 .build();
533
534 processFlowRule(true, flowRule);
535 }
536
537 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800538 * Populates default rules for IN_PORT table.
539 * All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
540 * from physical port to ACCESS_TYPE table.
Hyunsun Moonba290072015-12-16 20:53:23 -0800541 *
542 * @param deviceId device id to install the rules
Hyunsun Moon3467a262016-01-14 16:56:26 -0800543 * @param tunnelPort tunnel port number
544 * @param phyPort physical port number
Hyunsun Moonba290072015-12-16 20:53:23 -0800545 */
Hyunsun Moon3467a262016-01-14 16:56:26 -0800546 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber phyPort) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800547 checkNotNull(tunnelPort);
548
549 TrafficSelector selector = DefaultTrafficSelector.builder()
550 .matchInPort(tunnelPort)
551 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800552
Hyunsun Moonba290072015-12-16 20:53:23 -0800553 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
554 .transition(TABLE_TUNNEL_IN)
555 .build();
556
557 FlowRule flowRule = DefaultFlowRule.builder()
558 .fromApp(appId)
559 .withSelector(selector)
560 .withTreatment(treatment)
561 .withPriority(DEFAULT_PRIORITY)
562 .forDevice(deviceId)
563 .forTable(TABLE_IN_PORT)
564 .makePermanent()
565 .build();
566
567 processFlowRule(true, flowRule);
Hyunsun Moon3467a262016-01-14 16:56:26 -0800568
569 selector = DefaultTrafficSelector.builder()
570 .matchInPort(phyPort)
571 .build();
572
573 treatment = DefaultTrafficTreatment.builder()
574 .transition(TABLE_DST_IP)
575 .build();
576
577 flowRule = DefaultFlowRule.builder()
578 .fromApp(appId)
579 .withSelector(selector)
580 .withTreatment(treatment)
581 .withPriority(DEFAULT_PRIORITY)
582 .forDevice(deviceId)
583 .forTable(TABLE_IN_PORT)
584 .makePermanent()
585 .build();
586
587 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800588 }
589
590 /**
591 * Populates rules for local in port in IN_PORT table.
592 * Flows from a given in port, whose source IP is service IP transition
593 * to DST_TYPE table. Other flows transition to IN_SERVICE table.
594 *
595 * @param deviceId device id to install the rules
596 * @param inPort in port
597 * @param srcIp source ip
598 */
599 private void populateLocalInPortRule(DeviceId deviceId, PortNumber inPort, IpAddress srcIp) {
600 TrafficSelector selector = DefaultTrafficSelector.builder()
601 .matchInPort(inPort)
602 .matchEthType(Ethernet.TYPE_IPV4)
603 .matchIPSrc(srcIp.toIpPrefix())
604 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800605
Hyunsun Moonba290072015-12-16 20:53:23 -0800606 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
607 .transition(TABLE_ACCESS_TYPE)
608 .build();
609
610
611 FlowRule flowRule = DefaultFlowRule.builder()
612 .fromApp(appId)
613 .withSelector(selector)
614 .withTreatment(treatment)
615 .withPriority(DEFAULT_PRIORITY)
616 .forDevice(deviceId)
617 .forTable(TABLE_IN_PORT)
618 .makePermanent()
619 .build();
620
621 processFlowRule(true, flowRule);
622
623 selector = DefaultTrafficSelector.builder()
624 .matchInPort(inPort)
625 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800626
Hyunsun Moonba290072015-12-16 20:53:23 -0800627 treatment = DefaultTrafficTreatment.builder()
628 .transition(TABLE_IN_SERVICE)
629 .build();
630
631 flowRule = DefaultFlowRule.builder()
632 .fromApp(appId)
633 .withSelector(selector)
634 .withTreatment(treatment)
635 .withPriority(LOWER_PRIORITY)
636 .forDevice(deviceId)
637 .forTable(TABLE_IN_PORT)
638 .makePermanent()
639 .build();
640
641 processFlowRule(true, flowRule);
642 }
643
644 /**
645 * Populates direct VM access rules for ACCESS_TYPE table.
646 * These rules are installed to all devices.
647 *
648 * @param srcRange source ip range
649 * @param dstRange destination ip range
650 */
651 private void populateDirectAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange) {
652 TrafficSelector selector = DefaultTrafficSelector.builder()
653 .matchEthType(Ethernet.TYPE_IPV4)
654 .matchIPSrc(srcRange)
655 .matchIPDst(dstRange)
656 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800657
Hyunsun Moonba290072015-12-16 20:53:23 -0800658 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
659 .transition(TABLE_DST_IP)
660 .build();
661
662 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
663 FlowRule flowRuleDirect = DefaultFlowRule.builder()
664 .fromApp(appId)
665 .withSelector(selector)
666 .withTreatment(treatment)
667 .withPriority(LOWER_PRIORITY)
668 .forDevice(device.id())
669 .forTable(TABLE_ACCESS_TYPE)
670 .makePermanent()
671 .build();
672
673 processFlowRule(true, flowRuleDirect);
674 }
675 }
676
677 /**
678 * Populates indirect service access rules for ACCESS_TYPE table.
679 * These rules are installed to all devices.
680 *
681 * @param srcRange source range
682 * @param serviceIp service ip
683 * @param outGroups list of output group
684 */
685 private void populateIndirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
686 Map<DeviceId, GroupId> outGroups) {
687 TrafficSelector selector = DefaultTrafficSelector.builder()
688 .matchEthType(Ethernet.TYPE_IPV4)
689 .matchIPSrc(srcRange)
690 .matchIPDst(serviceIp.toIpPrefix())
691 .build();
692
693 for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
694 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
695 .group(outGroup.getValue())
696 .build();
697
698 FlowRule flowRule = DefaultFlowRule.builder()
699 .fromApp(appId)
700 .withSelector(selector)
701 .withTreatment(treatment)
702 .withPriority(DEFAULT_PRIORITY)
703 .forDevice(outGroup.getKey())
704 .forTable(TABLE_ACCESS_TYPE)
705 .makePermanent()
706 .build();
707
708 processFlowRule(true, flowRule);
709 }
710 }
711
712 /**
713 * Populates flow rules for IN_SERVICE table.
714 *
715 * @param inPorts list of inports related to the service for each device
716 * @param outGroups set of output groups
717 */
718 private void populateInServiceRule(Map<DeviceId, Set<PortNumber>> inPorts, Map<DeviceId, GroupId> outGroups) {
719 checkNotNull(inPorts);
720 checkNotNull(outGroups);
721
722 for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
723 Set<PortNumber> ports = entry.getValue();
724 DeviceId deviceId = entry.getKey();
725
726 GroupId groupId = outGroups.get(deviceId);
727 if (groupId == null) {
728 continue;
729 }
730
731 ports.stream().forEach(port -> {
732 TrafficSelector selector = DefaultTrafficSelector.builder()
733 .matchInPort(port)
734 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800735
Hyunsun Moonba290072015-12-16 20:53:23 -0800736 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
737 .group(groupId)
738 .build();
739
740 FlowRule flowRule = DefaultFlowRule.builder()
741 .fromApp(appId)
742 .withSelector(selector)
743 .withTreatment(treatment)
744 .withPriority(DEFAULT_PRIORITY)
745 .forDevice(deviceId)
746 .forTable(TABLE_IN_SERVICE)
747 .makePermanent()
748 .build();
749
750 processFlowRule(true, flowRule);
751 });
752 }
753 }
754
755 /**
756 * Populates flow rules for DST_IP table.
757 *
758 * @param deviceId device id
759 * @param inPort in port
760 * @param dstMac mac address
761 * @param dstIp destination ip
762 * @param tunnelId tunnel id
763 * @param tunnelIp tunnel remote ip
764 */
765 private void populateDstIpRule(DeviceId deviceId, PortNumber inPort, MacAddress dstMac,
766 IpAddress dstIp, long tunnelId, IpAddress tunnelIp) {
767 TrafficSelector selector = DefaultTrafficSelector.builder()
768 .matchEthType(Ethernet.TYPE_IPV4)
769 .matchIPDst(dstIp.toIpPrefix())
770 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800771
Hyunsun Moonba290072015-12-16 20:53:23 -0800772 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
773 .setEthDst(dstMac)
774 .setOutput(inPort)
775 .build();
776
777 FlowRule flowRule = DefaultFlowRule.builder()
778 .fromApp(appId)
779 .withSelector(selector)
780 .withTreatment(treatment)
781 .withPriority(DEFAULT_PRIORITY)
782 .forDevice(deviceId)
783 .forTable(TABLE_DST_IP)
784 .makePermanent()
785 .build();
786
787 processFlowRule(true, flowRule);
788
789 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
790 if (device.id().equals(deviceId)) {
791 continue;
792 }
793
794 ExtensionTreatment tunnelDst = getTunnelDst(device.id(), tunnelIp.getIp4Address());
795 if (tunnelDst == null) {
796 continue;
797 }
798
799 treatment = DefaultTrafficTreatment.builder()
800 .setEthDst(dstMac)
801 .setTunnelId(tunnelId)
802 .extension(tunnelDst, device.id())
803 .setOutput(getTunnelPort(device.id()))
804 .build();
805
806 flowRule = DefaultFlowRule.builder()
807 .fromApp(appId)
808 .withSelector(selector)
809 .withTreatment(treatment)
810 .withPriority(DEFAULT_PRIORITY)
811 .forDevice(device.id())
812 .forTable(TABLE_DST_IP)
813 .makePermanent()
814 .build();
815
816 processFlowRule(true, flowRule);
817 }
818 }
819
820 /**
821 * Populates flow rules for TUNNEL_ID table.
822 *
823 * @param deviceId device id
824 * @param inPort in port
825 * @param mac mac address
826 * @param tunnelId tunnel id
827 */
828 private void populateTunnelInRule(DeviceId deviceId, PortNumber inPort, MacAddress mac, long tunnelId) {
829 TrafficSelector selector = DefaultTrafficSelector.builder()
830 .matchTunnelId(tunnelId)
831 .matchEthDst(mac)
832 .build();
833
834 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
835 .setOutput(inPort)
836 .build();
837
838 FlowRule flowRule = DefaultFlowRule.builder()
839 .fromApp(appId)
840 .withSelector(selector)
841 .withTreatment(treatment)
842 .withPriority(DEFAULT_PRIORITY)
843 .forDevice(deviceId)
844 .forTable(TABLE_TUNNEL_IN)
845 .makePermanent()
846 .build();
847
848 processFlowRule(true, flowRule);
849 }
850
851 /**
852 * Installs or uninstall a given rule.
853 *
854 * @param install true to install, false to uninstall
855 * @param rule rule
856 */
857 private void processFlowRule(boolean install, FlowRule rule) {
858 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
859 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
860
861 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
862 @Override
863 public void onError(FlowRuleOperations ops) {
864 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
865 }
866 }));
867 }
868
869 /**
870 * Returns tunnel port of the device.
871 *
872 * @param deviceId device id
873 * @return tunnel port number, or null if no tunnel port exists on a given device
874 */
875 private PortNumber getTunnelPort(DeviceId deviceId) {
Hyunsun Moon2bf68e72016-01-15 11:41:14 -0800876 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moonba290072015-12-16 20:53:23 -0800877 .filter(p -> p.annotations().value("portName").contains(tunnelType))
Hyunsun Moon2bf68e72016-01-15 11:41:14 -0800878 .findFirst().orElse(null);
879
880 return port == null ? null : port.number();
Hyunsun Moonba290072015-12-16 20:53:23 -0800881 }
882
883 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800884 * Returns physical port name of a given device.
885 *
886 * @param deviceId device id
887 * @param phyPortName physical port name
888 * @return physical port number, or null if no physical port exists
889 */
890 private PortNumber getPhyPort(DeviceId deviceId, String phyPortName) {
Hyunsun Moon2bf68e72016-01-15 11:41:14 -0800891 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon3467a262016-01-14 16:56:26 -0800892 .filter(p -> p.annotations().value("portName").contains(phyPortName) &&
893 p.isEnabled())
Hyunsun Moon2bf68e72016-01-15 11:41:14 -0800894 .findFirst().orElse(null);
895
896 return port == null ? null : port.number();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800897 }
898
899 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800900 * Returns the inport from a given flow rule if the rule contains the match of it.
901 *
902 * @param flowRule flow rule
903 * @return port number, or null if the rule doesn't have inport match
904 */
905 private PortNumber getInPort(FlowRule flowRule) {
906 Criterion criterion = flowRule.selector().getCriterion(IN_PORT);
907 if (criterion != null && criterion instanceof PortCriterion) {
908 PortCriterion port = (PortCriterion) criterion;
909 return port.port();
910 } else {
911 return null;
912 }
913 }
914
915 /**
916 * Returns the destination mac address from a given flow rule if the rule
917 * contains the instruction of it.
918 *
919 * @param flowRule flow rule
920 * @return mac address, or null if the rule doesn't have destination mac instruction
921 */
922 private MacAddress getDstMacFromTreatment(FlowRule flowRule) {
923 Instruction instruction = flowRule.treatment().allInstructions().stream()
924 .filter(inst -> inst instanceof ModEtherInstruction &&
925 ((ModEtherInstruction) inst).subtype().equals(ETH_DST))
926 .findFirst()
927 .orElse(null);
928
929 if (instruction == null) {
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800930 return null;
931 }
932
Hyunsun Moonba290072015-12-16 20:53:23 -0800933 return ((ModEtherInstruction) instruction).mac();
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800934 }
935
936 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800937 * Returns the destination mac address from a given flow rule if the rule
938 * contains the match of it.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800939 *
Hyunsun Moonba290072015-12-16 20:53:23 -0800940 * @param flowRule flow rule
941 * @return mac address, or null if the rule doesn't have destination mac match
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800942 */
Hyunsun Moonba290072015-12-16 20:53:23 -0800943 private MacAddress getDstMacFromSelector(FlowRule flowRule) {
944 Criterion criterion = flowRule.selector().getCriterion(Criterion.Type.ETH_DST);
945 if (criterion != null && criterion instanceof EthCriterion) {
946 EthCriterion eth = (EthCriterion) criterion;
947 return eth.mac();
948 } else {
949 return null;
950 }
951 }
952
953 /**
954 * Returns the destination IP from a given flow rule if the rule contains
955 * the match of it.
956 *
957 * @param flowRule flow rule
958 * @return ip prefix, or null if the rule doesn't have ip match
959 */
960 private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
961 Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
962 if (criterion != null && criterion instanceof IPCriterion) {
963 IPCriterion ip = (IPCriterion) criterion;
964 return ip.ip();
965 } else {
966 return null;
967 }
968 }
969
970 /**
971 * Returns the source IP from a given flow rule if the rule contains
972 * the match of it.
973 *
974 * @param flowRule flow rule
975 * @return ip prefix, or null if the rule doesn't have ip match
976 */
977 private IpPrefix getSrcIpFromSelector(FlowRule flowRule) {
978 Criterion criterion = flowRule.selector().getCriterion(IPV4_SRC);
979 if (criterion != null && criterion instanceof IPCriterion) {
980 IPCriterion ip = (IPCriterion) criterion;
981 return ip.ip();
982 } else {
983 return null;
984 }
985 }
986
987 /**
988 * Returns the group ID from a given flow rule if the rule contains the
989 * treatment of it.
990 *
991 * @param flowRule flow rule
992 * @return group id, or null if the rule doesn't have group instruction
993 */
994 private GroupId getGroupIdFromTreatment(FlowRule flowRule) {
995 Instruction instruction = flowRule.treatment().allInstructions().stream()
996 .filter(inst -> inst instanceof Instructions.GroupInstruction)
997 .findFirst()
998 .orElse(null);
999
1000 if (instruction == null) {
1001 return null;
1002 }
1003
1004 return ((Instructions.GroupInstruction) instruction).groupId();
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001005 }
1006
1007 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -08001008 * Creates a new group for a given service.
1009 *
1010 * @param deviceId device id to create a group
1011 * @param service cord service
1012 * @return group id, or null if it fails to create
1013 */
1014 private GroupId createServiceGroup(DeviceId deviceId, CordService service) {
1015 checkNotNull(service);
1016
1017 GroupKey groupKey = getGroupKey(service.id());
1018 Group group = groupService.getGroup(deviceId, groupKey);
1019 GroupId groupId = getGroupId(service.id(), deviceId);
1020
1021 if (group != null) {
1022 log.debug("Group {} is already exist in {}", service.id(), deviceId);
1023 return groupId;
1024 }
1025
1026 GroupBuckets buckets = getServiceGroupBuckets(deviceId, service.segmentationId(), service.hosts());
1027 GroupDescription groupDescription = new DefaultGroupDescription(
1028 deviceId,
1029 GroupDescription.Type.SELECT,
1030 buckets,
1031 groupKey,
1032 groupId.id(),
1033 appId);
1034
1035 groupService.addGroup(groupDescription);
1036
1037 return groupId;
1038 }
1039
1040 /**
1041 * Returns group buckets for a given device.
1042 *
1043 * @param deviceId device id
1044 * @param tunnelId tunnel id
1045 * @param hosts list of host
1046 * @return group buckets
1047 */
1048 private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId, Map<Host, IpAddress> hosts) {
1049 List<GroupBucket> buckets = Lists.newArrayList();
1050
1051 for (Map.Entry<Host, IpAddress> entry : hosts.entrySet()) {
1052 Host host = entry.getKey();
1053 Ip4Address remoteIp = entry.getValue().getIp4Address();
1054 DeviceId hostDevice = host.location().deviceId();
1055
1056 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
1057 .builder()
1058 .setEthDst(host.mac());
1059
1060 if (deviceId.equals(hostDevice)) {
1061 tBuilder.setOutput(host.location().port());
1062 } else {
1063 ExtensionTreatment tunnelDst = getTunnelDst(deviceId, remoteIp);
1064 if (tunnelDst == null) {
1065 continue;
1066 }
1067
1068 tBuilder.extension(tunnelDst, deviceId)
1069 .setTunnelId(tunnelId)
1070 .setOutput(getTunnelPort(hostDevice));
1071 }
1072
1073 buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
1074 }
1075
1076 return new GroupBuckets(buckets);
1077 }
1078
1079 /**
1080 * Returns globally unique group ID.
1081 *
1082 * @param serviceId service id
1083 * @param deviceId device id
1084 * @return group id
1085 */
1086 private GroupId getGroupId(CordServiceId serviceId, DeviceId deviceId) {
1087 return new DefaultGroupId(Objects.hash(serviceId, deviceId));
1088 }
1089
1090 /**
1091 * Returns group key of a service.
1092 *
1093 * @param serviceId service id
1094 * @return group key
1095 */
1096 private GroupKey getGroupKey(CordServiceId serviceId) {
1097 return new DefaultGroupKey(serviceId.id().getBytes());
1098 }
1099
1100 /**
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001101 * Returns extension instruction to set tunnel destination.
1102 *
1103 * @param deviceId device id
1104 * @param remoteIp tunnel destination address
1105 * @return extension treatment or null if it fails to get instruction
1106 */
Hyunsun Moonba290072015-12-16 20:53:23 -08001107 private ExtensionTreatment getTunnelDst(DeviceId deviceId, Ip4Address remoteIp) {
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001108 try {
1109 Driver driver = driverService.getDriver(deviceId);
Hyunsun Moonba290072015-12-16 20:53:23 -08001110 DefaultDriverData driverData = new DefaultDriverData(driver, deviceId);
1111 DriverHandler handler = new DefaultDriverHandler(driverData);
1112 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001113
Hyunsun Moonba290072015-12-16 20:53:23 -08001114 ExtensionTreatment treatment =
1115 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001116 treatment.setPropertyValue("tunnelDst", remoteIp);
1117
1118 return treatment;
Hyunsun Moonba290072015-12-16 20:53:23 -08001119 } catch (ItemNotFoundException | UnsupportedOperationException |
1120 ExtensionPropertyException e) {
1121 log.error("Failed to get extension instruction {}", deviceId);
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001122 return null;
1123 }
1124 }
1125}
Hyunsun Moonba290072015-12-16 20:53:23 -08001126