blob: 1c34a62a25dc98ba651b5a2b629b093bf97de756 [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;
Hyunsun Moonfae776d2016-03-08 18:07:52 -080020import com.google.common.collect.Sets;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080021import org.onlab.packet.Ethernet;
Hyunsun Moon4a915152016-01-14 16:56:26 -080022import org.onlab.packet.IPv4;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080023import org.onlab.packet.Ip4Address;
Hyunsun Moonc71231d2015-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 Moon4a915152016-01-14 16:56:26 -080028import org.onlab.packet.TpPort;
Hyunsun Moon6d247342016-02-12 12:48:47 -080029import org.onlab.packet.VlanId;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080030import org.onlab.util.ItemNotFoundException;
31import org.onosproject.core.ApplicationId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080032import org.onosproject.core.DefaultGroupId;
33import org.onosproject.core.GroupId;
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 Moonfae776d2016-03-08 18:07:52 -080039import org.onosproject.net.config.NetworkConfigRegistry;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080040import org.onosproject.net.device.DeviceService;
Hyunsun Moon9f0814b2015-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 Moonc71231d2015-12-16 20:53:23 -080046import org.onosproject.net.flow.DefaultFlowRule;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080047import org.onosproject.net.flow.DefaultTrafficSelector;
48import org.onosproject.net.flow.DefaultTrafficTreatment;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080053import org.onosproject.net.flow.TrafficSelector;
54import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080059import org.onosproject.net.flow.instructions.ExtensionPropertyException;
60import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080061import org.onosproject.net.flow.instructions.Instruction;
62import org.onosproject.net.flow.instructions.Instructions;
Hyunsun Moon6d247342016-02-12 12:48:47 -080063import org.onosproject.net.flow.instructions.L2ModificationInstruction;
Hyunsun Moonc71231d2015-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;
sangho93447f12016-02-24 00:33:22 +090074import org.onosproject.openstackinterface.OpenstackNetwork;
75import org.onosproject.openstackinterface.OpenstackSubnet;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080076import org.slf4j.Logger;
77
Hyunsun Moon4161e6f2016-01-07 01:32:31 -080078import java.util.ArrayList;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080079import java.util.List;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080080import java.util.Map;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080081import java.util.Objects;
82import java.util.Set;
83import java.util.stream.Collectors;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080084
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080085import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moonc71231d2015-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 Moon9f0814b2015-11-04 17:34:35 -080089import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080090import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
Hyunsun Moon6d247342016-02-12 12:48:47 -080091import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080092import static org.slf4j.LoggerFactory.getLogger;
93
94/**
Hyunsun Moonc71231d2015-12-16 20:53:23 -080095 * Populates rules for CORD VTN service.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080096 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -080097public class CordVtnRuleInstaller {
98
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080099 protected final Logger log = getLogger(getClass());
100
Hyunsun Moon4a915152016-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 Moon6d247342016-02-12 12:48:47 -0800107 private static final int TABLE_Q_IN_Q = 6;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800108
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800109 private static final int MANAGEMENT_PRIORITY = 55000;
Hyunsun Moon6d247342016-02-12 12:48:47 -0800110 private static final int VSG_PRIORITY = 55000;
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800111 private static final int HIGH_PRIORITY = 50000;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800112 private static final int DEFAULT_PRIORITY = 5000;
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800113 private static final int LOW_PRIORITY = 4000;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800114 private static final int LOWEST_PRIORITY = 0;
Hyunsun Moon4a915152016-01-14 16:56:26 -0800115
116 private static final int VXLAN_UDP_PORT = 4789;
Hyunsun Moon6d247342016-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 Moon9f0814b2015-11-04 17:34:35 -0800122
123 private final ApplicationId appId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800124 private final FlowRuleService flowRuleService;
125 private final DeviceService deviceService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800126 private final DriverService driverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800127 private final GroupService groupService;
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800128 private final NetworkConfigRegistry configRegistry;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800129 private final String tunnelType;
130
131 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800132 * Creates a new rule populator.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800133 *
134 * @param appId application id
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800135 * @param flowRuleService flow rule service
136 * @param deviceService device service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800137 * @param driverService driver service
Jian Lidfba7392016-01-22 16:46:58 -0800138 * @param groupService group service
Ray Milkeyd4334db2016-04-05 17:39:44 -0700139 * @param configRegistry config registry
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800140 * @param tunnelType tunnel type
141 */
142 public CordVtnRuleInstaller(ApplicationId appId,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800143 FlowRuleService flowRuleService,
144 DeviceService deviceService,
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800145 DriverService driverService,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800146 GroupService groupService,
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800147 NetworkConfigRegistry configRegistry,
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800148 String tunnelType) {
149 this.appId = appId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800150 this.flowRuleService = flowRuleService;
151 this.deviceService = deviceService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800152 this.driverService = driverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800153 this.groupService = groupService;
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800154 this.configRegistry = configRegistry;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800155 this.tunnelType = checkNotNull(tunnelType);
156 }
157
158 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800159 * Installs table miss rule to a give device.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800160 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800161 * @param deviceId device id to install the rules
Hyunsun Moon133fd792016-02-09 01:55:48 -0800162 * @param dpIntf data plane interface name
163 * @param dpIp data plane ip address
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800164 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800165 public void init(DeviceId deviceId, String dpIntf, IpAddress dpIp) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800166 // default is drop packets which can be accomplished without
167 // a table miss entry for all table.
Hyunsun Moon4a915152016-01-14 16:56:26 -0800168 PortNumber tunnelPort = getTunnelPort(deviceId);
Hyunsun Moon133fd792016-02-09 01:55:48 -0800169 PortNumber dpPort = getDpPort(deviceId, dpIntf);
Hyunsun Moon4a915152016-01-14 16:56:26 -0800170
Hyunsun Moon133fd792016-02-09 01:55:48 -0800171 processFirstTable(deviceId, dpPort, dpIp);
172 processInPortTable(deviceId, tunnelPort, dpPort);
173 processAccessTypeTable(deviceId, dpPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800174 processQInQTable(deviceId, dpPort);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800175 }
176
177 /**
Hyunsun Moon2062e7e2016-03-08 15:37:57 -0800178 * Flush flows installed by this application.
179 */
180 public void flushRules() {
181 flowRuleService.getFlowRulesById(appId).forEach(flowRule -> processFlowRule(false, flowRule));
182 }
183
184 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800185 * Populates basic rules that connect a VM to the other VMs in the system.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800186 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800187 * @param host host
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800188 * @param tunnelIp tunnel ip
189 * @param vNet openstack network
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800190 */
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800191 public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, OpenstackNetwork vNet) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800192 checkNotNull(host);
193 checkNotNull(vNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800194
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800195 DeviceId deviceId = host.location().deviceId();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800196 PortNumber inPort = host.location().port();
197 MacAddress dstMac = host.mac();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800198 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800199 long tunnelId = Long.parseLong(vNet.segmentId());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800200
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800201 OpenstackSubnet subnet = vNet.subnets().stream()
202 .findFirst()
203 .orElse(null);
204
205 if (subnet == null) {
206 log.error("Failed to get subnet for {}", host.id());
207 return;
208 }
209
210 populateLocalInPortRule(deviceId, inPort, hostIp);
211 populateDirectAccessRule(Ip4Prefix.valueOf(subnet.cidr()), Ip4Prefix.valueOf(subnet.cidr()));
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800212 populateServiceIsolationRule(Ip4Prefix.valueOf(subnet.cidr()));
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800213 populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
214 populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800215 }
216
217 /**
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800218 * Removes all rules related to a given service VM host.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800219 *
220 * @param host host to be removed
221 */
222 public void removeBasicConnectionRules(Host host) {
223 checkNotNull(host);
224
225 DeviceId deviceId = host.location().deviceId();
226 MacAddress mac = host.mac();
227 PortNumber port = host.location().port();
228 IpAddress ip = host.ipAddresses().stream().findFirst().orElse(null);
229
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800230 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
231 if (flowRule.deviceId().equals(deviceId)) {
232 PortNumber inPort = getInPort(flowRule);
233 if (inPort != null && inPort.equals(port)) {
234 processFlowRule(false, flowRule);
235 continue;
236 }
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800237
238 PortNumber output = getOutputFromTreatment(flowRule);
239 if (output != null && output.equals(host.location().port())) {
240 processFlowRule(false, flowRule);
241 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800242 }
243
244 MacAddress dstMac = getDstMacFromTreatment(flowRule);
245 if (dstMac != null && dstMac.equals(mac)) {
246 processFlowRule(false, flowRule);
247 continue;
248 }
249
250 dstMac = getDstMacFromSelector(flowRule);
251 if (dstMac != null && dstMac.equals(mac)) {
252 processFlowRule(false, flowRule);
253 continue;
254 }
255
256 IpPrefix dstIp = getDstIpFromSelector(flowRule);
257 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
258 processFlowRule(false, flowRule);
259 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800260 }
261
262 // TODO uninstall same network access rule in access table if no vm exists in the network
263 }
264
265 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800266 * Populates service dependency rules.
267 *
268 * @param tService tenant cord service
269 * @param pService provider cord service
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800270 * @param isBidirectional true to enable bidirectional connection between two services
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800271 */
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800272 public void populateServiceDependencyRules(CordService tService, CordService pService,
273 boolean isBidirectional) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800274 checkNotNull(tService);
275 checkNotNull(pService);
276
277 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
278 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
279 Ip4Address serviceIp = pService.serviceIp().getIp4Address();
280
281 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
282 Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
283
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800284 getVirtualSwitches().stream().forEach(deviceId -> {
285 GroupId groupId = createServiceGroup(deviceId, pService);
286 outGroups.put(deviceId, groupId);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800287
288 Set<PortNumber> vms = tService.hosts().keySet()
289 .stream()
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800290 .filter(host -> host.location().deviceId().equals(deviceId))
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800291 .map(host -> host.location().port())
292 .collect(Collectors.toSet());
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800293 inPorts.put(deviceId, vms);
294 });
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800295
296 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
297 populateDirectAccessRule(srcRange, dstRange);
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800298 if (isBidirectional) {
299 populateDirectAccessRule(dstRange, srcRange);
300 }
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800301 populateInServiceRule(inPorts, outGroups);
302 }
303
304 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800305 * Removes service dependency rules.
306 *
307 * @param tService tenant cord service
308 * @param pService provider cord service
309 */
310 public void removeServiceDependencyRules(CordService tService, CordService pService) {
311 checkNotNull(tService);
312 checkNotNull(pService);
313
314 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
315 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
316 IpPrefix serviceIp = pService.serviceIp().toIpPrefix();
317
318 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
319 GroupKey groupKey = new DefaultGroupKey(pService.id().id().getBytes());
320
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800321 getVirtualSwitches().stream().forEach(deviceId -> {
322 Group group = groupService.getGroup(deviceId, groupKey);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800323 if (group != null) {
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800324 outGroups.put(deviceId, group.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800325 }
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800326 });
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800327
328 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
329 IpPrefix dstIp = getDstIpFromSelector(flowRule);
330 IpPrefix srcIp = getSrcIpFromSelector(flowRule);
331
332 if (dstIp != null && dstIp.equals(serviceIp)) {
333 processFlowRule(false, flowRule);
334 continue;
335 }
336
337 if (dstIp != null && srcIp != null) {
338 if (dstIp.equals(dstRange) && srcIp.equals(srcRange)) {
339 processFlowRule(false, flowRule);
340 continue;
341 }
342
343 if (dstIp.equals(srcRange) && srcIp.equals(dstRange)) {
344 processFlowRule(false, flowRule);
345 continue;
346 }
347 }
348
349 GroupId groupId = getGroupIdFromTreatment(flowRule);
350 if (groupId != null && groupId.equals(outGroups.get(flowRule.deviceId()))) {
351 processFlowRule(false, flowRule);
352 }
353 }
354
355 // TODO remove the group if it is not in use
356 }
357
358 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800359 * Updates group buckets for a given service to all devices.
360 *
361 * @param service cord service
362 */
363 public void updateServiceGroup(CordService service) {
364 checkNotNull(service);
365
366 GroupKey groupKey = getGroupKey(service.id());
367
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800368 for (DeviceId deviceId : getVirtualSwitches()) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800369 Group group = groupService.getGroup(deviceId, groupKey);
370 if (group == null) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800371 log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800372 continue;
373 }
374
375 List<GroupBucket> oldBuckets = group.buckets().buckets();
376 List<GroupBucket> newBuckets = getServiceGroupBuckets(
377 deviceId, service.segmentationId(), service.hosts()).buckets();
378
379 if (oldBuckets.equals(newBuckets)) {
380 continue;
381 }
382
383 List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
384 bucketsToRemove.removeAll(newBuckets);
385 if (!bucketsToRemove.isEmpty()) {
386 groupService.removeBucketsFromGroup(
387 deviceId,
388 groupKey,
389 new GroupBuckets(bucketsToRemove),
390 groupKey, appId);
391 }
392
393 List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
394 bucketsToAdd.removeAll(oldBuckets);
395 if (!bucketsToAdd.isEmpty()) {
396 groupService.addBucketsToGroup(
397 deviceId,
398 groupKey,
399 new GroupBuckets(bucketsToAdd),
400 groupKey, appId);
401 }
402 }
403 }
404
405 /**
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800406 * Populates flow rules for management network access.
407 *
408 * @param host host which has management network interface
409 * @param mService management network service
410 */
411 public void populateManagementNetworkRules(Host host, CordService mService) {
412 checkNotNull(mService);
413
414 DeviceId deviceId = host.location().deviceId();
415 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
416
417 TrafficSelector selector = DefaultTrafficSelector.builder()
418 .matchEthType(Ethernet.TYPE_ARP)
419 .matchArpTpa(mService.serviceIp().getIp4Address())
420 .build();
421
422 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
423 .setOutput(PortNumber.LOCAL)
424 .build();
425
426 FlowRule flowRule = DefaultFlowRule.builder()
427 .fromApp(appId)
428 .withSelector(selector)
429 .withTreatment(treatment)
430 .withPriority(MANAGEMENT_PRIORITY)
431 .forDevice(deviceId)
432 .forTable(TABLE_FIRST)
433 .makePermanent()
434 .build();
435
436 processFlowRule(true, flowRule);
437
438 selector = DefaultTrafficSelector.builder()
439 .matchInPort(PortNumber.LOCAL)
440 .matchEthType(Ethernet.TYPE_ARP)
441 .matchArpTpa(hostIp.getIp4Address())
442 .build();
443
444 treatment = DefaultTrafficTreatment.builder()
445 .setOutput(host.location().port())
446 .build();
447
448 flowRule = DefaultFlowRule.builder()
449 .fromApp(appId)
450 .withSelector(selector)
451 .withTreatment(treatment)
452 .withPriority(MANAGEMENT_PRIORITY)
453 .forDevice(deviceId)
454 .forTable(TABLE_FIRST)
455 .makePermanent()
456 .build();
457
458 processFlowRule(true, flowRule);
459
460 selector = DefaultTrafficSelector.builder()
461 .matchInPort(PortNumber.LOCAL)
462 .matchEthType(Ethernet.TYPE_IPV4)
463 .matchIPDst(mService.serviceIpRange())
464 .build();
465
466 treatment = DefaultTrafficTreatment.builder()
467 .transition(TABLE_DST_IP)
468 .build();
469
470 flowRule = DefaultFlowRule.builder()
471 .fromApp(appId)
472 .withSelector(selector)
473 .withTreatment(treatment)
474 .withPriority(MANAGEMENT_PRIORITY)
475 .forDevice(deviceId)
476 .forTable(TABLE_FIRST)
477 .makePermanent()
478 .build();
479
480 processFlowRule(true, flowRule);
481
482 selector = DefaultTrafficSelector.builder()
483 .matchEthType(Ethernet.TYPE_IPV4)
484 .matchIPDst(mService.serviceIp().toIpPrefix())
485 .build();
486
487 treatment = DefaultTrafficTreatment.builder()
488 .setOutput(PortNumber.LOCAL)
489 .build();
490
491 flowRule = DefaultFlowRule.builder()
492 .fromApp(appId)
493 .withSelector(selector)
494 .withTreatment(treatment)
495 .withPriority(MANAGEMENT_PRIORITY)
496 .forDevice(deviceId)
497 .forTable(TABLE_ACCESS_TYPE)
498 .makePermanent()
499 .build();
500
501 processFlowRule(true, flowRule);
502 }
503
504 /**
505 * Removes management network access rules.
506 *
507 * @param host host to be removed
508 * @param mService service for management network
509 */
510 public void removeManagementNetworkRules(Host host, CordService mService) {
511 checkNotNull(mService);
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800512 // TODO remove management network specific rules
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800513 }
514
515 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800516 * Populates rules for vSG VM.
517 *
518 * @param vSgHost vSG host
519 * @param vSgIps set of ip addresses of vSGs running inside the vSG VM
520 */
521 public void populateSubscriberGatewayRules(Host vSgHost, Set<IpAddress> vSgIps) {
522 VlanId serviceVlan = getServiceVlan(vSgHost);
523 PortNumber dpPort = getDpPort(vSgHost);
524
525 if (serviceVlan == null || dpPort == null) {
526 log.warn("Failed to populate rules for vSG VM {}", vSgHost.id());
527 return;
528 }
529
530 // for traffics with s-tag, strip the tag and take through the vSG VM
531 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800532 .matchInPort(dpPort)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800533 .matchVlanId(serviceVlan)
534 .build();
535
536 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon6d247342016-02-12 12:48:47 -0800537 .setOutput(vSgHost.location().port())
538 .build();
539
540 FlowRule flowRule = DefaultFlowRule.builder()
541 .fromApp(appId)
542 .withSelector(selector)
543 .withTreatment(treatment)
544 .withPriority(DEFAULT_PRIORITY)
545 .forDevice(vSgHost.location().deviceId())
546 .forTable(TABLE_Q_IN_Q)
547 .makePermanent()
548 .build();
549
550 processFlowRule(true, flowRule);
551
552 // for traffics with customer vlan, tag with the service vlan based on input port with
553 // lower priority to avoid conflict with WAN tag
554 selector = DefaultTrafficSelector.builder()
555 .matchInPort(vSgHost.location().port())
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800556 .matchVlanId(serviceVlan)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800557 .build();
558
559 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon6d247342016-02-12 12:48:47 -0800560 .setOutput(dpPort)
561 .build();
562
563 flowRule = DefaultFlowRule.builder()
564 .fromApp(appId)
565 .withSelector(selector)
566 .withTreatment(treatment)
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800567 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800568 .forDevice(vSgHost.location().deviceId())
569 .forTable(TABLE_Q_IN_Q)
570 .makePermanent()
571 .build();
572
573 processFlowRule(true, flowRule);
574
575 // for traffic coming from WAN, tag 500 and take through the vSG VM
576 // based on destination ip
577 vSgIps.stream().forEach(ip -> {
578 TrafficSelector downstream = DefaultTrafficSelector.builder()
579 .matchEthType(Ethernet.TYPE_IPV4)
580 .matchIPDst(ip.toIpPrefix())
581 .build();
582
583 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
584 .pushVlan()
585 .setVlanId(VLAN_WAN)
586 .setEthDst(vSgHost.mac())
587 .setOutput(vSgHost.location().port())
588 .build();
589
590 FlowRule downstreamFlowRule = DefaultFlowRule.builder()
591 .fromApp(appId)
592 .withSelector(downstream)
593 .withTreatment(downstreamTreatment)
594 .withPriority(DEFAULT_PRIORITY)
595 .forDevice(vSgHost.location().deviceId())
596 .forTable(TABLE_DST_IP)
597 .makePermanent()
598 .build();
599
600 processFlowRule(true, downstreamFlowRule);
601 });
602
603 // remove downstream flow rules for the vSG not shown in vSgIps
604 for (FlowRule rule : flowRuleService.getFlowRulesById(appId)) {
605 if (!rule.deviceId().equals(vSgHost.location().deviceId())) {
606 continue;
607 }
608 PortNumber output = getOutputFromTreatment(rule);
609 if (output == null || !output.equals(vSgHost.location().port()) ||
610 !isVlanPushFromTreatment(rule)) {
611 continue;
612 }
613
614 IpPrefix dstIp = getDstIpFromSelector(rule);
615 if (dstIp != null && !vSgIps.contains(dstIp.address())) {
616 processFlowRule(false, rule);
617 }
618 }
619 }
620
621 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800622 * Populates default rules on the first table.
Hyunsun Moon133fd792016-02-09 01:55:48 -0800623 * It includes the rules for shuttling vxlan-encapped packets between ovs and
624 * linux stack,and external network connectivity.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800625 *
626 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -0800627 * @param dpPort data plane interface port number
628 * @param dpIp data plane ip address
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800629 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800630 private void processFirstTable(DeviceId deviceId, PortNumber dpPort, IpAddress dpIp) {
Hyunsun Moon4a915152016-01-14 16:56:26 -0800631 // take vxlan packet out onto the physical port
632 TrafficSelector selector = DefaultTrafficSelector.builder()
633 .matchInPort(PortNumber.LOCAL)
634 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800635
Hyunsun Moon4a915152016-01-14 16:56:26 -0800636 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800637 .setOutput(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800638 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800639
Hyunsun Moon4a915152016-01-14 16:56:26 -0800640 FlowRule flowRule = DefaultFlowRule.builder()
641 .fromApp(appId)
642 .withSelector(selector)
643 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800644 .withPriority(HIGH_PRIORITY)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800645 .forDevice(deviceId)
646 .forTable(TABLE_FIRST)
647 .makePermanent()
648 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800649
Hyunsun Moon4a915152016-01-14 16:56:26 -0800650 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800651
Hyunsun Moon4a915152016-01-14 16:56:26 -0800652 // take a vxlan encap'd packet through the Linux stack
653 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800654 .matchInPort(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800655 .matchEthType(Ethernet.TYPE_IPV4)
656 .matchIPProtocol(IPv4.PROTOCOL_UDP)
657 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
658 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800659
Hyunsun Moon4a915152016-01-14 16:56:26 -0800660 treatment = DefaultTrafficTreatment.builder()
661 .setOutput(PortNumber.LOCAL)
662 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800663
Hyunsun Moon4a915152016-01-14 16:56:26 -0800664 flowRule = DefaultFlowRule.builder()
665 .fromApp(appId)
666 .withSelector(selector)
667 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800668 .withPriority(HIGH_PRIORITY)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800669 .forDevice(deviceId)
670 .forTable(TABLE_FIRST)
671 .makePermanent()
672 .build();
673
674 processFlowRule(true, flowRule);
675
Hyunsun Moon133fd792016-02-09 01:55:48 -0800676 // take a packet to the data plane ip through Linux stack
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800677 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800678 .matchInPort(dpPort)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800679 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon133fd792016-02-09 01:55:48 -0800680 .matchIPDst(dpIp.toIpPrefix())
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800681 .build();
682
683 treatment = DefaultTrafficTreatment.builder()
684 .setOutput(PortNumber.LOCAL)
685 .build();
686
687 flowRule = DefaultFlowRule.builder()
688 .fromApp(appId)
689 .withSelector(selector)
690 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800691 .withPriority(HIGH_PRIORITY)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800692 .forDevice(deviceId)
693 .forTable(TABLE_FIRST)
694 .makePermanent()
695 .build();
696
697 processFlowRule(true, flowRule);
698
699 // take an arp packet from physical through Linux stack
700 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800701 .matchInPort(dpPort)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800702 .matchEthType(Ethernet.TYPE_ARP)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800703 .matchArpTpa(dpIp.getIp4Address())
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800704 .build();
705
706 treatment = DefaultTrafficTreatment.builder()
707 .setOutput(PortNumber.LOCAL)
708 .build();
709
710 flowRule = DefaultFlowRule.builder()
711 .fromApp(appId)
712 .withSelector(selector)
713 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800714 .withPriority(HIGH_PRIORITY)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800715 .forDevice(deviceId)
716 .forTable(TABLE_FIRST)
717 .makePermanent()
718 .build();
719
720 processFlowRule(true, flowRule);
721
Hyunsun Moon4a915152016-01-14 16:56:26 -0800722 // take all else to the next table
723 selector = DefaultTrafficSelector.builder()
724 .build();
725
726 treatment = DefaultTrafficTreatment.builder()
727 .transition(TABLE_IN_PORT)
728 .build();
729
730 flowRule = DefaultFlowRule.builder()
731 .fromApp(appId)
732 .withSelector(selector)
733 .withTreatment(treatment)
734 .withPriority(LOWEST_PRIORITY)
735 .forDevice(deviceId)
736 .forTable(TABLE_FIRST)
737 .makePermanent()
738 .build();
739
740 processFlowRule(true, flowRule);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800741
742 // take all vlan tagged packet to the Q_IN_Q table
743 selector = DefaultTrafficSelector.builder()
744 .matchVlanId(VlanId.ANY)
745 .build();
746
747 treatment = DefaultTrafficTreatment.builder()
748 .transition(TABLE_Q_IN_Q)
749 .build();
750
751 flowRule = DefaultFlowRule.builder()
752 .fromApp(appId)
753 .withSelector(selector)
754 .withTreatment(treatment)
755 .withPriority(VSG_PRIORITY)
756 .forDevice(deviceId)
757 .forTable(TABLE_FIRST)
758 .makePermanent()
759 .build();
760
761 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800762 }
763
764 /**
Hyunsun Moon133fd792016-02-09 01:55:48 -0800765 * Forward table miss packets in ACCESS_TYPE table to data plane port.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800766 *
767 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -0800768 * @param dpPort data plane interface port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800769 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800770 private void processAccessTypeTable(DeviceId deviceId, PortNumber dpPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800771 TrafficSelector selector = DefaultTrafficSelector.builder()
772 .build();
773
774 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800775 .setOutput(dpPort)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800776 .build();
777
778 FlowRule flowRule = DefaultFlowRule.builder()
779 .fromApp(appId)
780 .withSelector(selector)
781 .withTreatment(treatment)
782 .withPriority(LOWEST_PRIORITY)
783 .forDevice(deviceId)
784 .forTable(TABLE_ACCESS_TYPE)
785 .makePermanent()
786 .build();
787
788 processFlowRule(true, flowRule);
789 }
790
791 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800792 * Populates default rules for IN_PORT table.
793 * All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
Hyunsun Moon133fd792016-02-09 01:55:48 -0800794 * from data plane interface port to ACCESS_TYPE table.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800795 *
796 * @param deviceId device id to install the rules
Hyunsun Moon4a915152016-01-14 16:56:26 -0800797 * @param tunnelPort tunnel port number
Hyunsun Moon133fd792016-02-09 01:55:48 -0800798 * @param dpPort data plane interface port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800799 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800800 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dpPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800801 checkNotNull(tunnelPort);
802
803 TrafficSelector selector = DefaultTrafficSelector.builder()
804 .matchInPort(tunnelPort)
805 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800806
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800807 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
808 .transition(TABLE_TUNNEL_IN)
809 .build();
810
811 FlowRule flowRule = DefaultFlowRule.builder()
812 .fromApp(appId)
813 .withSelector(selector)
814 .withTreatment(treatment)
815 .withPriority(DEFAULT_PRIORITY)
816 .forDevice(deviceId)
817 .forTable(TABLE_IN_PORT)
818 .makePermanent()
819 .build();
820
821 processFlowRule(true, flowRule);
Hyunsun Moon4a915152016-01-14 16:56:26 -0800822
823 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800824 .matchInPort(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800825 .build();
826
827 treatment = DefaultTrafficTreatment.builder()
828 .transition(TABLE_DST_IP)
829 .build();
830
831 flowRule = DefaultFlowRule.builder()
832 .fromApp(appId)
833 .withSelector(selector)
834 .withTreatment(treatment)
835 .withPriority(DEFAULT_PRIORITY)
836 .forDevice(deviceId)
837 .forTable(TABLE_IN_PORT)
838 .makePermanent()
839 .build();
840
841 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800842 }
843
844 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800845 * Populates default rules for Q_IN_Q table.
846 *
847 * @param deviceId device id
848 * @param dpPort data plane interface port number
849 */
850 private void processQInQTable(DeviceId deviceId, PortNumber dpPort) {
851 // for traffic going out to WAN, strip vid 500 and take through data plane interface
852 TrafficSelector selector = DefaultTrafficSelector.builder()
853 .matchVlanId(VLAN_WAN)
854 .build();
855
856 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
857 .popVlan()
858 .setOutput(dpPort)
859 .build();
860
861 FlowRule flowRule = DefaultFlowRule.builder()
862 .fromApp(appId)
863 .withSelector(selector)
864 .withTreatment(treatment)
865 .withPriority(DEFAULT_PRIORITY)
866 .forDevice(deviceId)
867 .forTable(TABLE_Q_IN_Q)
868 .makePermanent()
869 .build();
870
871 processFlowRule(true, flowRule);
872
873 selector = DefaultTrafficSelector.builder()
874 .matchVlanId(VLAN_WAN)
875 .matchEthType(Ethernet.TYPE_ARP)
876 .build();
877
878 treatment = DefaultTrafficTreatment.builder()
879 .setOutput(PortNumber.CONTROLLER)
880 .build();
881
882 flowRule = DefaultFlowRule.builder()
883 .fromApp(appId)
884 .withSelector(selector)
885 .withTreatment(treatment)
886 .withPriority(HIGH_PRIORITY)
887 .forDevice(deviceId)
888 .forTable(TABLE_Q_IN_Q)
889 .makePermanent()
890 .build();
891
892 processFlowRule(true, flowRule);
893 }
894
895 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800896 * Populates rules for local in port in IN_PORT table.
897 * Flows from a given in port, whose source IP is service IP transition
898 * to DST_TYPE table. Other flows transition to IN_SERVICE table.
899 *
900 * @param deviceId device id to install the rules
901 * @param inPort in port
902 * @param srcIp source ip
903 */
904 private void populateLocalInPortRule(DeviceId deviceId, PortNumber inPort, IpAddress srcIp) {
905 TrafficSelector selector = DefaultTrafficSelector.builder()
906 .matchInPort(inPort)
907 .matchEthType(Ethernet.TYPE_IPV4)
908 .matchIPSrc(srcIp.toIpPrefix())
909 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800910
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800911 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
912 .transition(TABLE_ACCESS_TYPE)
913 .build();
914
915
916 FlowRule flowRule = DefaultFlowRule.builder()
917 .fromApp(appId)
918 .withSelector(selector)
919 .withTreatment(treatment)
920 .withPriority(DEFAULT_PRIORITY)
921 .forDevice(deviceId)
922 .forTable(TABLE_IN_PORT)
923 .makePermanent()
924 .build();
925
926 processFlowRule(true, flowRule);
927
928 selector = DefaultTrafficSelector.builder()
929 .matchInPort(inPort)
930 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800931
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800932 treatment = DefaultTrafficTreatment.builder()
933 .transition(TABLE_IN_SERVICE)
934 .build();
935
936 flowRule = DefaultFlowRule.builder()
937 .fromApp(appId)
938 .withSelector(selector)
939 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800940 .withPriority(LOW_PRIORITY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800941 .forDevice(deviceId)
942 .forTable(TABLE_IN_PORT)
943 .makePermanent()
944 .build();
945
946 processFlowRule(true, flowRule);
947 }
948
949 /**
950 * Populates direct VM access rules for ACCESS_TYPE table.
951 * These rules are installed to all devices.
952 *
953 * @param srcRange source ip range
954 * @param dstRange destination ip range
955 */
956 private void populateDirectAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange) {
957 TrafficSelector selector = DefaultTrafficSelector.builder()
958 .matchEthType(Ethernet.TYPE_IPV4)
959 .matchIPSrc(srcRange)
960 .matchIPDst(dstRange)
961 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800962
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800963 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
964 .transition(TABLE_DST_IP)
965 .build();
966
Hyunsun Moon98025542016-03-08 04:36:02 -0800967
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800968 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800969 FlowRule flowRuleDirect = DefaultFlowRule.builder()
970 .fromApp(appId)
971 .withSelector(selector)
972 .withTreatment(treatment)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800973 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800974 .forDevice(deviceId)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800975 .forTable(TABLE_ACCESS_TYPE)
976 .makePermanent()
977 .build();
978
979 processFlowRule(true, flowRuleDirect);
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800980 });
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800981 }
982
983 /**
984 * Populates drop rules that does not match any direct access rules but has
985 * destination to a different service network in ACCESS_TYPE table.
986 *
987 * @param dstRange destination ip range
988 */
989 private void populateServiceIsolationRule(Ip4Prefix dstRange) {
990 TrafficSelector selector = DefaultTrafficSelector.builder()
991 .matchEthType(Ethernet.TYPE_IPV4)
992 .matchIPDst(dstRange)
993 .build();
994
995 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
996 .drop()
997 .build();
998
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800999 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moon81ab23b2016-02-01 23:00:56 -08001000 FlowRule flowRuleDirect = DefaultFlowRule.builder()
1001 .fromApp(appId)
1002 .withSelector(selector)
1003 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001004 .withPriority(LOW_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001005 .forDevice(deviceId)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001006 .forTable(TABLE_ACCESS_TYPE)
1007 .makePermanent()
1008 .build();
1009
1010 processFlowRule(true, flowRuleDirect);
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001011 });
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001012 }
1013
1014 /**
1015 * Populates indirect service access rules for ACCESS_TYPE table.
1016 * These rules are installed to all devices.
1017 *
1018 * @param srcRange source range
1019 * @param serviceIp service ip
1020 * @param outGroups list of output group
1021 */
1022 private void populateIndirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
1023 Map<DeviceId, GroupId> outGroups) {
1024 TrafficSelector selector = DefaultTrafficSelector.builder()
1025 .matchEthType(Ethernet.TYPE_IPV4)
1026 .matchIPSrc(srcRange)
1027 .matchIPDst(serviceIp.toIpPrefix())
1028 .build();
1029
1030 for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
1031 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1032 .group(outGroup.getValue())
1033 .build();
1034
1035 FlowRule flowRule = DefaultFlowRule.builder()
1036 .fromApp(appId)
1037 .withSelector(selector)
1038 .withTreatment(treatment)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -08001039 .withPriority(HIGH_PRIORITY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001040 .forDevice(outGroup.getKey())
1041 .forTable(TABLE_ACCESS_TYPE)
1042 .makePermanent()
1043 .build();
1044
1045 processFlowRule(true, flowRule);
1046 }
1047 }
1048
1049 /**
1050 * Populates flow rules for IN_SERVICE table.
1051 *
1052 * @param inPorts list of inports related to the service for each device
1053 * @param outGroups set of output groups
1054 */
1055 private void populateInServiceRule(Map<DeviceId, Set<PortNumber>> inPorts, Map<DeviceId, GroupId> outGroups) {
1056 checkNotNull(inPorts);
1057 checkNotNull(outGroups);
1058
1059 for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
1060 Set<PortNumber> ports = entry.getValue();
1061 DeviceId deviceId = entry.getKey();
1062
1063 GroupId groupId = outGroups.get(deviceId);
1064 if (groupId == null) {
1065 continue;
1066 }
1067
1068 ports.stream().forEach(port -> {
1069 TrafficSelector selector = DefaultTrafficSelector.builder()
1070 .matchInPort(port)
1071 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001072
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001073 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1074 .group(groupId)
1075 .build();
1076
1077 FlowRule flowRule = DefaultFlowRule.builder()
1078 .fromApp(appId)
1079 .withSelector(selector)
1080 .withTreatment(treatment)
1081 .withPriority(DEFAULT_PRIORITY)
1082 .forDevice(deviceId)
1083 .forTable(TABLE_IN_SERVICE)
1084 .makePermanent()
1085 .build();
1086
1087 processFlowRule(true, flowRule);
1088 });
1089 }
1090 }
1091
1092 /**
1093 * Populates flow rules for DST_IP table.
1094 *
1095 * @param deviceId device id
1096 * @param inPort in port
1097 * @param dstMac mac address
1098 * @param dstIp destination ip
1099 * @param tunnelId tunnel id
1100 * @param tunnelIp tunnel remote ip
1101 */
1102 private void populateDstIpRule(DeviceId deviceId, PortNumber inPort, MacAddress dstMac,
1103 IpAddress dstIp, long tunnelId, IpAddress tunnelIp) {
1104 TrafficSelector selector = DefaultTrafficSelector.builder()
1105 .matchEthType(Ethernet.TYPE_IPV4)
1106 .matchIPDst(dstIp.toIpPrefix())
1107 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001108
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001109 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1110 .setEthDst(dstMac)
1111 .setOutput(inPort)
1112 .build();
1113
1114 FlowRule flowRule = DefaultFlowRule.builder()
1115 .fromApp(appId)
1116 .withSelector(selector)
1117 .withTreatment(treatment)
1118 .withPriority(DEFAULT_PRIORITY)
1119 .forDevice(deviceId)
1120 .forTable(TABLE_DST_IP)
1121 .makePermanent()
1122 .build();
1123
1124 processFlowRule(true, flowRule);
1125
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001126 for (DeviceId vSwitchId : getVirtualSwitches()) {
1127 if (vSwitchId.equals(deviceId)) {
Hyunsun Moon98025542016-03-08 04:36:02 -08001128 continue;
1129 }
1130
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001131 ExtensionTreatment tunnelDst = getTunnelDst(vSwitchId, tunnelIp.getIp4Address());
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001132 if (tunnelDst == null) {
1133 continue;
1134 }
1135
1136 treatment = DefaultTrafficTreatment.builder()
1137 .setEthDst(dstMac)
1138 .setTunnelId(tunnelId)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001139 .extension(tunnelDst, vSwitchId)
1140 .setOutput(getTunnelPort(vSwitchId))
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001141 .build();
1142
1143 flowRule = DefaultFlowRule.builder()
1144 .fromApp(appId)
1145 .withSelector(selector)
1146 .withTreatment(treatment)
1147 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001148 .forDevice(vSwitchId)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001149 .forTable(TABLE_DST_IP)
1150 .makePermanent()
1151 .build();
1152
1153 processFlowRule(true, flowRule);
1154 }
1155 }
1156
1157 /**
1158 * Populates flow rules for TUNNEL_ID table.
1159 *
1160 * @param deviceId device id
1161 * @param inPort in port
1162 * @param mac mac address
1163 * @param tunnelId tunnel id
1164 */
1165 private void populateTunnelInRule(DeviceId deviceId, PortNumber inPort, MacAddress mac, long tunnelId) {
1166 TrafficSelector selector = DefaultTrafficSelector.builder()
1167 .matchTunnelId(tunnelId)
1168 .matchEthDst(mac)
1169 .build();
1170
1171 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1172 .setOutput(inPort)
1173 .build();
1174
1175 FlowRule flowRule = DefaultFlowRule.builder()
1176 .fromApp(appId)
1177 .withSelector(selector)
1178 .withTreatment(treatment)
1179 .withPriority(DEFAULT_PRIORITY)
1180 .forDevice(deviceId)
1181 .forTable(TABLE_TUNNEL_IN)
1182 .makePermanent()
1183 .build();
1184
1185 processFlowRule(true, flowRule);
1186 }
1187
1188 /**
1189 * Installs or uninstall a given rule.
1190 *
1191 * @param install true to install, false to uninstall
1192 * @param rule rule
1193 */
1194 private void processFlowRule(boolean install, FlowRule rule) {
1195 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
1196 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
1197
1198 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
1199 @Override
1200 public void onError(FlowRuleOperations ops) {
1201 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
1202 }
1203 }));
1204 }
1205
1206 /**
1207 * Returns tunnel port of the device.
1208 *
1209 * @param deviceId device id
1210 * @return tunnel port number, or null if no tunnel port exists on a given device
1211 */
1212 private PortNumber getTunnelPort(DeviceId deviceId) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001213 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001214 .filter(p -> p.annotations().value(PORT_NAME).contains(tunnelType))
1215 .findFirst().orElse(null);
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001216
1217 return port == null ? null : port.number();
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001218 }
1219
1220 /**
Hyunsun Moon133fd792016-02-09 01:55:48 -08001221 * Returns data plane interface port name of a given device.
Hyunsun Moon4a915152016-01-14 16:56:26 -08001222 *
1223 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -08001224 * @param dpIntf data plane interface port name
1225 * @return data plane interface port number, or null if no such port exists
Hyunsun Moon4a915152016-01-14 16:56:26 -08001226 */
Hyunsun Moon133fd792016-02-09 01:55:48 -08001227 private PortNumber getDpPort(DeviceId deviceId, String dpIntf) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001228 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001229 .filter(p -> p.annotations().value(PORT_NAME).contains(dpIntf) &&
1230 p.isEnabled())
1231 .findFirst().orElse(null);
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001232
1233 return port == null ? null : port.number();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001234 }
1235
Hyunsun Moon6d247342016-02-12 12:48:47 -08001236 /** Returns data plane interface port number of a given host.
1237 *
1238 * @param host host
1239 * @return port number, or null
1240 */
1241 private PortNumber getDpPort(Host host) {
1242 String portName = host.annotations().value(DATA_PLANE_INTF);
1243 return portName == null ? null : getDpPort(host.location().deviceId(), portName);
1244 }
1245
1246 /**
1247 * Returns service vlan from a given host.
1248 *
1249 * @param host host
1250 * @return vlan id, or null
1251 */
1252 private VlanId getServiceVlan(Host host) {
1253 String serviceVlan = host.annotations().value(S_TAG);
1254 return serviceVlan == null ? null : VlanId.vlanId(Short.parseShort(serviceVlan));
1255 }
1256
Hyunsun Moon4a915152016-01-14 16:56:26 -08001257 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001258 * Returns the inport from a given flow rule if the rule contains the match of it.
1259 *
1260 * @param flowRule flow rule
1261 * @return port number, or null if the rule doesn't have inport match
1262 */
1263 private PortNumber getInPort(FlowRule flowRule) {
1264 Criterion criterion = flowRule.selector().getCriterion(IN_PORT);
1265 if (criterion != null && criterion instanceof PortCriterion) {
1266 PortCriterion port = (PortCriterion) criterion;
1267 return port.port();
1268 } else {
1269 return null;
1270 }
1271 }
1272
1273 /**
1274 * Returns the destination mac address from a given flow rule if the rule
1275 * contains the instruction of it.
1276 *
1277 * @param flowRule flow rule
1278 * @return mac address, or null if the rule doesn't have destination mac instruction
1279 */
1280 private MacAddress getDstMacFromTreatment(FlowRule flowRule) {
1281 Instruction instruction = flowRule.treatment().allInstructions().stream()
1282 .filter(inst -> inst instanceof ModEtherInstruction &&
1283 ((ModEtherInstruction) inst).subtype().equals(ETH_DST))
1284 .findFirst()
1285 .orElse(null);
1286
1287 if (instruction == null) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001288 return null;
1289 }
1290
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001291 return ((ModEtherInstruction) instruction).mac();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001292 }
1293
1294 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001295 * Returns the destination mac address from a given flow rule if the rule
1296 * contains the match of it.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001297 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001298 * @param flowRule flow rule
1299 * @return mac address, or null if the rule doesn't have destination mac match
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001300 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001301 private MacAddress getDstMacFromSelector(FlowRule flowRule) {
1302 Criterion criterion = flowRule.selector().getCriterion(Criterion.Type.ETH_DST);
1303 if (criterion != null && criterion instanceof EthCriterion) {
1304 EthCriterion eth = (EthCriterion) criterion;
1305 return eth.mac();
1306 } else {
1307 return null;
1308 }
1309 }
1310
1311 /**
1312 * Returns the destination IP from a given flow rule if the rule contains
1313 * the match of it.
1314 *
1315 * @param flowRule flow rule
1316 * @return ip prefix, or null if the rule doesn't have ip match
1317 */
1318 private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
1319 Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
1320 if (criterion != null && criterion instanceof IPCriterion) {
1321 IPCriterion ip = (IPCriterion) criterion;
1322 return ip.ip();
1323 } else {
1324 return null;
1325 }
1326 }
1327
1328 /**
1329 * Returns the source IP from a given flow rule if the rule contains
1330 * the match of it.
1331 *
1332 * @param flowRule flow rule
1333 * @return ip prefix, or null if the rule doesn't have ip match
1334 */
1335 private IpPrefix getSrcIpFromSelector(FlowRule flowRule) {
1336 Criterion criterion = flowRule.selector().getCriterion(IPV4_SRC);
1337 if (criterion != null && criterion instanceof IPCriterion) {
1338 IPCriterion ip = (IPCriterion) criterion;
1339 return ip.ip();
1340 } else {
1341 return null;
1342 }
1343 }
1344
1345 /**
1346 * Returns the group ID from a given flow rule if the rule contains the
1347 * treatment of it.
1348 *
1349 * @param flowRule flow rule
1350 * @return group id, or null if the rule doesn't have group instruction
1351 */
1352 private GroupId getGroupIdFromTreatment(FlowRule flowRule) {
1353 Instruction instruction = flowRule.treatment().allInstructions().stream()
1354 .filter(inst -> inst instanceof Instructions.GroupInstruction)
1355 .findFirst()
1356 .orElse(null);
1357
1358 if (instruction == null) {
1359 return null;
1360 }
1361
1362 return ((Instructions.GroupInstruction) instruction).groupId();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001363 }
1364
1365 /**
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001366 * Returns the output port number from a given flow rule.
1367 *
1368 * @param flowRule flow rule
1369 * @return port number, or null if the rule does not have output instruction
1370 */
1371 private PortNumber getOutputFromTreatment(FlowRule flowRule) {
1372 Instruction instruction = flowRule.treatment().allInstructions().stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001373 .filter(inst -> inst instanceof Instructions.OutputInstruction)
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001374 .findFirst()
1375 .orElse(null);
1376
1377 if (instruction == null) {
1378 return null;
1379 }
1380
1381 return ((Instructions.OutputInstruction) instruction).port();
1382 }
1383
1384 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -08001385 * Returns if a given flow rule has vlan push instruction or not.
1386 *
1387 * @param flowRule flow rule
1388 * @return true if it includes vlan push, or false
1389 */
1390 private boolean isVlanPushFromTreatment(FlowRule flowRule) {
1391 Instruction instruction = flowRule.treatment().allInstructions().stream()
1392 .filter(inst -> inst instanceof L2ModificationInstruction)
1393 .filter(inst -> ((L2ModificationInstruction) inst).subtype().equals(VLAN_PUSH))
1394 .findAny()
1395 .orElse(null);
1396
1397 return instruction != null;
1398 }
1399
1400 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -08001401 * Creates a new group for a given service.
1402 *
1403 * @param deviceId device id to create a group
1404 * @param service cord service
1405 * @return group id, or null if it fails to create
1406 */
1407 private GroupId createServiceGroup(DeviceId deviceId, CordService service) {
1408 checkNotNull(service);
1409
1410 GroupKey groupKey = getGroupKey(service.id());
1411 Group group = groupService.getGroup(deviceId, groupKey);
1412 GroupId groupId = getGroupId(service.id(), deviceId);
1413
1414 if (group != null) {
1415 log.debug("Group {} is already exist in {}", service.id(), deviceId);
1416 return groupId;
1417 }
1418
1419 GroupBuckets buckets = getServiceGroupBuckets(deviceId, service.segmentationId(), service.hosts());
1420 GroupDescription groupDescription = new DefaultGroupDescription(
1421 deviceId,
1422 GroupDescription.Type.SELECT,
1423 buckets,
1424 groupKey,
1425 groupId.id(),
1426 appId);
1427
1428 groupService.addGroup(groupDescription);
1429
1430 return groupId;
1431 }
1432
1433 /**
1434 * Returns group buckets for a given device.
1435 *
1436 * @param deviceId device id
1437 * @param tunnelId tunnel id
1438 * @param hosts list of host
1439 * @return group buckets
1440 */
1441 private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId, Map<Host, IpAddress> hosts) {
1442 List<GroupBucket> buckets = Lists.newArrayList();
1443
1444 for (Map.Entry<Host, IpAddress> entry : hosts.entrySet()) {
1445 Host host = entry.getKey();
1446 Ip4Address remoteIp = entry.getValue().getIp4Address();
1447 DeviceId hostDevice = host.location().deviceId();
1448
1449 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
1450 .builder()
1451 .setEthDst(host.mac());
1452
1453 if (deviceId.equals(hostDevice)) {
1454 tBuilder.setOutput(host.location().port());
1455 } else {
1456 ExtensionTreatment tunnelDst = getTunnelDst(deviceId, remoteIp);
1457 if (tunnelDst == null) {
1458 continue;
1459 }
1460
1461 tBuilder.extension(tunnelDst, deviceId)
1462 .setTunnelId(tunnelId)
1463 .setOutput(getTunnelPort(hostDevice));
1464 }
1465
1466 buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
1467 }
1468
1469 return new GroupBuckets(buckets);
1470 }
1471
1472 /**
1473 * Returns globally unique group ID.
1474 *
1475 * @param serviceId service id
1476 * @param deviceId device id
1477 * @return group id
1478 */
1479 private GroupId getGroupId(CordServiceId serviceId, DeviceId deviceId) {
1480 return new DefaultGroupId(Objects.hash(serviceId, deviceId));
1481 }
1482
1483 /**
1484 * Returns group key of a service.
1485 *
1486 * @param serviceId service id
1487 * @return group key
1488 */
1489 private GroupKey getGroupKey(CordServiceId serviceId) {
1490 return new DefaultGroupKey(serviceId.id().getBytes());
1491 }
1492
1493 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001494 * Returns extension instruction to set tunnel destination.
1495 *
1496 * @param deviceId device id
1497 * @param remoteIp tunnel destination address
1498 * @return extension treatment or null if it fails to get instruction
1499 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001500 private ExtensionTreatment getTunnelDst(DeviceId deviceId, Ip4Address remoteIp) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001501 try {
1502 Driver driver = driverService.getDriver(deviceId);
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001503 DefaultDriverData driverData = new DefaultDriverData(driver, deviceId);
1504 DriverHandler handler = new DefaultDriverHandler(driverData);
1505 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001506
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001507 ExtensionTreatment treatment =
1508 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001509 treatment.setPropertyValue("tunnelDst", remoteIp);
1510
1511 return treatment;
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001512 } catch (ItemNotFoundException | UnsupportedOperationException |
1513 ExtensionPropertyException e) {
1514 log.error("Failed to get extension instruction {}", deviceId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001515 return null;
1516 }
1517 }
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001518
1519 /**
1520 * Returns integration bridges configured in the system.
1521 *
1522 * @return set of device ids
1523 */
1524 private Set<DeviceId> getVirtualSwitches() {
1525 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
1526 if (config == null) {
1527 log.debug("No configuration found for {}", appId.name());
1528 return Sets.newHashSet();
1529 }
1530
1531 return config.cordVtnNodes().stream()
1532 .map(CordVtnNode::intBrId).collect(Collectors.toSet());
1533 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001534}
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001535