blob: d5e72bb11e8839f9c6eb1d62dbb65dd424893058 [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;
Hyunsun Moon7a9bb122016-03-08 18:07:52 -080020import com.google.common.collect.Sets;
Hyunsun Moonba290072015-12-16 20:53:23 -080021import org.onlab.packet.Ethernet;
Hyunsun Moon3467a262016-01-14 16:56:26 -080022import org.onlab.packet.IPv4;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080023import org.onlab.packet.Ip4Address;
Hyunsun Moonba290072015-12-16 20:53:23 -080024import org.onlab.packet.Ip4Prefix;
25import org.onlab.packet.IpAddress;
26import org.onlab.packet.IpPrefix;
27import org.onlab.packet.MacAddress;
Hyunsun Moon3467a262016-01-14 16:56:26 -080028import org.onlab.packet.TpPort;
Hyunsun Moon01556a52016-02-12 12:48:47 -080029import org.onlab.packet.VlanId;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080030import org.onlab.util.ItemNotFoundException;
31import org.onosproject.core.ApplicationId;
Hyunsun Moonba290072015-12-16 20:53:23 -080032import org.onosproject.core.DefaultGroupId;
33import org.onosproject.core.GroupId;
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 Moon7a9bb122016-03-08 18:07:52 -080039import org.onosproject.net.config.NetworkConfigRegistry;
Hyunsun Moonba290072015-12-16 20:53:23 -080040import org.onosproject.net.device.DeviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080041import org.onosproject.net.driver.DefaultDriverData;
42import org.onosproject.net.driver.DefaultDriverHandler;
43import org.onosproject.net.driver.Driver;
44import org.onosproject.net.driver.DriverHandler;
45import org.onosproject.net.driver.DriverService;
Hyunsun Moonba290072015-12-16 20:53:23 -080046import org.onosproject.net.flow.DefaultFlowRule;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080047import org.onosproject.net.flow.DefaultTrafficSelector;
48import org.onosproject.net.flow.DefaultTrafficTreatment;
Hyunsun Moonba290072015-12-16 20:53:23 -080049import org.onosproject.net.flow.FlowRule;
50import org.onosproject.net.flow.FlowRuleOperations;
51import org.onosproject.net.flow.FlowRuleOperationsContext;
52import org.onosproject.net.flow.FlowRuleService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080053import org.onosproject.net.flow.TrafficSelector;
54import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moonba290072015-12-16 20:53:23 -080055import org.onosproject.net.flow.criteria.Criterion;
56import org.onosproject.net.flow.criteria.EthCriterion;
57import org.onosproject.net.flow.criteria.IPCriterion;
58import org.onosproject.net.flow.criteria.PortCriterion;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080059import org.onosproject.net.flow.instructions.ExtensionPropertyException;
60import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moonba290072015-12-16 20:53:23 -080061import org.onosproject.net.flow.instructions.Instruction;
62import org.onosproject.net.flow.instructions.Instructions;
Hyunsun Moon01556a52016-02-12 12:48:47 -080063import org.onosproject.net.flow.instructions.L2ModificationInstruction;
Hyunsun Moonba290072015-12-16 20:53:23 -080064import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
65import org.onosproject.net.group.DefaultGroupBucket;
66import org.onosproject.net.group.DefaultGroupDescription;
67import org.onosproject.net.group.DefaultGroupKey;
68import org.onosproject.net.group.Group;
69import org.onosproject.net.group.GroupBucket;
70import org.onosproject.net.group.GroupBuckets;
71import org.onosproject.net.group.GroupDescription;
72import org.onosproject.net.group.GroupKey;
73import org.onosproject.net.group.GroupService;
sangho47502d92016-02-24 00:33:22 +090074import org.onosproject.openstackinterface.OpenstackNetwork;
75import org.onosproject.openstackinterface.OpenstackSubnet;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080076import org.slf4j.Logger;
77
Hyunsun Moonee37c442016-01-07 01:32:31 -080078import java.util.ArrayList;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080079import java.util.List;
Hyunsun Moonba290072015-12-16 20:53:23 -080080import java.util.Map;
Hyunsun Moonba290072015-12-16 20:53:23 -080081import java.util.Objects;
82import java.util.Set;
83import java.util.stream.Collectors;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080084
Hyunsun Moon05f528a2015-11-04 17:34:35 -080085import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moonba290072015-12-16 20:53:23 -080086import static org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT;
87import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
88import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_SRC;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080089import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
Hyunsun Moonba290072015-12-16 20:53:23 -080090import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
Hyunsun Moon01556a52016-02-12 12:48:47 -080091import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080092import static org.slf4j.LoggerFactory.getLogger;
93
94/**
Hyunsun Moonba290072015-12-16 20:53:23 -080095 * Populates rules for CORD VTN service.
Hyunsun Moon05f528a2015-11-04 17:34:35 -080096 */
Hyunsun Moonba290072015-12-16 20:53:23 -080097public class CordVtnRuleInstaller {
98
Hyunsun Moon05f528a2015-11-04 17:34:35 -080099 protected final Logger log = getLogger(getClass());
100
Hyunsun Moon3467a262016-01-14 16:56:26 -0800101 private static final int TABLE_FIRST = 0;
102 private static final int TABLE_IN_PORT = 1;
103 private static final int TABLE_ACCESS_TYPE = 2;
104 private static final int TABLE_IN_SERVICE = 3;
105 private static final int TABLE_DST_IP = 4;
106 private static final int TABLE_TUNNEL_IN = 5;
Hyunsun Moon01556a52016-02-12 12:48:47 -0800107 private static final int TABLE_Q_IN_Q = 6;
Hyunsun Moonba290072015-12-16 20:53:23 -0800108
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800109 private static final int MANAGEMENT_PRIORITY = 55000;
Hyunsun Moon01556a52016-02-12 12:48:47 -0800110 private static final int VSG_PRIORITY = 55000;
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800111 private static final int HIGH_PRIORITY = 50000;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800112 private static final int DEFAULT_PRIORITY = 5000;
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800113 private static final int LOW_PRIORITY = 4000;
Hyunsun Moonba290072015-12-16 20:53:23 -0800114 private static final int LOWEST_PRIORITY = 0;
Hyunsun Moon3467a262016-01-14 16:56:26 -0800115
116 private static final int VXLAN_UDP_PORT = 4789;
Hyunsun Moon01556a52016-02-12 12:48:47 -0800117 private static final VlanId VLAN_WAN = VlanId.vlanId((short) 500);
118
119 private static final String PORT_NAME = "portName";
120 private static final String DATA_PLANE_INTF = "dataPlaneIntf";
121 private static final String S_TAG = "stag";
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800122
123 private final ApplicationId appId;
Hyunsun Moonba290072015-12-16 20:53:23 -0800124 private final FlowRuleService flowRuleService;
125 private final DeviceService deviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800126 private final DriverService driverService;
Hyunsun Moonba290072015-12-16 20:53:23 -0800127 private final GroupService groupService;
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800128 private final NetworkConfigRegistry configRegistry;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800129 private final String tunnelType;
130
131 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800132 * Creates a new rule populator.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800133 *
134 * @param appId application id
Hyunsun Moonba290072015-12-16 20:53:23 -0800135 * @param flowRuleService flow rule service
136 * @param deviceService device service
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800137 * @param driverService driver service
Jian Li248e9202016-01-22 16:46:58 -0800138 * @param groupService group service
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800139 * @param tunnelType tunnel type
140 */
141 public CordVtnRuleInstaller(ApplicationId appId,
Hyunsun Moonba290072015-12-16 20:53:23 -0800142 FlowRuleService flowRuleService,
143 DeviceService deviceService,
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800144 DriverService driverService,
Hyunsun Moonba290072015-12-16 20:53:23 -0800145 GroupService groupService,
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800146 NetworkConfigRegistry configRegistry,
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800147 String tunnelType) {
148 this.appId = appId;
Hyunsun Moonba290072015-12-16 20:53:23 -0800149 this.flowRuleService = flowRuleService;
150 this.deviceService = deviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800151 this.driverService = driverService;
Hyunsun Moonba290072015-12-16 20:53:23 -0800152 this.groupService = groupService;
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800153 this.configRegistry = configRegistry;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800154 this.tunnelType = checkNotNull(tunnelType);
155 }
156
157 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800158 * Installs table miss rule to a give device.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800159 *
Hyunsun Moonba290072015-12-16 20:53:23 -0800160 * @param deviceId device id to install the rules
Hyunsun Moon126171d2016-02-09 01:55:48 -0800161 * @param dpIntf data plane interface name
162 * @param dpIp data plane ip address
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800163 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800164 public void init(DeviceId deviceId, String dpIntf, IpAddress dpIp) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800165 // default is drop packets which can be accomplished without
166 // a table miss entry for all table.
Hyunsun Moon3467a262016-01-14 16:56:26 -0800167 PortNumber tunnelPort = getTunnelPort(deviceId);
Hyunsun Moon126171d2016-02-09 01:55:48 -0800168 PortNumber dpPort = getDpPort(deviceId, dpIntf);
Hyunsun Moon3467a262016-01-14 16:56:26 -0800169
Hyunsun Moon126171d2016-02-09 01:55:48 -0800170 processFirstTable(deviceId, dpPort, dpIp);
171 processInPortTable(deviceId, tunnelPort, dpPort);
172 processAccessTypeTable(deviceId, dpPort);
Hyunsun Moon01556a52016-02-12 12:48:47 -0800173 processQInQTable(deviceId, dpPort);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800174 }
175
176 /**
Hyunsun Mooncbc885f2016-03-08 15:37:57 -0800177 * Flush flows installed by this application.
178 */
179 public void flushRules() {
180 flowRuleService.getFlowRulesById(appId).forEach(flowRule -> processFlowRule(false, flowRule));
181 }
182
183 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800184 * Populates basic rules that connect a VM to the other VMs in the system.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800185 *
Hyunsun Moonba290072015-12-16 20:53:23 -0800186 * @param host host
Hyunsun Moonba290072015-12-16 20:53:23 -0800187 * @param tunnelIp tunnel ip
188 * @param vNet openstack network
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800189 */
Hyunsun Mooncb799442016-01-15 20:03:18 -0800190 public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, OpenstackNetwork vNet) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800191 checkNotNull(host);
192 checkNotNull(vNet);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800193
Hyunsun Moonba290072015-12-16 20:53:23 -0800194 DeviceId deviceId = host.location().deviceId();
Hyunsun Moonba290072015-12-16 20:53:23 -0800195 PortNumber inPort = host.location().port();
196 MacAddress dstMac = host.mac();
Hyunsun Mooncb799442016-01-15 20:03:18 -0800197 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
Hyunsun Moonba290072015-12-16 20:53:23 -0800198 long tunnelId = Long.parseLong(vNet.segmentId());
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800199
Hyunsun Moonba290072015-12-16 20:53:23 -0800200 OpenstackSubnet subnet = vNet.subnets().stream()
201 .findFirst()
202 .orElse(null);
203
204 if (subnet == null) {
205 log.error("Failed to get subnet for {}", host.id());
206 return;
207 }
208
209 populateLocalInPortRule(deviceId, inPort, hostIp);
210 populateDirectAccessRule(Ip4Prefix.valueOf(subnet.cidr()), Ip4Prefix.valueOf(subnet.cidr()));
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800211 populateServiceIsolationRule(Ip4Prefix.valueOf(subnet.cidr()));
Hyunsun Moonba290072015-12-16 20:53:23 -0800212 populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
213 populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800214 }
215
216 /**
Hyunsun Moon703a0912016-02-18 15:37:22 -0800217 * Removes all rules related to a given service VM host.
Hyunsun Moonba290072015-12-16 20:53:23 -0800218 *
219 * @param host host to be removed
220 */
221 public void removeBasicConnectionRules(Host host) {
222 checkNotNull(host);
223
224 DeviceId deviceId = host.location().deviceId();
225 MacAddress mac = host.mac();
226 PortNumber port = host.location().port();
227 IpAddress ip = host.ipAddresses().stream().findFirst().orElse(null);
228
Hyunsun Moonba290072015-12-16 20:53:23 -0800229 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
230 if (flowRule.deviceId().equals(deviceId)) {
231 PortNumber inPort = getInPort(flowRule);
232 if (inPort != null && inPort.equals(port)) {
233 processFlowRule(false, flowRule);
234 continue;
235 }
Hyunsun Moon703a0912016-02-18 15:37:22 -0800236
237 PortNumber output = getOutputFromTreatment(flowRule);
238 if (output != null && output.equals(host.location().port())) {
239 processFlowRule(false, flowRule);
240 }
Hyunsun Moonba290072015-12-16 20:53:23 -0800241 }
242
243 MacAddress dstMac = getDstMacFromTreatment(flowRule);
244 if (dstMac != null && dstMac.equals(mac)) {
245 processFlowRule(false, flowRule);
246 continue;
247 }
248
249 dstMac = getDstMacFromSelector(flowRule);
250 if (dstMac != null && dstMac.equals(mac)) {
251 processFlowRule(false, flowRule);
252 continue;
253 }
254
255 IpPrefix dstIp = getDstIpFromSelector(flowRule);
256 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
257 processFlowRule(false, flowRule);
258 }
Hyunsun Moonba290072015-12-16 20:53:23 -0800259 }
260
261 // TODO uninstall same network access rule in access table if no vm exists in the network
262 }
263
264 /**
Hyunsun Moonee37c442016-01-07 01:32:31 -0800265 * Populates service dependency rules.
266 *
267 * @param tService tenant cord service
268 * @param pService provider cord service
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800269 * @param isBidirectional true to enable bidirectional connection between two services
Hyunsun Moonee37c442016-01-07 01:32:31 -0800270 */
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800271 public void populateServiceDependencyRules(CordService tService, CordService pService,
272 boolean isBidirectional) {
Hyunsun Moonee37c442016-01-07 01:32:31 -0800273 checkNotNull(tService);
274 checkNotNull(pService);
275
276 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
277 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
278 Ip4Address serviceIp = pService.serviceIp().getIp4Address();
279
280 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
281 Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
282
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800283 getVirtualSwitches().stream().forEach(deviceId -> {
284 GroupId groupId = createServiceGroup(deviceId, pService);
285 outGroups.put(deviceId, groupId);
Hyunsun Moonee37c442016-01-07 01:32:31 -0800286
287 Set<PortNumber> vms = tService.hosts().keySet()
288 .stream()
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800289 .filter(host -> host.location().deviceId().equals(deviceId))
Hyunsun Moonee37c442016-01-07 01:32:31 -0800290 .map(host -> host.location().port())
291 .collect(Collectors.toSet());
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800292 inPorts.put(deviceId, vms);
293 });
Hyunsun Moonee37c442016-01-07 01:32:31 -0800294
295 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
296 populateDirectAccessRule(srcRange, dstRange);
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800297 if (isBidirectional) {
298 populateDirectAccessRule(dstRange, srcRange);
299 }
Hyunsun Moonee37c442016-01-07 01:32:31 -0800300 populateInServiceRule(inPorts, outGroups);
301 }
302
303 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800304 * Removes service dependency rules.
305 *
306 * @param tService tenant cord service
307 * @param pService provider cord service
308 */
309 public void removeServiceDependencyRules(CordService tService, CordService pService) {
310 checkNotNull(tService);
311 checkNotNull(pService);
312
313 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
314 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
315 IpPrefix serviceIp = pService.serviceIp().toIpPrefix();
316
317 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
318 GroupKey groupKey = new DefaultGroupKey(pService.id().id().getBytes());
319
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800320 getVirtualSwitches().stream().forEach(deviceId -> {
321 Group group = groupService.getGroup(deviceId, groupKey);
Hyunsun Moonba290072015-12-16 20:53:23 -0800322 if (group != null) {
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800323 outGroups.put(deviceId, group.id());
Hyunsun Moonba290072015-12-16 20:53:23 -0800324 }
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800325 });
Hyunsun Moonba290072015-12-16 20:53:23 -0800326
327 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
328 IpPrefix dstIp = getDstIpFromSelector(flowRule);
329 IpPrefix srcIp = getSrcIpFromSelector(flowRule);
330
331 if (dstIp != null && dstIp.equals(serviceIp)) {
332 processFlowRule(false, flowRule);
333 continue;
334 }
335
336 if (dstIp != null && srcIp != null) {
337 if (dstIp.equals(dstRange) && srcIp.equals(srcRange)) {
338 processFlowRule(false, flowRule);
339 continue;
340 }
341
342 if (dstIp.equals(srcRange) && srcIp.equals(dstRange)) {
343 processFlowRule(false, flowRule);
344 continue;
345 }
346 }
347
348 GroupId groupId = getGroupIdFromTreatment(flowRule);
349 if (groupId != null && groupId.equals(outGroups.get(flowRule.deviceId()))) {
350 processFlowRule(false, flowRule);
351 }
352 }
353
354 // TODO remove the group if it is not in use
355 }
356
357 /**
Hyunsun Moonee37c442016-01-07 01:32:31 -0800358 * Updates group buckets for a given service to all devices.
359 *
360 * @param service cord service
361 */
362 public void updateServiceGroup(CordService service) {
363 checkNotNull(service);
364
365 GroupKey groupKey = getGroupKey(service.id());
366
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800367 for (DeviceId deviceId : getVirtualSwitches()) {
Hyunsun Moonee37c442016-01-07 01:32:31 -0800368 Group group = groupService.getGroup(deviceId, groupKey);
369 if (group == null) {
Hyunsun Mooncb799442016-01-15 20:03:18 -0800370 log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId);
Hyunsun Moonee37c442016-01-07 01:32:31 -0800371 continue;
372 }
373
374 List<GroupBucket> oldBuckets = group.buckets().buckets();
375 List<GroupBucket> newBuckets = getServiceGroupBuckets(
376 deviceId, service.segmentationId(), service.hosts()).buckets();
377
378 if (oldBuckets.equals(newBuckets)) {
379 continue;
380 }
381
382 List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
383 bucketsToRemove.removeAll(newBuckets);
384 if (!bucketsToRemove.isEmpty()) {
385 groupService.removeBucketsFromGroup(
386 deviceId,
387 groupKey,
388 new GroupBuckets(bucketsToRemove),
389 groupKey, appId);
390 }
391
392 List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
393 bucketsToAdd.removeAll(oldBuckets);
394 if (!bucketsToAdd.isEmpty()) {
395 groupService.addBucketsToGroup(
396 deviceId,
397 groupKey,
398 new GroupBuckets(bucketsToAdd),
399 groupKey, appId);
400 }
401 }
402 }
403
404 /**
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800405 * Populates flow rules for management network access.
406 *
407 * @param host host which has management network interface
408 * @param mService management network service
409 */
410 public void populateManagementNetworkRules(Host host, CordService mService) {
411 checkNotNull(mService);
412
413 DeviceId deviceId = host.location().deviceId();
414 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
415
416 TrafficSelector selector = DefaultTrafficSelector.builder()
417 .matchEthType(Ethernet.TYPE_ARP)
418 .matchArpTpa(mService.serviceIp().getIp4Address())
419 .build();
420
421 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
422 .setOutput(PortNumber.LOCAL)
423 .build();
424
425 FlowRule flowRule = DefaultFlowRule.builder()
426 .fromApp(appId)
427 .withSelector(selector)
428 .withTreatment(treatment)
429 .withPriority(MANAGEMENT_PRIORITY)
430 .forDevice(deviceId)
431 .forTable(TABLE_FIRST)
432 .makePermanent()
433 .build();
434
435 processFlowRule(true, flowRule);
436
437 selector = DefaultTrafficSelector.builder()
438 .matchInPort(PortNumber.LOCAL)
439 .matchEthType(Ethernet.TYPE_ARP)
440 .matchArpTpa(hostIp.getIp4Address())
441 .build();
442
443 treatment = DefaultTrafficTreatment.builder()
444 .setOutput(host.location().port())
445 .build();
446
447 flowRule = DefaultFlowRule.builder()
448 .fromApp(appId)
449 .withSelector(selector)
450 .withTreatment(treatment)
451 .withPriority(MANAGEMENT_PRIORITY)
452 .forDevice(deviceId)
453 .forTable(TABLE_FIRST)
454 .makePermanent()
455 .build();
456
457 processFlowRule(true, flowRule);
458
459 selector = DefaultTrafficSelector.builder()
460 .matchInPort(PortNumber.LOCAL)
461 .matchEthType(Ethernet.TYPE_IPV4)
462 .matchIPDst(mService.serviceIpRange())
463 .build();
464
465 treatment = DefaultTrafficTreatment.builder()
466 .transition(TABLE_DST_IP)
467 .build();
468
469 flowRule = DefaultFlowRule.builder()
470 .fromApp(appId)
471 .withSelector(selector)
472 .withTreatment(treatment)
473 .withPriority(MANAGEMENT_PRIORITY)
474 .forDevice(deviceId)
475 .forTable(TABLE_FIRST)
476 .makePermanent()
477 .build();
478
479 processFlowRule(true, flowRule);
480
481 selector = DefaultTrafficSelector.builder()
482 .matchEthType(Ethernet.TYPE_IPV4)
483 .matchIPDst(mService.serviceIp().toIpPrefix())
484 .build();
485
486 treatment = DefaultTrafficTreatment.builder()
487 .setOutput(PortNumber.LOCAL)
488 .build();
489
490 flowRule = DefaultFlowRule.builder()
491 .fromApp(appId)
492 .withSelector(selector)
493 .withTreatment(treatment)
494 .withPriority(MANAGEMENT_PRIORITY)
495 .forDevice(deviceId)
496 .forTable(TABLE_ACCESS_TYPE)
497 .makePermanent()
498 .build();
499
500 processFlowRule(true, flowRule);
501 }
502
503 /**
504 * Removes management network access rules.
505 *
506 * @param host host to be removed
507 * @param mService service for management network
508 */
509 public void removeManagementNetworkRules(Host host, CordService mService) {
510 checkNotNull(mService);
Hyunsun Moon703a0912016-02-18 15:37:22 -0800511 // TODO remove management network specific rules
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800512 }
513
514 /**
Hyunsun Moon01556a52016-02-12 12:48:47 -0800515 * Populates rules for vSG VM.
516 *
517 * @param vSgHost vSG host
518 * @param vSgIps set of ip addresses of vSGs running inside the vSG VM
519 */
520 public void populateSubscriberGatewayRules(Host vSgHost, Set<IpAddress> vSgIps) {
521 VlanId serviceVlan = getServiceVlan(vSgHost);
522 PortNumber dpPort = getDpPort(vSgHost);
523
524 if (serviceVlan == null || dpPort == null) {
525 log.warn("Failed to populate rules for vSG VM {}", vSgHost.id());
526 return;
527 }
528
529 // for traffics with s-tag, strip the tag and take through the vSG VM
530 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon703a0912016-02-18 15:37:22 -0800531 .matchInPort(dpPort)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800532 .matchVlanId(serviceVlan)
533 .build();
534
535 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon01556a52016-02-12 12:48:47 -0800536 .setOutput(vSgHost.location().port())
537 .build();
538
539 FlowRule flowRule = DefaultFlowRule.builder()
540 .fromApp(appId)
541 .withSelector(selector)
542 .withTreatment(treatment)
543 .withPriority(DEFAULT_PRIORITY)
544 .forDevice(vSgHost.location().deviceId())
545 .forTable(TABLE_Q_IN_Q)
546 .makePermanent()
547 .build();
548
549 processFlowRule(true, flowRule);
550
551 // for traffics with customer vlan, tag with the service vlan based on input port with
552 // lower priority to avoid conflict with WAN tag
553 selector = DefaultTrafficSelector.builder()
554 .matchInPort(vSgHost.location().port())
Hyunsun Moon703a0912016-02-18 15:37:22 -0800555 .matchVlanId(serviceVlan)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800556 .build();
557
558 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon01556a52016-02-12 12:48:47 -0800559 .setOutput(dpPort)
560 .build();
561
562 flowRule = DefaultFlowRule.builder()
563 .fromApp(appId)
564 .withSelector(selector)
565 .withTreatment(treatment)
Hyunsun Moon703a0912016-02-18 15:37:22 -0800566 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800567 .forDevice(vSgHost.location().deviceId())
568 .forTable(TABLE_Q_IN_Q)
569 .makePermanent()
570 .build();
571
572 processFlowRule(true, flowRule);
573
574 // for traffic coming from WAN, tag 500 and take through the vSG VM
575 // based on destination ip
576 vSgIps.stream().forEach(ip -> {
577 TrafficSelector downstream = DefaultTrafficSelector.builder()
578 .matchEthType(Ethernet.TYPE_IPV4)
579 .matchIPDst(ip.toIpPrefix())
580 .build();
581
582 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
583 .pushVlan()
584 .setVlanId(VLAN_WAN)
585 .setEthDst(vSgHost.mac())
586 .setOutput(vSgHost.location().port())
587 .build();
588
589 FlowRule downstreamFlowRule = DefaultFlowRule.builder()
590 .fromApp(appId)
591 .withSelector(downstream)
592 .withTreatment(downstreamTreatment)
593 .withPriority(DEFAULT_PRIORITY)
594 .forDevice(vSgHost.location().deviceId())
595 .forTable(TABLE_DST_IP)
596 .makePermanent()
597 .build();
598
599 processFlowRule(true, downstreamFlowRule);
600 });
601
602 // remove downstream flow rules for the vSG not shown in vSgIps
603 for (FlowRule rule : flowRuleService.getFlowRulesById(appId)) {
604 if (!rule.deviceId().equals(vSgHost.location().deviceId())) {
605 continue;
606 }
607 PortNumber output = getOutputFromTreatment(rule);
608 if (output == null || !output.equals(vSgHost.location().port()) ||
609 !isVlanPushFromTreatment(rule)) {
610 continue;
611 }
612
613 IpPrefix dstIp = getDstIpFromSelector(rule);
614 if (dstIp != null && !vSgIps.contains(dstIp.address())) {
615 processFlowRule(false, rule);
616 }
617 }
618 }
619
620 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800621 * Populates default rules on the first table.
Hyunsun Moon126171d2016-02-09 01:55:48 -0800622 * It includes the rules for shuttling vxlan-encapped packets between ovs and
623 * linux stack,and external network connectivity.
Hyunsun Moonba290072015-12-16 20:53:23 -0800624 *
625 * @param deviceId device id
Hyunsun Moon126171d2016-02-09 01:55:48 -0800626 * @param dpPort data plane interface port number
627 * @param dpIp data plane ip address
Hyunsun Moonba290072015-12-16 20:53:23 -0800628 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800629 private void processFirstTable(DeviceId deviceId, PortNumber dpPort, IpAddress dpIp) {
Hyunsun Moon3467a262016-01-14 16:56:26 -0800630 // take vxlan packet out onto the physical port
631 TrafficSelector selector = DefaultTrafficSelector.builder()
632 .matchInPort(PortNumber.LOCAL)
633 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800634
Hyunsun Moon3467a262016-01-14 16:56:26 -0800635 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800636 .setOutput(dpPort)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800637 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800638
Hyunsun Moon3467a262016-01-14 16:56:26 -0800639 FlowRule flowRule = DefaultFlowRule.builder()
640 .fromApp(appId)
641 .withSelector(selector)
642 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800643 .withPriority(HIGH_PRIORITY)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800644 .forDevice(deviceId)
645 .forTable(TABLE_FIRST)
646 .makePermanent()
647 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800648
Hyunsun Moon3467a262016-01-14 16:56:26 -0800649 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800650
Hyunsun Moon3467a262016-01-14 16:56:26 -0800651 // take a vxlan encap'd packet through the Linux stack
652 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800653 .matchInPort(dpPort)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800654 .matchEthType(Ethernet.TYPE_IPV4)
655 .matchIPProtocol(IPv4.PROTOCOL_UDP)
656 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
657 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800658
Hyunsun Moon3467a262016-01-14 16:56:26 -0800659 treatment = DefaultTrafficTreatment.builder()
660 .setOutput(PortNumber.LOCAL)
661 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800662
Hyunsun Moon3467a262016-01-14 16:56:26 -0800663 flowRule = DefaultFlowRule.builder()
664 .fromApp(appId)
665 .withSelector(selector)
666 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800667 .withPriority(HIGH_PRIORITY)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800668 .forDevice(deviceId)
669 .forTable(TABLE_FIRST)
670 .makePermanent()
671 .build();
672
673 processFlowRule(true, flowRule);
674
Hyunsun Moon126171d2016-02-09 01:55:48 -0800675 // take a packet to the data plane ip through Linux stack
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800676 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800677 .matchInPort(dpPort)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800678 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon126171d2016-02-09 01:55:48 -0800679 .matchIPDst(dpIp.toIpPrefix())
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800680 .build();
681
682 treatment = DefaultTrafficTreatment.builder()
683 .setOutput(PortNumber.LOCAL)
684 .build();
685
686 flowRule = DefaultFlowRule.builder()
687 .fromApp(appId)
688 .withSelector(selector)
689 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800690 .withPriority(HIGH_PRIORITY)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800691 .forDevice(deviceId)
692 .forTable(TABLE_FIRST)
693 .makePermanent()
694 .build();
695
696 processFlowRule(true, flowRule);
697
698 // take an arp packet from physical through Linux stack
699 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800700 .matchInPort(dpPort)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800701 .matchEthType(Ethernet.TYPE_ARP)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800702 .matchArpTpa(dpIp.getIp4Address())
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800703 .build();
704
705 treatment = DefaultTrafficTreatment.builder()
706 .setOutput(PortNumber.LOCAL)
707 .build();
708
709 flowRule = DefaultFlowRule.builder()
710 .fromApp(appId)
711 .withSelector(selector)
712 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800713 .withPriority(HIGH_PRIORITY)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800714 .forDevice(deviceId)
715 .forTable(TABLE_FIRST)
716 .makePermanent()
717 .build();
718
719 processFlowRule(true, flowRule);
720
Hyunsun Moon3467a262016-01-14 16:56:26 -0800721 // take all else to the next table
722 selector = DefaultTrafficSelector.builder()
723 .build();
724
725 treatment = DefaultTrafficTreatment.builder()
726 .transition(TABLE_IN_PORT)
727 .build();
728
729 flowRule = DefaultFlowRule.builder()
730 .fromApp(appId)
731 .withSelector(selector)
732 .withTreatment(treatment)
733 .withPriority(LOWEST_PRIORITY)
734 .forDevice(deviceId)
735 .forTable(TABLE_FIRST)
736 .makePermanent()
737 .build();
738
739 processFlowRule(true, flowRule);
Hyunsun Moon01556a52016-02-12 12:48:47 -0800740
741 // take all vlan tagged packet to the Q_IN_Q table
742 selector = DefaultTrafficSelector.builder()
743 .matchVlanId(VlanId.ANY)
744 .build();
745
746 treatment = DefaultTrafficTreatment.builder()
747 .transition(TABLE_Q_IN_Q)
748 .build();
749
750 flowRule = DefaultFlowRule.builder()
751 .fromApp(appId)
752 .withSelector(selector)
753 .withTreatment(treatment)
754 .withPriority(VSG_PRIORITY)
755 .forDevice(deviceId)
756 .forTable(TABLE_FIRST)
757 .makePermanent()
758 .build();
759
760 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800761 }
762
763 /**
Hyunsun Moon126171d2016-02-09 01:55:48 -0800764 * Forward table miss packets in ACCESS_TYPE table to data plane port.
Hyunsun Moonba290072015-12-16 20:53:23 -0800765 *
766 * @param deviceId device id
Hyunsun Moon126171d2016-02-09 01:55:48 -0800767 * @param dpPort data plane interface port number
Hyunsun Moonba290072015-12-16 20:53:23 -0800768 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800769 private void processAccessTypeTable(DeviceId deviceId, PortNumber dpPort) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800770 TrafficSelector selector = DefaultTrafficSelector.builder()
771 .build();
772
773 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800774 .setOutput(dpPort)
Hyunsun Moonba290072015-12-16 20:53:23 -0800775 .build();
776
777 FlowRule flowRule = DefaultFlowRule.builder()
778 .fromApp(appId)
779 .withSelector(selector)
780 .withTreatment(treatment)
781 .withPriority(LOWEST_PRIORITY)
782 .forDevice(deviceId)
783 .forTable(TABLE_ACCESS_TYPE)
784 .makePermanent()
785 .build();
786
787 processFlowRule(true, flowRule);
788 }
789
790 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800791 * Populates default rules for IN_PORT table.
792 * All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
Hyunsun Moon126171d2016-02-09 01:55:48 -0800793 * from data plane interface port to ACCESS_TYPE table.
Hyunsun Moonba290072015-12-16 20:53:23 -0800794 *
795 * @param deviceId device id to install the rules
Hyunsun Moon3467a262016-01-14 16:56:26 -0800796 * @param tunnelPort tunnel port number
Hyunsun Moon126171d2016-02-09 01:55:48 -0800797 * @param dpPort data plane interface port number
Hyunsun Moonba290072015-12-16 20:53:23 -0800798 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800799 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dpPort) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800800 checkNotNull(tunnelPort);
801
802 TrafficSelector selector = DefaultTrafficSelector.builder()
803 .matchInPort(tunnelPort)
804 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800805
Hyunsun Moonba290072015-12-16 20:53:23 -0800806 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
807 .transition(TABLE_TUNNEL_IN)
808 .build();
809
810 FlowRule flowRule = DefaultFlowRule.builder()
811 .fromApp(appId)
812 .withSelector(selector)
813 .withTreatment(treatment)
814 .withPriority(DEFAULT_PRIORITY)
815 .forDevice(deviceId)
816 .forTable(TABLE_IN_PORT)
817 .makePermanent()
818 .build();
819
820 processFlowRule(true, flowRule);
Hyunsun Moon3467a262016-01-14 16:56:26 -0800821
822 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800823 .matchInPort(dpPort)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800824 .build();
825
826 treatment = DefaultTrafficTreatment.builder()
827 .transition(TABLE_DST_IP)
828 .build();
829
830 flowRule = DefaultFlowRule.builder()
831 .fromApp(appId)
832 .withSelector(selector)
833 .withTreatment(treatment)
834 .withPriority(DEFAULT_PRIORITY)
835 .forDevice(deviceId)
836 .forTable(TABLE_IN_PORT)
837 .makePermanent()
838 .build();
839
840 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800841 }
842
843 /**
Hyunsun Moon01556a52016-02-12 12:48:47 -0800844 * Populates default rules for Q_IN_Q table.
845 *
846 * @param deviceId device id
847 * @param dpPort data plane interface port number
848 */
849 private void processQInQTable(DeviceId deviceId, PortNumber dpPort) {
850 // for traffic going out to WAN, strip vid 500 and take through data plane interface
851 TrafficSelector selector = DefaultTrafficSelector.builder()
852 .matchVlanId(VLAN_WAN)
853 .build();
854
855 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
856 .popVlan()
857 .setOutput(dpPort)
858 .build();
859
860 FlowRule flowRule = DefaultFlowRule.builder()
861 .fromApp(appId)
862 .withSelector(selector)
863 .withTreatment(treatment)
864 .withPriority(DEFAULT_PRIORITY)
865 .forDevice(deviceId)
866 .forTable(TABLE_Q_IN_Q)
867 .makePermanent()
868 .build();
869
870 processFlowRule(true, flowRule);
871
872 selector = DefaultTrafficSelector.builder()
873 .matchVlanId(VLAN_WAN)
874 .matchEthType(Ethernet.TYPE_ARP)
875 .build();
876
877 treatment = DefaultTrafficTreatment.builder()
878 .setOutput(PortNumber.CONTROLLER)
879 .build();
880
881 flowRule = DefaultFlowRule.builder()
882 .fromApp(appId)
883 .withSelector(selector)
884 .withTreatment(treatment)
885 .withPriority(HIGH_PRIORITY)
886 .forDevice(deviceId)
887 .forTable(TABLE_Q_IN_Q)
888 .makePermanent()
889 .build();
890
891 processFlowRule(true, flowRule);
892 }
893
894 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800895 * Populates rules for local in port in IN_PORT table.
896 * Flows from a given in port, whose source IP is service IP transition
897 * to DST_TYPE table. Other flows transition to IN_SERVICE table.
898 *
899 * @param deviceId device id to install the rules
900 * @param inPort in port
901 * @param srcIp source ip
902 */
903 private void populateLocalInPortRule(DeviceId deviceId, PortNumber inPort, IpAddress srcIp) {
904 TrafficSelector selector = DefaultTrafficSelector.builder()
905 .matchInPort(inPort)
906 .matchEthType(Ethernet.TYPE_IPV4)
907 .matchIPSrc(srcIp.toIpPrefix())
908 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800909
Hyunsun Moonba290072015-12-16 20:53:23 -0800910 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
911 .transition(TABLE_ACCESS_TYPE)
912 .build();
913
914
915 FlowRule flowRule = DefaultFlowRule.builder()
916 .fromApp(appId)
917 .withSelector(selector)
918 .withTreatment(treatment)
919 .withPriority(DEFAULT_PRIORITY)
920 .forDevice(deviceId)
921 .forTable(TABLE_IN_PORT)
922 .makePermanent()
923 .build();
924
925 processFlowRule(true, flowRule);
926
927 selector = DefaultTrafficSelector.builder()
928 .matchInPort(inPort)
929 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800930
Hyunsun Moonba290072015-12-16 20:53:23 -0800931 treatment = DefaultTrafficTreatment.builder()
932 .transition(TABLE_IN_SERVICE)
933 .build();
934
935 flowRule = DefaultFlowRule.builder()
936 .fromApp(appId)
937 .withSelector(selector)
938 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800939 .withPriority(LOW_PRIORITY)
Hyunsun Moonba290072015-12-16 20:53:23 -0800940 .forDevice(deviceId)
941 .forTable(TABLE_IN_PORT)
942 .makePermanent()
943 .build();
944
945 processFlowRule(true, flowRule);
946 }
947
948 /**
949 * Populates direct VM access rules for ACCESS_TYPE table.
950 * These rules are installed to all devices.
951 *
952 * @param srcRange source ip range
953 * @param dstRange destination ip range
954 */
955 private void populateDirectAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange) {
956 TrafficSelector selector = DefaultTrafficSelector.builder()
957 .matchEthType(Ethernet.TYPE_IPV4)
958 .matchIPSrc(srcRange)
959 .matchIPDst(dstRange)
960 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800961
Hyunsun Moonba290072015-12-16 20:53:23 -0800962 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
963 .transition(TABLE_DST_IP)
964 .build();
965
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800966
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800967 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moonba290072015-12-16 20:53:23 -0800968 FlowRule flowRuleDirect = DefaultFlowRule.builder()
969 .fromApp(appId)
970 .withSelector(selector)
971 .withTreatment(treatment)
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800972 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800973 .forDevice(deviceId)
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800974 .forTable(TABLE_ACCESS_TYPE)
975 .makePermanent()
976 .build();
977
978 processFlowRule(true, flowRuleDirect);
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800979 });
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800980 }
981
982 /**
983 * Populates drop rules that does not match any direct access rules but has
984 * destination to a different service network in ACCESS_TYPE table.
985 *
986 * @param dstRange destination ip range
987 */
988 private void populateServiceIsolationRule(Ip4Prefix dstRange) {
989 TrafficSelector selector = DefaultTrafficSelector.builder()
990 .matchEthType(Ethernet.TYPE_IPV4)
991 .matchIPDst(dstRange)
992 .build();
993
994 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
995 .drop()
996 .build();
997
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800998 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800999 FlowRule flowRuleDirect = DefaultFlowRule.builder()
1000 .fromApp(appId)
1001 .withSelector(selector)
1002 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -08001003 .withPriority(LOW_PRIORITY)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001004 .forDevice(deviceId)
Hyunsun Moonba290072015-12-16 20:53:23 -08001005 .forTable(TABLE_ACCESS_TYPE)
1006 .makePermanent()
1007 .build();
1008
1009 processFlowRule(true, flowRuleDirect);
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001010 });
Hyunsun Moonba290072015-12-16 20:53:23 -08001011 }
1012
1013 /**
1014 * Populates indirect service access rules for ACCESS_TYPE table.
1015 * These rules are installed to all devices.
1016 *
1017 * @param srcRange source range
1018 * @param serviceIp service ip
1019 * @param outGroups list of output group
1020 */
1021 private void populateIndirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
1022 Map<DeviceId, GroupId> outGroups) {
1023 TrafficSelector selector = DefaultTrafficSelector.builder()
1024 .matchEthType(Ethernet.TYPE_IPV4)
1025 .matchIPSrc(srcRange)
1026 .matchIPDst(serviceIp.toIpPrefix())
1027 .build();
1028
1029 for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
1030 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1031 .group(outGroup.getValue())
1032 .build();
1033
1034 FlowRule flowRule = DefaultFlowRule.builder()
1035 .fromApp(appId)
1036 .withSelector(selector)
1037 .withTreatment(treatment)
Hyunsun Moon1257efc2016-02-01 23:00:56 -08001038 .withPriority(HIGH_PRIORITY)
Hyunsun Moonba290072015-12-16 20:53:23 -08001039 .forDevice(outGroup.getKey())
1040 .forTable(TABLE_ACCESS_TYPE)
1041 .makePermanent()
1042 .build();
1043
1044 processFlowRule(true, flowRule);
1045 }
1046 }
1047
1048 /**
1049 * Populates flow rules for IN_SERVICE table.
1050 *
1051 * @param inPorts list of inports related to the service for each device
1052 * @param outGroups set of output groups
1053 */
1054 private void populateInServiceRule(Map<DeviceId, Set<PortNumber>> inPorts, Map<DeviceId, GroupId> outGroups) {
1055 checkNotNull(inPorts);
1056 checkNotNull(outGroups);
1057
1058 for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
1059 Set<PortNumber> ports = entry.getValue();
1060 DeviceId deviceId = entry.getKey();
1061
1062 GroupId groupId = outGroups.get(deviceId);
1063 if (groupId == null) {
1064 continue;
1065 }
1066
1067 ports.stream().forEach(port -> {
1068 TrafficSelector selector = DefaultTrafficSelector.builder()
1069 .matchInPort(port)
1070 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -08001071
Hyunsun Moonba290072015-12-16 20:53:23 -08001072 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1073 .group(groupId)
1074 .build();
1075
1076 FlowRule flowRule = DefaultFlowRule.builder()
1077 .fromApp(appId)
1078 .withSelector(selector)
1079 .withTreatment(treatment)
1080 .withPriority(DEFAULT_PRIORITY)
1081 .forDevice(deviceId)
1082 .forTable(TABLE_IN_SERVICE)
1083 .makePermanent()
1084 .build();
1085
1086 processFlowRule(true, flowRule);
1087 });
1088 }
1089 }
1090
1091 /**
1092 * Populates flow rules for DST_IP table.
1093 *
1094 * @param deviceId device id
1095 * @param inPort in port
1096 * @param dstMac mac address
1097 * @param dstIp destination ip
1098 * @param tunnelId tunnel id
1099 * @param tunnelIp tunnel remote ip
1100 */
1101 private void populateDstIpRule(DeviceId deviceId, PortNumber inPort, MacAddress dstMac,
1102 IpAddress dstIp, long tunnelId, IpAddress tunnelIp) {
1103 TrafficSelector selector = DefaultTrafficSelector.builder()
1104 .matchEthType(Ethernet.TYPE_IPV4)
1105 .matchIPDst(dstIp.toIpPrefix())
1106 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -08001107
Hyunsun Moonba290072015-12-16 20:53:23 -08001108 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1109 .setEthDst(dstMac)
1110 .setOutput(inPort)
1111 .build();
1112
1113 FlowRule flowRule = DefaultFlowRule.builder()
1114 .fromApp(appId)
1115 .withSelector(selector)
1116 .withTreatment(treatment)
1117 .withPriority(DEFAULT_PRIORITY)
1118 .forDevice(deviceId)
1119 .forTable(TABLE_DST_IP)
1120 .makePermanent()
1121 .build();
1122
1123 processFlowRule(true, flowRule);
1124
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001125 for (DeviceId vSwitchId : getVirtualSwitches()) {
1126 if (vSwitchId.equals(deviceId)) {
Hyunsun Moon7004fcf2016-03-08 04:36:02 -08001127 continue;
1128 }
1129
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001130 ExtensionTreatment tunnelDst = getTunnelDst(vSwitchId, tunnelIp.getIp4Address());
Hyunsun Moonba290072015-12-16 20:53:23 -08001131 if (tunnelDst == null) {
1132 continue;
1133 }
1134
1135 treatment = DefaultTrafficTreatment.builder()
1136 .setEthDst(dstMac)
1137 .setTunnelId(tunnelId)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001138 .extension(tunnelDst, vSwitchId)
1139 .setOutput(getTunnelPort(vSwitchId))
Hyunsun Moonba290072015-12-16 20:53:23 -08001140 .build();
1141
1142 flowRule = DefaultFlowRule.builder()
1143 .fromApp(appId)
1144 .withSelector(selector)
1145 .withTreatment(treatment)
1146 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001147 .forDevice(vSwitchId)
Hyunsun Moonba290072015-12-16 20:53:23 -08001148 .forTable(TABLE_DST_IP)
1149 .makePermanent()
1150 .build();
1151
1152 processFlowRule(true, flowRule);
1153 }
1154 }
1155
1156 /**
1157 * Populates flow rules for TUNNEL_ID table.
1158 *
1159 * @param deviceId device id
1160 * @param inPort in port
1161 * @param mac mac address
1162 * @param tunnelId tunnel id
1163 */
1164 private void populateTunnelInRule(DeviceId deviceId, PortNumber inPort, MacAddress mac, long tunnelId) {
1165 TrafficSelector selector = DefaultTrafficSelector.builder()
1166 .matchTunnelId(tunnelId)
1167 .matchEthDst(mac)
1168 .build();
1169
1170 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1171 .setOutput(inPort)
1172 .build();
1173
1174 FlowRule flowRule = DefaultFlowRule.builder()
1175 .fromApp(appId)
1176 .withSelector(selector)
1177 .withTreatment(treatment)
1178 .withPriority(DEFAULT_PRIORITY)
1179 .forDevice(deviceId)
1180 .forTable(TABLE_TUNNEL_IN)
1181 .makePermanent()
1182 .build();
1183
1184 processFlowRule(true, flowRule);
1185 }
1186
1187 /**
1188 * Installs or uninstall a given rule.
1189 *
1190 * @param install true to install, false to uninstall
1191 * @param rule rule
1192 */
1193 private void processFlowRule(boolean install, FlowRule rule) {
1194 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
1195 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
1196
1197 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
1198 @Override
1199 public void onError(FlowRuleOperations ops) {
1200 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
1201 }
1202 }));
1203 }
1204
1205 /**
1206 * Returns tunnel port of the device.
1207 *
1208 * @param deviceId device id
1209 * @return tunnel port number, or null if no tunnel port exists on a given device
1210 */
1211 private PortNumber getTunnelPort(DeviceId deviceId) {
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001212 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon01556a52016-02-12 12:48:47 -08001213 .filter(p -> p.annotations().value(PORT_NAME).contains(tunnelType))
1214 .findFirst().orElse(null);
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001215
1216 return port == null ? null : port.number();
Hyunsun Moonba290072015-12-16 20:53:23 -08001217 }
1218
1219 /**
Hyunsun Moon126171d2016-02-09 01:55:48 -08001220 * Returns data plane interface port name of a given device.
Hyunsun Moon3467a262016-01-14 16:56:26 -08001221 *
1222 * @param deviceId device id
Hyunsun Moon126171d2016-02-09 01:55:48 -08001223 * @param dpIntf data plane interface port name
1224 * @return data plane interface port number, or null if no such port exists
Hyunsun Moon3467a262016-01-14 16:56:26 -08001225 */
Hyunsun Moon126171d2016-02-09 01:55:48 -08001226 private PortNumber getDpPort(DeviceId deviceId, String dpIntf) {
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001227 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon01556a52016-02-12 12:48:47 -08001228 .filter(p -> p.annotations().value(PORT_NAME).contains(dpIntf) &&
1229 p.isEnabled())
1230 .findFirst().orElse(null);
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001231
1232 return port == null ? null : port.number();
Hyunsun Moon3467a262016-01-14 16:56:26 -08001233 }
1234
Hyunsun Moon01556a52016-02-12 12:48:47 -08001235 /** Returns data plane interface port number of a given host.
1236 *
1237 * @param host host
1238 * @return port number, or null
1239 */
1240 private PortNumber getDpPort(Host host) {
1241 String portName = host.annotations().value(DATA_PLANE_INTF);
1242 return portName == null ? null : getDpPort(host.location().deviceId(), portName);
1243 }
1244
1245 /**
1246 * Returns service vlan from a given host.
1247 *
1248 * @param host host
1249 * @return vlan id, or null
1250 */
1251 private VlanId getServiceVlan(Host host) {
1252 String serviceVlan = host.annotations().value(S_TAG);
1253 return serviceVlan == null ? null : VlanId.vlanId(Short.parseShort(serviceVlan));
1254 }
1255
Hyunsun Moon3467a262016-01-14 16:56:26 -08001256 /**
Hyunsun Moonba290072015-12-16 20:53:23 -08001257 * Returns the inport from a given flow rule if the rule contains the match of it.
1258 *
1259 * @param flowRule flow rule
1260 * @return port number, or null if the rule doesn't have inport match
1261 */
1262 private PortNumber getInPort(FlowRule flowRule) {
1263 Criterion criterion = flowRule.selector().getCriterion(IN_PORT);
1264 if (criterion != null && criterion instanceof PortCriterion) {
1265 PortCriterion port = (PortCriterion) criterion;
1266 return port.port();
1267 } else {
1268 return null;
1269 }
1270 }
1271
1272 /**
1273 * Returns the destination mac address from a given flow rule if the rule
1274 * contains the instruction of it.
1275 *
1276 * @param flowRule flow rule
1277 * @return mac address, or null if the rule doesn't have destination mac instruction
1278 */
1279 private MacAddress getDstMacFromTreatment(FlowRule flowRule) {
1280 Instruction instruction = flowRule.treatment().allInstructions().stream()
1281 .filter(inst -> inst instanceof ModEtherInstruction &&
1282 ((ModEtherInstruction) inst).subtype().equals(ETH_DST))
1283 .findFirst()
1284 .orElse(null);
1285
1286 if (instruction == null) {
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001287 return null;
1288 }
1289
Hyunsun Moonba290072015-12-16 20:53:23 -08001290 return ((ModEtherInstruction) instruction).mac();
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001291 }
1292
1293 /**
Hyunsun Moonba290072015-12-16 20:53:23 -08001294 * Returns the destination mac address from a given flow rule if the rule
1295 * contains the match of it.
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001296 *
Hyunsun Moonba290072015-12-16 20:53:23 -08001297 * @param flowRule flow rule
1298 * @return mac address, or null if the rule doesn't have destination mac match
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001299 */
Hyunsun Moonba290072015-12-16 20:53:23 -08001300 private MacAddress getDstMacFromSelector(FlowRule flowRule) {
1301 Criterion criterion = flowRule.selector().getCriterion(Criterion.Type.ETH_DST);
1302 if (criterion != null && criterion instanceof EthCriterion) {
1303 EthCriterion eth = (EthCriterion) criterion;
1304 return eth.mac();
1305 } else {
1306 return null;
1307 }
1308 }
1309
1310 /**
1311 * Returns the destination IP from a given flow rule if the rule contains
1312 * the match of it.
1313 *
1314 * @param flowRule flow rule
1315 * @return ip prefix, or null if the rule doesn't have ip match
1316 */
1317 private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
1318 Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
1319 if (criterion != null && criterion instanceof IPCriterion) {
1320 IPCriterion ip = (IPCriterion) criterion;
1321 return ip.ip();
1322 } else {
1323 return null;
1324 }
1325 }
1326
1327 /**
1328 * Returns the source IP from a given flow rule if the rule contains
1329 * the match of it.
1330 *
1331 * @param flowRule flow rule
1332 * @return ip prefix, or null if the rule doesn't have ip match
1333 */
1334 private IpPrefix getSrcIpFromSelector(FlowRule flowRule) {
1335 Criterion criterion = flowRule.selector().getCriterion(IPV4_SRC);
1336 if (criterion != null && criterion instanceof IPCriterion) {
1337 IPCriterion ip = (IPCriterion) criterion;
1338 return ip.ip();
1339 } else {
1340 return null;
1341 }
1342 }
1343
1344 /**
1345 * Returns the group ID from a given flow rule if the rule contains the
1346 * treatment of it.
1347 *
1348 * @param flowRule flow rule
1349 * @return group id, or null if the rule doesn't have group instruction
1350 */
1351 private GroupId getGroupIdFromTreatment(FlowRule flowRule) {
1352 Instruction instruction = flowRule.treatment().allInstructions().stream()
1353 .filter(inst -> inst instanceof Instructions.GroupInstruction)
1354 .findFirst()
1355 .orElse(null);
1356
1357 if (instruction == null) {
1358 return null;
1359 }
1360
1361 return ((Instructions.GroupInstruction) instruction).groupId();
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001362 }
1363
1364 /**
Hyunsun Moon64ec6142016-01-29 18:57:05 -08001365 * Returns the output port number from a given flow rule.
1366 *
1367 * @param flowRule flow rule
1368 * @return port number, or null if the rule does not have output instruction
1369 */
1370 private PortNumber getOutputFromTreatment(FlowRule flowRule) {
1371 Instruction instruction = flowRule.treatment().allInstructions().stream()
Hyunsun Moon01556a52016-02-12 12:48:47 -08001372 .filter(inst -> inst instanceof Instructions.OutputInstruction)
Hyunsun Moon64ec6142016-01-29 18:57:05 -08001373 .findFirst()
1374 .orElse(null);
1375
1376 if (instruction == null) {
1377 return null;
1378 }
1379
1380 return ((Instructions.OutputInstruction) instruction).port();
1381 }
1382
1383 /**
Hyunsun Moon01556a52016-02-12 12:48:47 -08001384 * Returns if a given flow rule has vlan push instruction or not.
1385 *
1386 * @param flowRule flow rule
1387 * @return true if it includes vlan push, or false
1388 */
1389 private boolean isVlanPushFromTreatment(FlowRule flowRule) {
1390 Instruction instruction = flowRule.treatment().allInstructions().stream()
1391 .filter(inst -> inst instanceof L2ModificationInstruction)
1392 .filter(inst -> ((L2ModificationInstruction) inst).subtype().equals(VLAN_PUSH))
1393 .findAny()
1394 .orElse(null);
1395
1396 return instruction != null;
1397 }
1398
1399 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -08001400 * Creates a new group for a given service.
1401 *
1402 * @param deviceId device id to create a group
1403 * @param service cord service
1404 * @return group id, or null if it fails to create
1405 */
1406 private GroupId createServiceGroup(DeviceId deviceId, CordService service) {
1407 checkNotNull(service);
1408
1409 GroupKey groupKey = getGroupKey(service.id());
1410 Group group = groupService.getGroup(deviceId, groupKey);
1411 GroupId groupId = getGroupId(service.id(), deviceId);
1412
1413 if (group != null) {
1414 log.debug("Group {} is already exist in {}", service.id(), deviceId);
1415 return groupId;
1416 }
1417
1418 GroupBuckets buckets = getServiceGroupBuckets(deviceId, service.segmentationId(), service.hosts());
1419 GroupDescription groupDescription = new DefaultGroupDescription(
1420 deviceId,
1421 GroupDescription.Type.SELECT,
1422 buckets,
1423 groupKey,
1424 groupId.id(),
1425 appId);
1426
1427 groupService.addGroup(groupDescription);
1428
1429 return groupId;
1430 }
1431
1432 /**
1433 * Returns group buckets for a given device.
1434 *
1435 * @param deviceId device id
1436 * @param tunnelId tunnel id
1437 * @param hosts list of host
1438 * @return group buckets
1439 */
1440 private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId, Map<Host, IpAddress> hosts) {
1441 List<GroupBucket> buckets = Lists.newArrayList();
1442
1443 for (Map.Entry<Host, IpAddress> entry : hosts.entrySet()) {
1444 Host host = entry.getKey();
1445 Ip4Address remoteIp = entry.getValue().getIp4Address();
1446 DeviceId hostDevice = host.location().deviceId();
1447
1448 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
1449 .builder()
1450 .setEthDst(host.mac());
1451
1452 if (deviceId.equals(hostDevice)) {
1453 tBuilder.setOutput(host.location().port());
1454 } else {
1455 ExtensionTreatment tunnelDst = getTunnelDst(deviceId, remoteIp);
1456 if (tunnelDst == null) {
1457 continue;
1458 }
1459
1460 tBuilder.extension(tunnelDst, deviceId)
1461 .setTunnelId(tunnelId)
1462 .setOutput(getTunnelPort(hostDevice));
1463 }
1464
1465 buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
1466 }
1467
1468 return new GroupBuckets(buckets);
1469 }
1470
1471 /**
1472 * Returns globally unique group ID.
1473 *
1474 * @param serviceId service id
1475 * @param deviceId device id
1476 * @return group id
1477 */
1478 private GroupId getGroupId(CordServiceId serviceId, DeviceId deviceId) {
1479 return new DefaultGroupId(Objects.hash(serviceId, deviceId));
1480 }
1481
1482 /**
1483 * Returns group key of a service.
1484 *
1485 * @param serviceId service id
1486 * @return group key
1487 */
1488 private GroupKey getGroupKey(CordServiceId serviceId) {
1489 return new DefaultGroupKey(serviceId.id().getBytes());
1490 }
1491
1492 /**
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001493 * Returns extension instruction to set tunnel destination.
1494 *
1495 * @param deviceId device id
1496 * @param remoteIp tunnel destination address
1497 * @return extension treatment or null if it fails to get instruction
1498 */
Hyunsun Moonba290072015-12-16 20:53:23 -08001499 private ExtensionTreatment getTunnelDst(DeviceId deviceId, Ip4Address remoteIp) {
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001500 try {
1501 Driver driver = driverService.getDriver(deviceId);
Hyunsun Moonba290072015-12-16 20:53:23 -08001502 DefaultDriverData driverData = new DefaultDriverData(driver, deviceId);
1503 DriverHandler handler = new DefaultDriverHandler(driverData);
1504 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001505
Hyunsun Moonba290072015-12-16 20:53:23 -08001506 ExtensionTreatment treatment =
1507 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001508 treatment.setPropertyValue("tunnelDst", remoteIp);
1509
1510 return treatment;
Hyunsun Moonba290072015-12-16 20:53:23 -08001511 } catch (ItemNotFoundException | UnsupportedOperationException |
1512 ExtensionPropertyException e) {
1513 log.error("Failed to get extension instruction {}", deviceId);
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001514 return null;
1515 }
1516 }
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001517
1518 /**
1519 * Returns integration bridges configured in the system.
1520 *
1521 * @return set of device ids
1522 */
1523 private Set<DeviceId> getVirtualSwitches() {
1524 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
1525 if (config == null) {
1526 log.debug("No configuration found for {}", appId.name());
1527 return Sets.newHashSet();
1528 }
1529
1530 return config.cordVtnNodes().stream()
1531 .map(CordVtnNode::intBrId).collect(Collectors.toSet());
1532 }
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001533}
Hyunsun Moonba290072015-12-16 20:53:23 -08001534