blob: 864c5b646ef40a7b0e3d4d4a47a1eb9c494d86c6 [file] [log] [blame]
Hyunsun Moon9f0814b2015-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 Moonc71231d2015-12-16 20:53:23 -080018import com.google.common.collect.Lists;
19import com.google.common.collect.Maps;
20import org.onlab.packet.Ethernet;
Hyunsun Moon4a915152016-01-14 16:56:26 -080021import org.onlab.packet.IPv4;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080022import org.onlab.packet.Ip4Address;
Hyunsun Moonc71231d2015-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 Moon4a915152016-01-14 16:56:26 -080027import org.onlab.packet.TpPort;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080028import org.onlab.util.ItemNotFoundException;
29import org.onosproject.core.ApplicationId;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080034import org.onosproject.net.DeviceId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080035import org.onosproject.net.Host;
Hyunsun Moon5a4346f2016-01-15 11:41:14 -080036import org.onosproject.net.Port;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080037import org.onosproject.net.PortNumber;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080038import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080039import org.onosproject.net.device.DeviceService;
Hyunsun Moon9f0814b2015-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 Moonc71231d2015-12-16 20:53:23 -080045import org.onosproject.net.flow.DefaultFlowRule;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080046import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080052import org.onosproject.net.flow.TrafficSelector;
53import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080058import org.onosproject.net.flow.instructions.ExtensionPropertyException;
59import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080074import org.slf4j.Logger;
75
Hyunsun Moon4161e6f2016-01-07 01:32:31 -080076import java.util.ArrayList;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080077import java.util.List;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080078import java.util.Map;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080079import java.util.Objects;
80import java.util.Set;
81import java.util.stream.Collectors;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080082
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080083import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080088import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080089import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080090import static org.slf4j.LoggerFactory.getLogger;
91
92/**
Hyunsun Moonc71231d2015-12-16 20:53:23 -080093 * Populates rules for CORD VTN service.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080094 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -080095public class CordVtnRuleInstaller {
96
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080097 protected final Logger log = getLogger(getClass());
98
Hyunsun Moon4a915152016-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 Moonc71231d2015-12-16 20:53:23 -0800105
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800106 private static final int DEFAULT_PRIORITY = 5000;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800107 private static final int LOWER_PRIORITY = 4000;
108 private static final int LOWEST_PRIORITY = 0;
Hyunsun Moon4a915152016-01-14 16:56:26 -0800109 private static final int HIGHER_PRIORITY = 50000;
110
111 private static final int VXLAN_UDP_PORT = 4789;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800112
113 private final ApplicationId appId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800114 private final FlowRuleService flowRuleService;
115 private final DeviceService deviceService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800116 private final DriverService driverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800117 private final GroupService groupService;
118 private final MastershipService mastershipService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800119 private final String tunnelType;
120
121 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800122 * Creates a new rule populator.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800123 *
124 * @param appId application id
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800125 * @param flowRuleService flow rule service
126 * @param deviceService device service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800127 * @param driverService driver service
128 * @param tunnelType tunnel type
129 */
130 public CordVtnRuleInstaller(ApplicationId appId,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800131 FlowRuleService flowRuleService,
132 DeviceService deviceService,
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800133 DriverService driverService,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800134 GroupService groupService,
135 MastershipService mastershipService,
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800136 String tunnelType) {
137 this.appId = appId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800138 this.flowRuleService = flowRuleService;
139 this.deviceService = deviceService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800140 this.driverService = driverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800141 this.groupService = groupService;
142 this.mastershipService = mastershipService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800143 this.tunnelType = checkNotNull(tunnelType);
144 }
145
146 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800147 * Installs table miss rule to a give device.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800148 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800149 * @param deviceId device id to install the rules
Hyunsun Moon4a915152016-01-14 16:56:26 -0800150 * @param phyPortName physical port name
151 * @param localIp local data plane ip address
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800152 */
Hyunsun Moon4a915152016-01-14 16:56:26 -0800153 public void init(DeviceId deviceId, String phyPortName, IpAddress localIp) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800154 // default is drop packets which can be accomplished without
155 // a table miss entry for all table.
Hyunsun Moon4a915152016-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 Moon9f0814b2015-11-04 17:34:35 -0800162 }
163
164 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800165 * Populates basic rules that connect a VM to the other VMs in the system.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800166 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800167 * @param host host
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800168 * @param tunnelIp tunnel ip
169 * @param vNet openstack network
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800170 */
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800171 public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, OpenstackNetwork vNet) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800172 checkNotNull(host);
173 checkNotNull(vNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800174
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800175 DeviceId deviceId = host.location().deviceId();
176 if (!mastershipService.isLocalMaster(deviceId)) {
177 return;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800178 }
179
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800180 PortNumber inPort = host.location().port();
181 MacAddress dstMac = host.mac();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800182 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800183 long tunnelId = Long.parseLong(vNet.segmentId());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800184
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800185 OpenstackSubnet subnet = vNet.subnets().stream()
186 .findFirst()
187 .orElse(null);
188
189 if (subnet == null) {
190 log.error("Failed to get subnet for {}", host.id());
191 return;
192 }
193
194 populateLocalInPortRule(deviceId, inPort, hostIp);
195 populateDirectAccessRule(Ip4Prefix.valueOf(subnet.cidr()), Ip4Prefix.valueOf(subnet.cidr()));
196 populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
197 populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800198 }
199
200 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800201 * Removes basic rules related to a given flow information.
202 *
203 * @param host host to be removed
204 */
205 public void removeBasicConnectionRules(Host host) {
206 checkNotNull(host);
207
208 DeviceId deviceId = host.location().deviceId();
209 MacAddress mac = host.mac();
210 PortNumber port = host.location().port();
211 IpAddress ip = host.ipAddresses().stream().findFirst().orElse(null);
212
213 if (!mastershipService.isLocalMaster(deviceId)) {
214 return;
215 }
216
217 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
218 if (flowRule.deviceId().equals(deviceId)) {
219 PortNumber inPort = getInPort(flowRule);
220 if (inPort != null && inPort.equals(port)) {
221 processFlowRule(false, flowRule);
222 continue;
223 }
224 }
225
226 MacAddress dstMac = getDstMacFromTreatment(flowRule);
227 if (dstMac != null && dstMac.equals(mac)) {
228 processFlowRule(false, flowRule);
229 continue;
230 }
231
232 dstMac = getDstMacFromSelector(flowRule);
233 if (dstMac != null && dstMac.equals(mac)) {
234 processFlowRule(false, flowRule);
235 continue;
236 }
237
238 IpPrefix dstIp = getDstIpFromSelector(flowRule);
239 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
240 processFlowRule(false, flowRule);
241 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800242 }
243
244 // TODO uninstall same network access rule in access table if no vm exists in the network
245 }
246
247 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800248 * Populates service dependency rules.
249 *
250 * @param tService tenant cord service
251 * @param pService provider cord service
252 */
253 public void populateServiceDependencyRules(CordService tService, CordService pService) {
254 checkNotNull(tService);
255 checkNotNull(pService);
256
257 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
258 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
259 Ip4Address serviceIp = pService.serviceIp().getIp4Address();
260
261 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
262 Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
263
264 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
265 GroupId groupId = createServiceGroup(device.id(), pService);
266 outGroups.put(device.id(), groupId);
267
268 Set<PortNumber> vms = tService.hosts().keySet()
269 .stream()
270 .filter(host -> host.location().deviceId().equals(device.id()))
271 .map(host -> host.location().port())
272 .collect(Collectors.toSet());
273 inPorts.put(device.id(), vms);
274 }
275
276 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
277 populateDirectAccessRule(srcRange, dstRange);
278 populateInServiceRule(inPorts, outGroups);
279 }
280
281 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800282 * Removes service dependency rules.
283 *
284 * @param tService tenant cord service
285 * @param pService provider cord service
286 */
287 public void removeServiceDependencyRules(CordService tService, CordService pService) {
288 checkNotNull(tService);
289 checkNotNull(pService);
290
291 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
292 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
293 IpPrefix serviceIp = pService.serviceIp().toIpPrefix();
294
295 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
296 GroupKey groupKey = new DefaultGroupKey(pService.id().id().getBytes());
297
298 deviceService.getAvailableDevices(SWITCH).forEach(device -> {
299 Group group = groupService.getGroup(device.id(), groupKey);
300 if (group != null) {
301 outGroups.put(device.id(), group.id());
302 }
303 });
304
305 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
306 IpPrefix dstIp = getDstIpFromSelector(flowRule);
307 IpPrefix srcIp = getSrcIpFromSelector(flowRule);
308
309 if (dstIp != null && dstIp.equals(serviceIp)) {
310 processFlowRule(false, flowRule);
311 continue;
312 }
313
314 if (dstIp != null && srcIp != null) {
315 if (dstIp.equals(dstRange) && srcIp.equals(srcRange)) {
316 processFlowRule(false, flowRule);
317 continue;
318 }
319
320 if (dstIp.equals(srcRange) && srcIp.equals(dstRange)) {
321 processFlowRule(false, flowRule);
322 continue;
323 }
324 }
325
326 GroupId groupId = getGroupIdFromTreatment(flowRule);
327 if (groupId != null && groupId.equals(outGroups.get(flowRule.deviceId()))) {
328 processFlowRule(false, flowRule);
329 }
330 }
331
332 // TODO remove the group if it is not in use
333 }
334
335 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800336 * Updates group buckets for a given service to all devices.
337 *
338 * @param service cord service
339 */
340 public void updateServiceGroup(CordService service) {
341 checkNotNull(service);
342
343 GroupKey groupKey = getGroupKey(service.id());
344
345 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
346 DeviceId deviceId = device.id();
347 if (!mastershipService.isLocalMaster(deviceId)) {
348 continue;
349 }
350
351 Group group = groupService.getGroup(deviceId, groupKey);
352 if (group == null) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800353 log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800354 continue;
355 }
356
357 List<GroupBucket> oldBuckets = group.buckets().buckets();
358 List<GroupBucket> newBuckets = getServiceGroupBuckets(
359 deviceId, service.segmentationId(), service.hosts()).buckets();
360
361 if (oldBuckets.equals(newBuckets)) {
362 continue;
363 }
364
365 List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
366 bucketsToRemove.removeAll(newBuckets);
367 if (!bucketsToRemove.isEmpty()) {
368 groupService.removeBucketsFromGroup(
369 deviceId,
370 groupKey,
371 new GroupBuckets(bucketsToRemove),
372 groupKey, appId);
373 }
374
375 List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
376 bucketsToAdd.removeAll(oldBuckets);
377 if (!bucketsToAdd.isEmpty()) {
378 groupService.addBucketsToGroup(
379 deviceId,
380 groupKey,
381 new GroupBuckets(bucketsToAdd),
382 groupKey, appId);
383 }
384 }
385 }
386
387 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800388 * Populates default rules on the first table.
389 * The rules are for shuttling vxlan-encapped packets and supporting physical
390 * network connectivity.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800391 *
392 * @param deviceId device id
Hyunsun Moon4a915152016-01-14 16:56:26 -0800393 * @param phyPort physical port number
394 * @param localIp local data plane ip address
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800395 */
Hyunsun Moon4a915152016-01-14 16:56:26 -0800396 private void processFirstTable(DeviceId deviceId, PortNumber phyPort, IpAddress localIp) {
397 // take vxlan packet out onto the physical port
398 TrafficSelector selector = DefaultTrafficSelector.builder()
399 .matchInPort(PortNumber.LOCAL)
400 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800401
Hyunsun Moon4a915152016-01-14 16:56:26 -0800402 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
403 .setOutput(phyPort)
404 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800405
Hyunsun Moon4a915152016-01-14 16:56:26 -0800406 FlowRule flowRule = DefaultFlowRule.builder()
407 .fromApp(appId)
408 .withSelector(selector)
409 .withTreatment(treatment)
410 .withPriority(HIGHER_PRIORITY)
411 .forDevice(deviceId)
412 .forTable(TABLE_FIRST)
413 .makePermanent()
414 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800415
Hyunsun Moon4a915152016-01-14 16:56:26 -0800416 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800417
Hyunsun Moon4a915152016-01-14 16:56:26 -0800418 // take a vxlan encap'd packet through the Linux stack
419 selector = DefaultTrafficSelector.builder()
420 .matchInPort(phyPort)
421 .matchEthType(Ethernet.TYPE_IPV4)
422 .matchIPProtocol(IPv4.PROTOCOL_UDP)
423 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
424 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800425
Hyunsun Moon4a915152016-01-14 16:56:26 -0800426 treatment = DefaultTrafficTreatment.builder()
427 .setOutput(PortNumber.LOCAL)
428 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800429
Hyunsun Moon4a915152016-01-14 16:56:26 -0800430 flowRule = DefaultFlowRule.builder()
431 .fromApp(appId)
432 .withSelector(selector)
433 .withTreatment(treatment)
434 .withPriority(HIGHER_PRIORITY)
435 .forDevice(deviceId)
436 .forTable(TABLE_FIRST)
437 .makePermanent()
438 .build();
439
440 processFlowRule(true, flowRule);
441
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800442 // take a packet to the local ip through Linux stack
443 selector = DefaultTrafficSelector.builder()
444 .matchInPort(phyPort)
445 .matchEthType(Ethernet.TYPE_IPV4)
446 .matchIPDst(localIp.toIpPrefix())
447 .build();
448
449 treatment = DefaultTrafficTreatment.builder()
450 .setOutput(PortNumber.LOCAL)
451 .build();
452
453 flowRule = DefaultFlowRule.builder()
454 .fromApp(appId)
455 .withSelector(selector)
456 .withTreatment(treatment)
457 .withPriority(HIGHER_PRIORITY)
458 .forDevice(deviceId)
459 .forTable(TABLE_FIRST)
460 .makePermanent()
461 .build();
462
463 processFlowRule(true, flowRule);
464
465 // take an arp packet from physical through Linux stack
466 selector = DefaultTrafficSelector.builder()
467 .matchInPort(phyPort)
468 .matchEthType(Ethernet.TYPE_ARP)
469 .build();
470
471 treatment = DefaultTrafficTreatment.builder()
472 .setOutput(PortNumber.LOCAL)
473 .build();
474
475 flowRule = DefaultFlowRule.builder()
476 .fromApp(appId)
477 .withSelector(selector)
478 .withTreatment(treatment)
479 .withPriority(HIGHER_PRIORITY)
480 .forDevice(deviceId)
481 .forTable(TABLE_FIRST)
482 .makePermanent()
483 .build();
484
485 processFlowRule(true, flowRule);
486
Hyunsun Moon4a915152016-01-14 16:56:26 -0800487 // take all else to the next table
488 selector = DefaultTrafficSelector.builder()
489 .build();
490
491 treatment = DefaultTrafficTreatment.builder()
492 .transition(TABLE_IN_PORT)
493 .build();
494
495 flowRule = DefaultFlowRule.builder()
496 .fromApp(appId)
497 .withSelector(selector)
498 .withTreatment(treatment)
499 .withPriority(LOWEST_PRIORITY)
500 .forDevice(deviceId)
501 .forTable(TABLE_FIRST)
502 .makePermanent()
503 .build();
504
505 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800506 }
507
508 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800509 * Forward table miss packets in ACCESS_TYPE table to physical port.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800510 *
511 * @param deviceId device id
Hyunsun Moon4a915152016-01-14 16:56:26 -0800512 * @param phyPort physical port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800513 */
Hyunsun Moon4a915152016-01-14 16:56:26 -0800514 private void processAccessTypeTable(DeviceId deviceId, PortNumber phyPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800515 TrafficSelector selector = DefaultTrafficSelector.builder()
516 .build();
517
518 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon4a915152016-01-14 16:56:26 -0800519 .setOutput(phyPort)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800520 .build();
521
522 FlowRule flowRule = DefaultFlowRule.builder()
523 .fromApp(appId)
524 .withSelector(selector)
525 .withTreatment(treatment)
526 .withPriority(LOWEST_PRIORITY)
527 .forDevice(deviceId)
528 .forTable(TABLE_ACCESS_TYPE)
529 .makePermanent()
530 .build();
531
532 processFlowRule(true, flowRule);
533 }
534
535 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800536 * Populates default rules for IN_PORT table.
537 * All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
538 * from physical port to ACCESS_TYPE table.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800539 *
540 * @param deviceId device id to install the rules
Hyunsun Moon4a915152016-01-14 16:56:26 -0800541 * @param tunnelPort tunnel port number
542 * @param phyPort physical port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800543 */
Hyunsun Moon4a915152016-01-14 16:56:26 -0800544 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber phyPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800545 checkNotNull(tunnelPort);
546
547 TrafficSelector selector = DefaultTrafficSelector.builder()
548 .matchInPort(tunnelPort)
549 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800550
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800551 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
552 .transition(TABLE_TUNNEL_IN)
553 .build();
554
555 FlowRule flowRule = DefaultFlowRule.builder()
556 .fromApp(appId)
557 .withSelector(selector)
558 .withTreatment(treatment)
559 .withPriority(DEFAULT_PRIORITY)
560 .forDevice(deviceId)
561 .forTable(TABLE_IN_PORT)
562 .makePermanent()
563 .build();
564
565 processFlowRule(true, flowRule);
Hyunsun Moon4a915152016-01-14 16:56:26 -0800566
567 selector = DefaultTrafficSelector.builder()
568 .matchInPort(phyPort)
569 .build();
570
571 treatment = DefaultTrafficTreatment.builder()
572 .transition(TABLE_DST_IP)
573 .build();
574
575 flowRule = DefaultFlowRule.builder()
576 .fromApp(appId)
577 .withSelector(selector)
578 .withTreatment(treatment)
579 .withPriority(DEFAULT_PRIORITY)
580 .forDevice(deviceId)
581 .forTable(TABLE_IN_PORT)
582 .makePermanent()
583 .build();
584
585 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800586 }
587
588 /**
589 * Populates rules for local in port in IN_PORT table.
590 * Flows from a given in port, whose source IP is service IP transition
591 * to DST_TYPE table. Other flows transition to IN_SERVICE table.
592 *
593 * @param deviceId device id to install the rules
594 * @param inPort in port
595 * @param srcIp source ip
596 */
597 private void populateLocalInPortRule(DeviceId deviceId, PortNumber inPort, IpAddress srcIp) {
598 TrafficSelector selector = DefaultTrafficSelector.builder()
599 .matchInPort(inPort)
600 .matchEthType(Ethernet.TYPE_IPV4)
601 .matchIPSrc(srcIp.toIpPrefix())
602 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800603
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800604 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
605 .transition(TABLE_ACCESS_TYPE)
606 .build();
607
608
609 FlowRule flowRule = DefaultFlowRule.builder()
610 .fromApp(appId)
611 .withSelector(selector)
612 .withTreatment(treatment)
613 .withPriority(DEFAULT_PRIORITY)
614 .forDevice(deviceId)
615 .forTable(TABLE_IN_PORT)
616 .makePermanent()
617 .build();
618
619 processFlowRule(true, flowRule);
620
621 selector = DefaultTrafficSelector.builder()
622 .matchInPort(inPort)
623 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800624
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800625 treatment = DefaultTrafficTreatment.builder()
626 .transition(TABLE_IN_SERVICE)
627 .build();
628
629 flowRule = DefaultFlowRule.builder()
630 .fromApp(appId)
631 .withSelector(selector)
632 .withTreatment(treatment)
633 .withPriority(LOWER_PRIORITY)
634 .forDevice(deviceId)
635 .forTable(TABLE_IN_PORT)
636 .makePermanent()
637 .build();
638
639 processFlowRule(true, flowRule);
640 }
641
642 /**
643 * Populates direct VM access rules for ACCESS_TYPE table.
644 * These rules are installed to all devices.
645 *
646 * @param srcRange source ip range
647 * @param dstRange destination ip range
648 */
649 private void populateDirectAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange) {
650 TrafficSelector selector = DefaultTrafficSelector.builder()
651 .matchEthType(Ethernet.TYPE_IPV4)
652 .matchIPSrc(srcRange)
653 .matchIPDst(dstRange)
654 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800655
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800656 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
657 .transition(TABLE_DST_IP)
658 .build();
659
660 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
661 FlowRule flowRuleDirect = DefaultFlowRule.builder()
662 .fromApp(appId)
663 .withSelector(selector)
664 .withTreatment(treatment)
665 .withPriority(LOWER_PRIORITY)
666 .forDevice(device.id())
667 .forTable(TABLE_ACCESS_TYPE)
668 .makePermanent()
669 .build();
670
671 processFlowRule(true, flowRuleDirect);
672 }
673 }
674
675 /**
676 * Populates indirect service access rules for ACCESS_TYPE table.
677 * These rules are installed to all devices.
678 *
679 * @param srcRange source range
680 * @param serviceIp service ip
681 * @param outGroups list of output group
682 */
683 private void populateIndirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
684 Map<DeviceId, GroupId> outGroups) {
685 TrafficSelector selector = DefaultTrafficSelector.builder()
686 .matchEthType(Ethernet.TYPE_IPV4)
687 .matchIPSrc(srcRange)
688 .matchIPDst(serviceIp.toIpPrefix())
689 .build();
690
691 for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
692 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
693 .group(outGroup.getValue())
694 .build();
695
696 FlowRule flowRule = DefaultFlowRule.builder()
697 .fromApp(appId)
698 .withSelector(selector)
699 .withTreatment(treatment)
700 .withPriority(DEFAULT_PRIORITY)
701 .forDevice(outGroup.getKey())
702 .forTable(TABLE_ACCESS_TYPE)
703 .makePermanent()
704 .build();
705
706 processFlowRule(true, flowRule);
707 }
708 }
709
710 /**
711 * Populates flow rules for IN_SERVICE table.
712 *
713 * @param inPorts list of inports related to the service for each device
714 * @param outGroups set of output groups
715 */
716 private void populateInServiceRule(Map<DeviceId, Set<PortNumber>> inPorts, Map<DeviceId, GroupId> outGroups) {
717 checkNotNull(inPorts);
718 checkNotNull(outGroups);
719
720 for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
721 Set<PortNumber> ports = entry.getValue();
722 DeviceId deviceId = entry.getKey();
723
724 GroupId groupId = outGroups.get(deviceId);
725 if (groupId == null) {
726 continue;
727 }
728
729 ports.stream().forEach(port -> {
730 TrafficSelector selector = DefaultTrafficSelector.builder()
731 .matchInPort(port)
732 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800733
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800734 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
735 .group(groupId)
736 .build();
737
738 FlowRule flowRule = DefaultFlowRule.builder()
739 .fromApp(appId)
740 .withSelector(selector)
741 .withTreatment(treatment)
742 .withPriority(DEFAULT_PRIORITY)
743 .forDevice(deviceId)
744 .forTable(TABLE_IN_SERVICE)
745 .makePermanent()
746 .build();
747
748 processFlowRule(true, flowRule);
749 });
750 }
751 }
752
753 /**
754 * Populates flow rules for DST_IP table.
755 *
756 * @param deviceId device id
757 * @param inPort in port
758 * @param dstMac mac address
759 * @param dstIp destination ip
760 * @param tunnelId tunnel id
761 * @param tunnelIp tunnel remote ip
762 */
763 private void populateDstIpRule(DeviceId deviceId, PortNumber inPort, MacAddress dstMac,
764 IpAddress dstIp, long tunnelId, IpAddress tunnelIp) {
765 TrafficSelector selector = DefaultTrafficSelector.builder()
766 .matchEthType(Ethernet.TYPE_IPV4)
767 .matchIPDst(dstIp.toIpPrefix())
768 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800769
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800770 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
771 .setEthDst(dstMac)
772 .setOutput(inPort)
773 .build();
774
775 FlowRule flowRule = DefaultFlowRule.builder()
776 .fromApp(appId)
777 .withSelector(selector)
778 .withTreatment(treatment)
779 .withPriority(DEFAULT_PRIORITY)
780 .forDevice(deviceId)
781 .forTable(TABLE_DST_IP)
782 .makePermanent()
783 .build();
784
785 processFlowRule(true, flowRule);
786
787 for (Device device : deviceService.getAvailableDevices(SWITCH)) {
788 if (device.id().equals(deviceId)) {
789 continue;
790 }
791
792 ExtensionTreatment tunnelDst = getTunnelDst(device.id(), tunnelIp.getIp4Address());
793 if (tunnelDst == null) {
794 continue;
795 }
796
797 treatment = DefaultTrafficTreatment.builder()
798 .setEthDst(dstMac)
799 .setTunnelId(tunnelId)
800 .extension(tunnelDst, device.id())
801 .setOutput(getTunnelPort(device.id()))
802 .build();
803
804 flowRule = DefaultFlowRule.builder()
805 .fromApp(appId)
806 .withSelector(selector)
807 .withTreatment(treatment)
808 .withPriority(DEFAULT_PRIORITY)
809 .forDevice(device.id())
810 .forTable(TABLE_DST_IP)
811 .makePermanent()
812 .build();
813
814 processFlowRule(true, flowRule);
815 }
816 }
817
818 /**
819 * Populates flow rules for TUNNEL_ID table.
820 *
821 * @param deviceId device id
822 * @param inPort in port
823 * @param mac mac address
824 * @param tunnelId tunnel id
825 */
826 private void populateTunnelInRule(DeviceId deviceId, PortNumber inPort, MacAddress mac, long tunnelId) {
827 TrafficSelector selector = DefaultTrafficSelector.builder()
828 .matchTunnelId(tunnelId)
829 .matchEthDst(mac)
830 .build();
831
832 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
833 .setOutput(inPort)
834 .build();
835
836 FlowRule flowRule = DefaultFlowRule.builder()
837 .fromApp(appId)
838 .withSelector(selector)
839 .withTreatment(treatment)
840 .withPriority(DEFAULT_PRIORITY)
841 .forDevice(deviceId)
842 .forTable(TABLE_TUNNEL_IN)
843 .makePermanent()
844 .build();
845
846 processFlowRule(true, flowRule);
847 }
848
849 /**
850 * Installs or uninstall a given rule.
851 *
852 * @param install true to install, false to uninstall
853 * @param rule rule
854 */
855 private void processFlowRule(boolean install, FlowRule rule) {
856 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
857 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
858
859 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
860 @Override
861 public void onError(FlowRuleOperations ops) {
862 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
863 }
864 }));
865 }
866
867 /**
868 * Returns tunnel port of the device.
869 *
870 * @param deviceId device id
871 * @return tunnel port number, or null if no tunnel port exists on a given device
872 */
873 private PortNumber getTunnelPort(DeviceId deviceId) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800874 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800875 .filter(p -> p.annotations().value("portName").contains(tunnelType))
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800876 .findFirst().orElse(null);
877
878 return port == null ? null : port.number();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800879 }
880
881 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800882 * Returns physical port name of a given device.
883 *
884 * @param deviceId device id
885 * @param phyPortName physical port name
886 * @return physical port number, or null if no physical port exists
887 */
888 private PortNumber getPhyPort(DeviceId deviceId, String phyPortName) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800889 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon4a915152016-01-14 16:56:26 -0800890 .filter(p -> p.annotations().value("portName").contains(phyPortName) &&
891 p.isEnabled())
Hyunsun Moon5a4346f2016-01-15 11:41:14 -0800892 .findFirst().orElse(null);
893
894 return port == null ? null : port.number();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800895 }
896
897 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800898 * Returns the inport from a given flow rule if the rule contains the match of it.
899 *
900 * @param flowRule flow rule
901 * @return port number, or null if the rule doesn't have inport match
902 */
903 private PortNumber getInPort(FlowRule flowRule) {
904 Criterion criterion = flowRule.selector().getCriterion(IN_PORT);
905 if (criterion != null && criterion instanceof PortCriterion) {
906 PortCriterion port = (PortCriterion) criterion;
907 return port.port();
908 } else {
909 return null;
910 }
911 }
912
913 /**
914 * Returns the destination mac address from a given flow rule if the rule
915 * contains the instruction of it.
916 *
917 * @param flowRule flow rule
918 * @return mac address, or null if the rule doesn't have destination mac instruction
919 */
920 private MacAddress getDstMacFromTreatment(FlowRule flowRule) {
921 Instruction instruction = flowRule.treatment().allInstructions().stream()
922 .filter(inst -> inst instanceof ModEtherInstruction &&
923 ((ModEtherInstruction) inst).subtype().equals(ETH_DST))
924 .findFirst()
925 .orElse(null);
926
927 if (instruction == null) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800928 return null;
929 }
930
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800931 return ((ModEtherInstruction) instruction).mac();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800932 }
933
934 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800935 * Returns the destination mac address from a given flow rule if the rule
936 * contains the match of it.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800937 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800938 * @param flowRule flow rule
939 * @return mac address, or null if the rule doesn't have destination mac match
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800940 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800941 private MacAddress getDstMacFromSelector(FlowRule flowRule) {
942 Criterion criterion = flowRule.selector().getCriterion(Criterion.Type.ETH_DST);
943 if (criterion != null && criterion instanceof EthCriterion) {
944 EthCriterion eth = (EthCriterion) criterion;
945 return eth.mac();
946 } else {
947 return null;
948 }
949 }
950
951 /**
952 * Returns the destination IP from a given flow rule if the rule contains
953 * the match of it.
954 *
955 * @param flowRule flow rule
956 * @return ip prefix, or null if the rule doesn't have ip match
957 */
958 private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
959 Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
960 if (criterion != null && criterion instanceof IPCriterion) {
961 IPCriterion ip = (IPCriterion) criterion;
962 return ip.ip();
963 } else {
964 return null;
965 }
966 }
967
968 /**
969 * Returns the source IP from a given flow rule if the rule contains
970 * the match of it.
971 *
972 * @param flowRule flow rule
973 * @return ip prefix, or null if the rule doesn't have ip match
974 */
975 private IpPrefix getSrcIpFromSelector(FlowRule flowRule) {
976 Criterion criterion = flowRule.selector().getCriterion(IPV4_SRC);
977 if (criterion != null && criterion instanceof IPCriterion) {
978 IPCriterion ip = (IPCriterion) criterion;
979 return ip.ip();
980 } else {
981 return null;
982 }
983 }
984
985 /**
986 * Returns the group ID from a given flow rule if the rule contains the
987 * treatment of it.
988 *
989 * @param flowRule flow rule
990 * @return group id, or null if the rule doesn't have group instruction
991 */
992 private GroupId getGroupIdFromTreatment(FlowRule flowRule) {
993 Instruction instruction = flowRule.treatment().allInstructions().stream()
994 .filter(inst -> inst instanceof Instructions.GroupInstruction)
995 .findFirst()
996 .orElse(null);
997
998 if (instruction == null) {
999 return null;
1000 }
1001
1002 return ((Instructions.GroupInstruction) instruction).groupId();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001003 }
1004
1005 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -08001006 * Creates a new group for a given service.
1007 *
1008 * @param deviceId device id to create a group
1009 * @param service cord service
1010 * @return group id, or null if it fails to create
1011 */
1012 private GroupId createServiceGroup(DeviceId deviceId, CordService service) {
1013 checkNotNull(service);
1014
1015 GroupKey groupKey = getGroupKey(service.id());
1016 Group group = groupService.getGroup(deviceId, groupKey);
1017 GroupId groupId = getGroupId(service.id(), deviceId);
1018
1019 if (group != null) {
1020 log.debug("Group {} is already exist in {}", service.id(), deviceId);
1021 return groupId;
1022 }
1023
1024 GroupBuckets buckets = getServiceGroupBuckets(deviceId, service.segmentationId(), service.hosts());
1025 GroupDescription groupDescription = new DefaultGroupDescription(
1026 deviceId,
1027 GroupDescription.Type.SELECT,
1028 buckets,
1029 groupKey,
1030 groupId.id(),
1031 appId);
1032
1033 groupService.addGroup(groupDescription);
1034
1035 return groupId;
1036 }
1037
1038 /**
1039 * Returns group buckets for a given device.
1040 *
1041 * @param deviceId device id
1042 * @param tunnelId tunnel id
1043 * @param hosts list of host
1044 * @return group buckets
1045 */
1046 private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId, Map<Host, IpAddress> hosts) {
1047 List<GroupBucket> buckets = Lists.newArrayList();
1048
1049 for (Map.Entry<Host, IpAddress> entry : hosts.entrySet()) {
1050 Host host = entry.getKey();
1051 Ip4Address remoteIp = entry.getValue().getIp4Address();
1052 DeviceId hostDevice = host.location().deviceId();
1053
1054 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
1055 .builder()
1056 .setEthDst(host.mac());
1057
1058 if (deviceId.equals(hostDevice)) {
1059 tBuilder.setOutput(host.location().port());
1060 } else {
1061 ExtensionTreatment tunnelDst = getTunnelDst(deviceId, remoteIp);
1062 if (tunnelDst == null) {
1063 continue;
1064 }
1065
1066 tBuilder.extension(tunnelDst, deviceId)
1067 .setTunnelId(tunnelId)
1068 .setOutput(getTunnelPort(hostDevice));
1069 }
1070
1071 buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
1072 }
1073
1074 return new GroupBuckets(buckets);
1075 }
1076
1077 /**
1078 * Returns globally unique group ID.
1079 *
1080 * @param serviceId service id
1081 * @param deviceId device id
1082 * @return group id
1083 */
1084 private GroupId getGroupId(CordServiceId serviceId, DeviceId deviceId) {
1085 return new DefaultGroupId(Objects.hash(serviceId, deviceId));
1086 }
1087
1088 /**
1089 * Returns group key of a service.
1090 *
1091 * @param serviceId service id
1092 * @return group key
1093 */
1094 private GroupKey getGroupKey(CordServiceId serviceId) {
1095 return new DefaultGroupKey(serviceId.id().getBytes());
1096 }
1097
1098 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001099 * Returns extension instruction to set tunnel destination.
1100 *
1101 * @param deviceId device id
1102 * @param remoteIp tunnel destination address
1103 * @return extension treatment or null if it fails to get instruction
1104 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001105 private ExtensionTreatment getTunnelDst(DeviceId deviceId, Ip4Address remoteIp) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001106 try {
1107 Driver driver = driverService.getDriver(deviceId);
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001108 DefaultDriverData driverData = new DefaultDriverData(driver, deviceId);
1109 DriverHandler handler = new DefaultDriverHandler(driverData);
1110 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001111
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001112 ExtensionTreatment treatment =
1113 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001114 treatment.setPropertyValue("tunnelDst", remoteIp);
1115
1116 return treatment;
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001117 } catch (ItemNotFoundException | UnsupportedOperationException |
1118 ExtensionPropertyException e) {
1119 log.error("Failed to get extension instruction {}", deviceId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001120 return null;
1121 }
1122 }
1123}
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001124