blob: 5914b71dbccfd9506cf9110a7e4721fc4b9932a1 [file] [log] [blame]
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08003 *
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 */
Hyunsun Moon7f4ed9d2016-04-14 16:13:42 -070016package org.onosproject.cordvtn.impl;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080017
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;
Hyunsun Moon7f4ed9d2016-04-14 16:13:42 -070031import org.onosproject.cordvtn.api.CordService;
32import org.onosproject.cordvtn.api.CordServiceId;
33import org.onosproject.cordvtn.api.CordVtnConfig;
34import org.onosproject.cordvtn.api.CordVtnNode;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080035import org.onosproject.core.ApplicationId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080036import org.onosproject.core.DefaultGroupId;
37import org.onosproject.core.GroupId;
Jian Li7532eb12016-04-15 13:22:05 -070038import org.onosproject.net.Device;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080039import org.onosproject.net.DeviceId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080040import org.onosproject.net.Host;
Hyunsun Moon5a4346f2016-01-15 11:41:14 -080041import org.onosproject.net.Port;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080042import org.onosproject.net.PortNumber;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080043import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
Hyunsun Moonfae776d2016-03-08 18:07:52 -080044import org.onosproject.net.config.NetworkConfigRegistry;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080045import org.onosproject.net.device.DeviceService;
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;
Hyunsun Moon576d6872016-04-14 19:04:23 -070074import org.openstack4j.model.network.Network;
75import org.openstack4j.model.network.Subnet;
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 Moonc71231d2015-12-16 20:53:23 -0800126 private final GroupService groupService;
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800127 private final NetworkConfigRegistry configRegistry;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800128 private final String tunnelType;
129
130 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800131 * Creates a new rule populator.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800132 *
133 * @param appId application id
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800134 * @param flowRuleService flow rule service
135 * @param deviceService device service
Jian Lidfba7392016-01-22 16:46:58 -0800136 * @param groupService group service
Ray Milkeyd4334db2016-04-05 17:39:44 -0700137 * @param configRegistry config registry
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800138 * @param tunnelType tunnel type
139 */
140 public CordVtnRuleInstaller(ApplicationId appId,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800141 FlowRuleService flowRuleService,
142 DeviceService deviceService,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800143 GroupService groupService,
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800144 NetworkConfigRegistry configRegistry,
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800145 String tunnelType) {
146 this.appId = appId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800147 this.flowRuleService = flowRuleService;
148 this.deviceService = deviceService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800149 this.groupService = groupService;
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800150 this.configRegistry = configRegistry;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800151 this.tunnelType = checkNotNull(tunnelType);
152 }
153
154 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800155 * Installs table miss rule to a give device.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800156 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800157 * @param deviceId device id to install the rules
Hyunsun Moon133fd792016-02-09 01:55:48 -0800158 * @param dpIntf data plane interface name
159 * @param dpIp data plane ip address
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800160 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800161 public void init(DeviceId deviceId, String dpIntf, IpAddress dpIp) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800162 // default is drop packets which can be accomplished without
163 // a table miss entry for all table.
Hyunsun Moon4a915152016-01-14 16:56:26 -0800164 PortNumber tunnelPort = getTunnelPort(deviceId);
Hyunsun Moon133fd792016-02-09 01:55:48 -0800165 PortNumber dpPort = getDpPort(deviceId, dpIntf);
Hyunsun Moon4a915152016-01-14 16:56:26 -0800166
Hyunsun Moon133fd792016-02-09 01:55:48 -0800167 processFirstTable(deviceId, dpPort, dpIp);
168 processInPortTable(deviceId, tunnelPort, dpPort);
169 processAccessTypeTable(deviceId, dpPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800170 processQInQTable(deviceId, dpPort);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800171 }
172
173 /**
Hyunsun Moon2062e7e2016-03-08 15:37:57 -0800174 * Flush flows installed by this application.
175 */
176 public void flushRules() {
177 flowRuleService.getFlowRulesById(appId).forEach(flowRule -> processFlowRule(false, flowRule));
178 }
179
180 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800181 * Populates basic rules that connect a VM to the other VMs in the system.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800182 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800183 * @param host host
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800184 * @param tunnelIp tunnel ip
Hyunsun Moon576d6872016-04-14 19:04:23 -0700185 * @param osNet openstack network
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800186 */
Hyunsun Moon576d6872016-04-14 19:04:23 -0700187 public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, Network osNet) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800188 checkNotNull(host);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700189 checkNotNull(osNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800190
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800191 DeviceId deviceId = host.location().deviceId();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800192 PortNumber inPort = host.location().port();
193 MacAddress dstMac = host.mac();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800194 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
Hyunsun Moon576d6872016-04-14 19:04:23 -0700195 long tunnelId = Long.parseLong(osNet.getProviderSegID());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800196
Hyunsun Moon576d6872016-04-14 19:04:23 -0700197 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800198 .findFirst()
199 .orElse(null);
200
Hyunsun Moon576d6872016-04-14 19:04:23 -0700201 if (osSubnet == null) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800202 log.error("Failed to get subnet for {}", host.id());
203 return;
204 }
Hyunsun Moon576d6872016-04-14 19:04:23 -0700205 Ip4Prefix cidr = Ip4Prefix.valueOf(osSubnet.getCidr());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800206
207 populateLocalInPortRule(deviceId, inPort, hostIp);
Hyunsun Moon576d6872016-04-14 19:04:23 -0700208 populateDirectAccessRule(cidr, cidr);
209 populateServiceIsolationRule(cidr);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800210 populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
211 populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800212 }
213
214 /**
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800215 * Removes all rules related to a given service VM host.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800216 *
217 * @param host host to be removed
218 */
219 public void removeBasicConnectionRules(Host host) {
220 checkNotNull(host);
221
222 DeviceId deviceId = host.location().deviceId();
223 MacAddress mac = host.mac();
224 PortNumber port = host.location().port();
225 IpAddress ip = host.ipAddresses().stream().findFirst().orElse(null);
226
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800227 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
228 if (flowRule.deviceId().equals(deviceId)) {
229 PortNumber inPort = getInPort(flowRule);
230 if (inPort != null && inPort.equals(port)) {
231 processFlowRule(false, flowRule);
232 continue;
233 }
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800234
235 PortNumber output = getOutputFromTreatment(flowRule);
236 if (output != null && output.equals(host.location().port())) {
237 processFlowRule(false, flowRule);
238 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800239 }
240
241 MacAddress dstMac = getDstMacFromTreatment(flowRule);
242 if (dstMac != null && dstMac.equals(mac)) {
243 processFlowRule(false, flowRule);
244 continue;
245 }
246
247 dstMac = getDstMacFromSelector(flowRule);
248 if (dstMac != null && dstMac.equals(mac)) {
249 processFlowRule(false, flowRule);
250 continue;
251 }
252
253 IpPrefix dstIp = getDstIpFromSelector(flowRule);
254 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
255 processFlowRule(false, flowRule);
256 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800257 }
258
259 // TODO uninstall same network access rule in access table if no vm exists in the network
260 }
261
262 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800263 * Populates service dependency rules.
264 *
265 * @param tService tenant cord service
266 * @param pService provider cord service
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800267 * @param isBidirectional true to enable bidirectional connection between two services
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800268 */
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800269 public void populateServiceDependencyRules(CordService tService, CordService pService,
270 boolean isBidirectional) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800271 checkNotNull(tService);
272 checkNotNull(pService);
273
274 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
275 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
276 Ip4Address serviceIp = pService.serviceIp().getIp4Address();
277
278 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
279 Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
280
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800281 getVirtualSwitches().stream().forEach(deviceId -> {
282 GroupId groupId = createServiceGroup(deviceId, pService);
283 outGroups.put(deviceId, groupId);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800284
285 Set<PortNumber> vms = tService.hosts().keySet()
286 .stream()
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800287 .filter(host -> host.location().deviceId().equals(deviceId))
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800288 .map(host -> host.location().port())
289 .collect(Collectors.toSet());
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800290 inPorts.put(deviceId, vms);
291 });
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800292
293 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
294 populateDirectAccessRule(srcRange, dstRange);
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800295 if (isBidirectional) {
296 populateDirectAccessRule(dstRange, srcRange);
297 }
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800298 populateInServiceRule(inPorts, outGroups);
299 }
300
301 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800302 * Removes service dependency rules.
303 *
304 * @param tService tenant cord service
305 * @param pService provider cord service
306 */
307 public void removeServiceDependencyRules(CordService tService, CordService pService) {
308 checkNotNull(tService);
309 checkNotNull(pService);
310
311 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
312 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
313 IpPrefix serviceIp = pService.serviceIp().toIpPrefix();
314
315 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
316 GroupKey groupKey = new DefaultGroupKey(pService.id().id().getBytes());
317
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800318 getVirtualSwitches().stream().forEach(deviceId -> {
319 Group group = groupService.getGroup(deviceId, groupKey);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800320 if (group != null) {
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800321 outGroups.put(deviceId, group.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800322 }
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800323 });
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800324
325 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
326 IpPrefix dstIp = getDstIpFromSelector(flowRule);
327 IpPrefix srcIp = getSrcIpFromSelector(flowRule);
328
329 if (dstIp != null && dstIp.equals(serviceIp)) {
330 processFlowRule(false, flowRule);
331 continue;
332 }
333
334 if (dstIp != null && srcIp != null) {
335 if (dstIp.equals(dstRange) && srcIp.equals(srcRange)) {
336 processFlowRule(false, flowRule);
337 continue;
338 }
339
340 if (dstIp.equals(srcRange) && srcIp.equals(dstRange)) {
341 processFlowRule(false, flowRule);
342 continue;
343 }
344 }
345
346 GroupId groupId = getGroupIdFromTreatment(flowRule);
347 if (groupId != null && groupId.equals(outGroups.get(flowRule.deviceId()))) {
348 processFlowRule(false, flowRule);
349 }
350 }
351
352 // TODO remove the group if it is not in use
353 }
354
355 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800356 * Updates group buckets for a given service to all devices.
357 *
358 * @param service cord service
359 */
360 public void updateServiceGroup(CordService service) {
361 checkNotNull(service);
362
363 GroupKey groupKey = getGroupKey(service.id());
364
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800365 for (DeviceId deviceId : getVirtualSwitches()) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800366 Group group = groupService.getGroup(deviceId, groupKey);
367 if (group == null) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800368 log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800369 continue;
370 }
371
372 List<GroupBucket> oldBuckets = group.buckets().buckets();
373 List<GroupBucket> newBuckets = getServiceGroupBuckets(
374 deviceId, service.segmentationId(), service.hosts()).buckets();
375
376 if (oldBuckets.equals(newBuckets)) {
377 continue;
378 }
379
380 List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
381 bucketsToRemove.removeAll(newBuckets);
382 if (!bucketsToRemove.isEmpty()) {
383 groupService.removeBucketsFromGroup(
384 deviceId,
385 groupKey,
386 new GroupBuckets(bucketsToRemove),
387 groupKey, appId);
388 }
389
390 List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
391 bucketsToAdd.removeAll(oldBuckets);
392 if (!bucketsToAdd.isEmpty()) {
393 groupService.addBucketsToGroup(
394 deviceId,
395 groupKey,
396 new GroupBuckets(bucketsToAdd),
397 groupKey, appId);
398 }
399 }
400 }
401
402 /**
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800403 * Populates flow rules for management network access.
404 *
405 * @param host host which has management network interface
406 * @param mService management network service
407 */
408 public void populateManagementNetworkRules(Host host, CordService mService) {
409 checkNotNull(mService);
410
411 DeviceId deviceId = host.location().deviceId();
412 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
413
414 TrafficSelector selector = DefaultTrafficSelector.builder()
415 .matchEthType(Ethernet.TYPE_ARP)
416 .matchArpTpa(mService.serviceIp().getIp4Address())
417 .build();
418
419 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
420 .setOutput(PortNumber.LOCAL)
421 .build();
422
423 FlowRule flowRule = DefaultFlowRule.builder()
424 .fromApp(appId)
425 .withSelector(selector)
426 .withTreatment(treatment)
427 .withPriority(MANAGEMENT_PRIORITY)
428 .forDevice(deviceId)
429 .forTable(TABLE_FIRST)
430 .makePermanent()
431 .build();
432
433 processFlowRule(true, flowRule);
434
435 selector = DefaultTrafficSelector.builder()
436 .matchInPort(PortNumber.LOCAL)
437 .matchEthType(Ethernet.TYPE_ARP)
438 .matchArpTpa(hostIp.getIp4Address())
439 .build();
440
441 treatment = DefaultTrafficTreatment.builder()
442 .setOutput(host.location().port())
443 .build();
444
445 flowRule = DefaultFlowRule.builder()
446 .fromApp(appId)
447 .withSelector(selector)
448 .withTreatment(treatment)
449 .withPriority(MANAGEMENT_PRIORITY)
450 .forDevice(deviceId)
451 .forTable(TABLE_FIRST)
452 .makePermanent()
453 .build();
454
455 processFlowRule(true, flowRule);
456
457 selector = DefaultTrafficSelector.builder()
458 .matchInPort(PortNumber.LOCAL)
459 .matchEthType(Ethernet.TYPE_IPV4)
460 .matchIPDst(mService.serviceIpRange())
461 .build();
462
463 treatment = DefaultTrafficTreatment.builder()
464 .transition(TABLE_DST_IP)
465 .build();
466
467 flowRule = DefaultFlowRule.builder()
468 .fromApp(appId)
469 .withSelector(selector)
470 .withTreatment(treatment)
471 .withPriority(MANAGEMENT_PRIORITY)
472 .forDevice(deviceId)
473 .forTable(TABLE_FIRST)
474 .makePermanent()
475 .build();
476
477 processFlowRule(true, flowRule);
478
479 selector = DefaultTrafficSelector.builder()
480 .matchEthType(Ethernet.TYPE_IPV4)
481 .matchIPDst(mService.serviceIp().toIpPrefix())
482 .build();
483
484 treatment = DefaultTrafficTreatment.builder()
485 .setOutput(PortNumber.LOCAL)
486 .build();
487
488 flowRule = DefaultFlowRule.builder()
489 .fromApp(appId)
490 .withSelector(selector)
491 .withTreatment(treatment)
492 .withPriority(MANAGEMENT_PRIORITY)
493 .forDevice(deviceId)
494 .forTable(TABLE_ACCESS_TYPE)
495 .makePermanent()
496 .build();
497
498 processFlowRule(true, flowRule);
499 }
500
501 /**
502 * Removes management network access rules.
503 *
504 * @param host host to be removed
505 * @param mService service for management network
506 */
507 public void removeManagementNetworkRules(Host host, CordService mService) {
508 checkNotNull(mService);
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800509 // TODO remove management network specific rules
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800510 }
511
512 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800513 * Populates rules for vSG VM.
514 *
515 * @param vSgHost vSG host
516 * @param vSgIps set of ip addresses of vSGs running inside the vSG VM
517 */
518 public void populateSubscriberGatewayRules(Host vSgHost, Set<IpAddress> vSgIps) {
519 VlanId serviceVlan = getServiceVlan(vSgHost);
520 PortNumber dpPort = getDpPort(vSgHost);
521
522 if (serviceVlan == null || dpPort == null) {
523 log.warn("Failed to populate rules for vSG VM {}", vSgHost.id());
524 return;
525 }
526
527 // for traffics with s-tag, strip the tag and take through the vSG VM
528 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800529 .matchInPort(dpPort)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800530 .matchVlanId(serviceVlan)
531 .build();
532
533 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon6d247342016-02-12 12:48:47 -0800534 .setOutput(vSgHost.location().port())
535 .build();
536
537 FlowRule flowRule = DefaultFlowRule.builder()
538 .fromApp(appId)
539 .withSelector(selector)
540 .withTreatment(treatment)
541 .withPriority(DEFAULT_PRIORITY)
542 .forDevice(vSgHost.location().deviceId())
543 .forTable(TABLE_Q_IN_Q)
544 .makePermanent()
545 .build();
546
547 processFlowRule(true, flowRule);
548
549 // for traffics with customer vlan, tag with the service vlan based on input port with
550 // lower priority to avoid conflict with WAN tag
551 selector = DefaultTrafficSelector.builder()
552 .matchInPort(vSgHost.location().port())
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800553 .matchVlanId(serviceVlan)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800554 .build();
555
556 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon6d247342016-02-12 12:48:47 -0800557 .setOutput(dpPort)
558 .build();
559
560 flowRule = DefaultFlowRule.builder()
561 .fromApp(appId)
562 .withSelector(selector)
563 .withTreatment(treatment)
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800564 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800565 .forDevice(vSgHost.location().deviceId())
566 .forTable(TABLE_Q_IN_Q)
567 .makePermanent()
568 .build();
569
570 processFlowRule(true, flowRule);
571
572 // for traffic coming from WAN, tag 500 and take through the vSG VM
573 // based on destination ip
574 vSgIps.stream().forEach(ip -> {
575 TrafficSelector downstream = DefaultTrafficSelector.builder()
576 .matchEthType(Ethernet.TYPE_IPV4)
577 .matchIPDst(ip.toIpPrefix())
578 .build();
579
580 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
581 .pushVlan()
582 .setVlanId(VLAN_WAN)
583 .setEthDst(vSgHost.mac())
584 .setOutput(vSgHost.location().port())
585 .build();
586
587 FlowRule downstreamFlowRule = DefaultFlowRule.builder()
588 .fromApp(appId)
589 .withSelector(downstream)
590 .withTreatment(downstreamTreatment)
591 .withPriority(DEFAULT_PRIORITY)
592 .forDevice(vSgHost.location().deviceId())
593 .forTable(TABLE_DST_IP)
594 .makePermanent()
595 .build();
596
597 processFlowRule(true, downstreamFlowRule);
598 });
599
600 // remove downstream flow rules for the vSG not shown in vSgIps
601 for (FlowRule rule : flowRuleService.getFlowRulesById(appId)) {
602 if (!rule.deviceId().equals(vSgHost.location().deviceId())) {
603 continue;
604 }
605 PortNumber output = getOutputFromTreatment(rule);
606 if (output == null || !output.equals(vSgHost.location().port()) ||
607 !isVlanPushFromTreatment(rule)) {
608 continue;
609 }
610
611 IpPrefix dstIp = getDstIpFromSelector(rule);
612 if (dstIp != null && !vSgIps.contains(dstIp.address())) {
613 processFlowRule(false, rule);
614 }
615 }
616 }
617
618 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800619 * Populates default rules on the first table.
Hyunsun Moon133fd792016-02-09 01:55:48 -0800620 * It includes the rules for shuttling vxlan-encapped packets between ovs and
621 * linux stack,and external network connectivity.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800622 *
623 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -0800624 * @param dpPort data plane interface port number
625 * @param dpIp data plane ip address
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800626 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800627 private void processFirstTable(DeviceId deviceId, PortNumber dpPort, IpAddress dpIp) {
Hyunsun Moon4a915152016-01-14 16:56:26 -0800628 // take vxlan packet out onto the physical port
629 TrafficSelector selector = DefaultTrafficSelector.builder()
630 .matchInPort(PortNumber.LOCAL)
631 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800632
Hyunsun Moon4a915152016-01-14 16:56:26 -0800633 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800634 .setOutput(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800635 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800636
Hyunsun Moon4a915152016-01-14 16:56:26 -0800637 FlowRule flowRule = DefaultFlowRule.builder()
638 .fromApp(appId)
639 .withSelector(selector)
640 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800641 .withPriority(HIGH_PRIORITY)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800642 .forDevice(deviceId)
643 .forTable(TABLE_FIRST)
644 .makePermanent()
645 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800646
Hyunsun Moon4a915152016-01-14 16:56:26 -0800647 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800648
Hyunsun Moon4a915152016-01-14 16:56:26 -0800649 // take a vxlan encap'd packet through the Linux stack
650 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800651 .matchInPort(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800652 .matchEthType(Ethernet.TYPE_IPV4)
653 .matchIPProtocol(IPv4.PROTOCOL_UDP)
654 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
655 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800656
Hyunsun Moon4a915152016-01-14 16:56:26 -0800657 treatment = DefaultTrafficTreatment.builder()
658 .setOutput(PortNumber.LOCAL)
659 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800660
Hyunsun Moon4a915152016-01-14 16:56:26 -0800661 flowRule = DefaultFlowRule.builder()
662 .fromApp(appId)
663 .withSelector(selector)
664 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800665 .withPriority(HIGH_PRIORITY)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800666 .forDevice(deviceId)
667 .forTable(TABLE_FIRST)
668 .makePermanent()
669 .build();
670
671 processFlowRule(true, flowRule);
672
Hyunsun Moon133fd792016-02-09 01:55:48 -0800673 // take a packet to the data plane ip through Linux stack
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800674 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800675 .matchInPort(dpPort)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800676 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon133fd792016-02-09 01:55:48 -0800677 .matchIPDst(dpIp.toIpPrefix())
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800678 .build();
679
680 treatment = DefaultTrafficTreatment.builder()
681 .setOutput(PortNumber.LOCAL)
682 .build();
683
684 flowRule = DefaultFlowRule.builder()
685 .fromApp(appId)
686 .withSelector(selector)
687 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800688 .withPriority(HIGH_PRIORITY)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800689 .forDevice(deviceId)
690 .forTable(TABLE_FIRST)
691 .makePermanent()
692 .build();
693
694 processFlowRule(true, flowRule);
695
696 // take an arp packet from physical through Linux stack
697 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800698 .matchInPort(dpPort)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800699 .matchEthType(Ethernet.TYPE_ARP)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800700 .matchArpTpa(dpIp.getIp4Address())
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800701 .build();
702
703 treatment = DefaultTrafficTreatment.builder()
704 .setOutput(PortNumber.LOCAL)
705 .build();
706
707 flowRule = DefaultFlowRule.builder()
708 .fromApp(appId)
709 .withSelector(selector)
710 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800711 .withPriority(HIGH_PRIORITY)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800712 .forDevice(deviceId)
713 .forTable(TABLE_FIRST)
714 .makePermanent()
715 .build();
716
717 processFlowRule(true, flowRule);
718
Hyunsun Moon4a915152016-01-14 16:56:26 -0800719 // take all else to the next table
720 selector = DefaultTrafficSelector.builder()
721 .build();
722
723 treatment = DefaultTrafficTreatment.builder()
724 .transition(TABLE_IN_PORT)
725 .build();
726
727 flowRule = DefaultFlowRule.builder()
728 .fromApp(appId)
729 .withSelector(selector)
730 .withTreatment(treatment)
731 .withPriority(LOWEST_PRIORITY)
732 .forDevice(deviceId)
733 .forTable(TABLE_FIRST)
734 .makePermanent()
735 .build();
736
737 processFlowRule(true, flowRule);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800738
739 // take all vlan tagged packet to the Q_IN_Q table
740 selector = DefaultTrafficSelector.builder()
741 .matchVlanId(VlanId.ANY)
742 .build();
743
744 treatment = DefaultTrafficTreatment.builder()
745 .transition(TABLE_Q_IN_Q)
746 .build();
747
748 flowRule = DefaultFlowRule.builder()
749 .fromApp(appId)
750 .withSelector(selector)
751 .withTreatment(treatment)
752 .withPriority(VSG_PRIORITY)
753 .forDevice(deviceId)
754 .forTable(TABLE_FIRST)
755 .makePermanent()
756 .build();
757
758 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800759 }
760
761 /**
Hyunsun Moon133fd792016-02-09 01:55:48 -0800762 * Forward table miss packets in ACCESS_TYPE table to data plane port.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800763 *
764 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -0800765 * @param dpPort data plane interface port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800766 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800767 private void processAccessTypeTable(DeviceId deviceId, PortNumber dpPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800768 TrafficSelector selector = DefaultTrafficSelector.builder()
769 .build();
770
771 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800772 .setOutput(dpPort)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800773 .build();
774
775 FlowRule flowRule = DefaultFlowRule.builder()
776 .fromApp(appId)
777 .withSelector(selector)
778 .withTreatment(treatment)
779 .withPriority(LOWEST_PRIORITY)
780 .forDevice(deviceId)
781 .forTable(TABLE_ACCESS_TYPE)
782 .makePermanent()
783 .build();
784
785 processFlowRule(true, flowRule);
786 }
787
788 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800789 * Populates default rules for IN_PORT table.
790 * All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
Hyunsun Moon133fd792016-02-09 01:55:48 -0800791 * from data plane interface port to ACCESS_TYPE table.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800792 *
793 * @param deviceId device id to install the rules
Hyunsun Moon4a915152016-01-14 16:56:26 -0800794 * @param tunnelPort tunnel port number
Hyunsun Moon133fd792016-02-09 01:55:48 -0800795 * @param dpPort data plane interface port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800796 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800797 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dpPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800798 checkNotNull(tunnelPort);
799
800 TrafficSelector selector = DefaultTrafficSelector.builder()
801 .matchInPort(tunnelPort)
802 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800803
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800804 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
805 .transition(TABLE_TUNNEL_IN)
806 .build();
807
808 FlowRule flowRule = DefaultFlowRule.builder()
809 .fromApp(appId)
810 .withSelector(selector)
811 .withTreatment(treatment)
812 .withPriority(DEFAULT_PRIORITY)
813 .forDevice(deviceId)
814 .forTable(TABLE_IN_PORT)
815 .makePermanent()
816 .build();
817
818 processFlowRule(true, flowRule);
Hyunsun Moon4a915152016-01-14 16:56:26 -0800819
820 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800821 .matchInPort(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800822 .build();
823
824 treatment = DefaultTrafficTreatment.builder()
825 .transition(TABLE_DST_IP)
826 .build();
827
828 flowRule = DefaultFlowRule.builder()
829 .fromApp(appId)
830 .withSelector(selector)
831 .withTreatment(treatment)
832 .withPriority(DEFAULT_PRIORITY)
833 .forDevice(deviceId)
834 .forTable(TABLE_IN_PORT)
835 .makePermanent()
836 .build();
837
838 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800839 }
840
841 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800842 * Populates default rules for Q_IN_Q table.
843 *
844 * @param deviceId device id
845 * @param dpPort data plane interface port number
846 */
847 private void processQInQTable(DeviceId deviceId, PortNumber dpPort) {
848 // for traffic going out to WAN, strip vid 500 and take through data plane interface
849 TrafficSelector selector = DefaultTrafficSelector.builder()
850 .matchVlanId(VLAN_WAN)
851 .build();
852
853 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
854 .popVlan()
855 .setOutput(dpPort)
856 .build();
857
858 FlowRule flowRule = DefaultFlowRule.builder()
859 .fromApp(appId)
860 .withSelector(selector)
861 .withTreatment(treatment)
862 .withPriority(DEFAULT_PRIORITY)
863 .forDevice(deviceId)
864 .forTable(TABLE_Q_IN_Q)
865 .makePermanent()
866 .build();
867
868 processFlowRule(true, flowRule);
869
870 selector = DefaultTrafficSelector.builder()
871 .matchVlanId(VLAN_WAN)
872 .matchEthType(Ethernet.TYPE_ARP)
873 .build();
874
875 treatment = DefaultTrafficTreatment.builder()
876 .setOutput(PortNumber.CONTROLLER)
877 .build();
878
879 flowRule = DefaultFlowRule.builder()
880 .fromApp(appId)
881 .withSelector(selector)
882 .withTreatment(treatment)
883 .withPriority(HIGH_PRIORITY)
884 .forDevice(deviceId)
885 .forTable(TABLE_Q_IN_Q)
886 .makePermanent()
887 .build();
888
889 processFlowRule(true, flowRule);
890 }
891
892 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800893 * Populates rules for local in port in IN_PORT table.
894 * Flows from a given in port, whose source IP is service IP transition
895 * to DST_TYPE table. Other flows transition to IN_SERVICE table.
896 *
897 * @param deviceId device id to install the rules
898 * @param inPort in port
899 * @param srcIp source ip
900 */
901 private void populateLocalInPortRule(DeviceId deviceId, PortNumber inPort, IpAddress srcIp) {
902 TrafficSelector selector = DefaultTrafficSelector.builder()
903 .matchInPort(inPort)
904 .matchEthType(Ethernet.TYPE_IPV4)
905 .matchIPSrc(srcIp.toIpPrefix())
906 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800907
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800908 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
909 .transition(TABLE_ACCESS_TYPE)
910 .build();
911
912
913 FlowRule flowRule = DefaultFlowRule.builder()
914 .fromApp(appId)
915 .withSelector(selector)
916 .withTreatment(treatment)
917 .withPriority(DEFAULT_PRIORITY)
918 .forDevice(deviceId)
919 .forTable(TABLE_IN_PORT)
920 .makePermanent()
921 .build();
922
923 processFlowRule(true, flowRule);
924
925 selector = DefaultTrafficSelector.builder()
926 .matchInPort(inPort)
927 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800928
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800929 treatment = DefaultTrafficTreatment.builder()
930 .transition(TABLE_IN_SERVICE)
931 .build();
932
933 flowRule = DefaultFlowRule.builder()
934 .fromApp(appId)
935 .withSelector(selector)
936 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800937 .withPriority(LOW_PRIORITY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800938 .forDevice(deviceId)
939 .forTable(TABLE_IN_PORT)
940 .makePermanent()
941 .build();
942
943 processFlowRule(true, flowRule);
944 }
945
946 /**
947 * Populates direct VM access rules for ACCESS_TYPE table.
948 * These rules are installed to all devices.
949 *
950 * @param srcRange source ip range
951 * @param dstRange destination ip range
952 */
953 private void populateDirectAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange) {
954 TrafficSelector selector = DefaultTrafficSelector.builder()
955 .matchEthType(Ethernet.TYPE_IPV4)
956 .matchIPSrc(srcRange)
957 .matchIPDst(dstRange)
958 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800959
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800960 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
961 .transition(TABLE_DST_IP)
962 .build();
963
Hyunsun Moon98025542016-03-08 04:36:02 -0800964
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800965 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800966 FlowRule flowRuleDirect = DefaultFlowRule.builder()
967 .fromApp(appId)
968 .withSelector(selector)
969 .withTreatment(treatment)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800970 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800971 .forDevice(deviceId)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800972 .forTable(TABLE_ACCESS_TYPE)
973 .makePermanent()
974 .build();
975
976 processFlowRule(true, flowRuleDirect);
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800977 });
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800978 }
979
980 /**
981 * Populates drop rules that does not match any direct access rules but has
982 * destination to a different service network in ACCESS_TYPE table.
983 *
984 * @param dstRange destination ip range
985 */
986 private void populateServiceIsolationRule(Ip4Prefix dstRange) {
987 TrafficSelector selector = DefaultTrafficSelector.builder()
988 .matchEthType(Ethernet.TYPE_IPV4)
989 .matchIPDst(dstRange)
990 .build();
991
992 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
993 .drop()
994 .build();
995
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800996 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800997 FlowRule flowRuleDirect = DefaultFlowRule.builder()
998 .fromApp(appId)
999 .withSelector(selector)
1000 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001001 .withPriority(LOW_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001002 .forDevice(deviceId)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001003 .forTable(TABLE_ACCESS_TYPE)
1004 .makePermanent()
1005 .build();
1006
1007 processFlowRule(true, flowRuleDirect);
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001008 });
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001009 }
1010
1011 /**
1012 * Populates indirect service access rules for ACCESS_TYPE table.
1013 * These rules are installed to all devices.
1014 *
1015 * @param srcRange source range
1016 * @param serviceIp service ip
1017 * @param outGroups list of output group
1018 */
1019 private void populateIndirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
1020 Map<DeviceId, GroupId> outGroups) {
1021 TrafficSelector selector = DefaultTrafficSelector.builder()
1022 .matchEthType(Ethernet.TYPE_IPV4)
1023 .matchIPSrc(srcRange)
1024 .matchIPDst(serviceIp.toIpPrefix())
1025 .build();
1026
1027 for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
1028 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1029 .group(outGroup.getValue())
1030 .build();
1031
1032 FlowRule flowRule = DefaultFlowRule.builder()
1033 .fromApp(appId)
1034 .withSelector(selector)
1035 .withTreatment(treatment)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -08001036 .withPriority(HIGH_PRIORITY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001037 .forDevice(outGroup.getKey())
1038 .forTable(TABLE_ACCESS_TYPE)
1039 .makePermanent()
1040 .build();
1041
1042 processFlowRule(true, flowRule);
1043 }
1044 }
1045
1046 /**
1047 * Populates flow rules for IN_SERVICE table.
1048 *
1049 * @param inPorts list of inports related to the service for each device
1050 * @param outGroups set of output groups
1051 */
1052 private void populateInServiceRule(Map<DeviceId, Set<PortNumber>> inPorts, Map<DeviceId, GroupId> outGroups) {
1053 checkNotNull(inPorts);
1054 checkNotNull(outGroups);
1055
1056 for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
1057 Set<PortNumber> ports = entry.getValue();
1058 DeviceId deviceId = entry.getKey();
1059
1060 GroupId groupId = outGroups.get(deviceId);
1061 if (groupId == null) {
1062 continue;
1063 }
1064
1065 ports.stream().forEach(port -> {
1066 TrafficSelector selector = DefaultTrafficSelector.builder()
1067 .matchInPort(port)
1068 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001069
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001070 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1071 .group(groupId)
1072 .build();
1073
1074 FlowRule flowRule = DefaultFlowRule.builder()
1075 .fromApp(appId)
1076 .withSelector(selector)
1077 .withTreatment(treatment)
1078 .withPriority(DEFAULT_PRIORITY)
1079 .forDevice(deviceId)
1080 .forTable(TABLE_IN_SERVICE)
1081 .makePermanent()
1082 .build();
1083
1084 processFlowRule(true, flowRule);
1085 });
1086 }
1087 }
1088
1089 /**
1090 * Populates flow rules for DST_IP table.
1091 *
1092 * @param deviceId device id
1093 * @param inPort in port
1094 * @param dstMac mac address
1095 * @param dstIp destination ip
1096 * @param tunnelId tunnel id
1097 * @param tunnelIp tunnel remote ip
1098 */
1099 private void populateDstIpRule(DeviceId deviceId, PortNumber inPort, MacAddress dstMac,
1100 IpAddress dstIp, long tunnelId, IpAddress tunnelIp) {
1101 TrafficSelector selector = DefaultTrafficSelector.builder()
1102 .matchEthType(Ethernet.TYPE_IPV4)
1103 .matchIPDst(dstIp.toIpPrefix())
1104 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001105
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001106 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1107 .setEthDst(dstMac)
1108 .setOutput(inPort)
1109 .build();
1110
1111 FlowRule flowRule = DefaultFlowRule.builder()
1112 .fromApp(appId)
1113 .withSelector(selector)
1114 .withTreatment(treatment)
1115 .withPriority(DEFAULT_PRIORITY)
1116 .forDevice(deviceId)
1117 .forTable(TABLE_DST_IP)
1118 .makePermanent()
1119 .build();
1120
1121 processFlowRule(true, flowRule);
1122
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001123 for (DeviceId vSwitchId : getVirtualSwitches()) {
1124 if (vSwitchId.equals(deviceId)) {
Hyunsun Moon98025542016-03-08 04:36:02 -08001125 continue;
1126 }
1127
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001128 ExtensionTreatment tunnelDst = getTunnelDst(vSwitchId, tunnelIp.getIp4Address());
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001129 if (tunnelDst == null) {
1130 continue;
1131 }
1132
1133 treatment = DefaultTrafficTreatment.builder()
1134 .setEthDst(dstMac)
1135 .setTunnelId(tunnelId)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001136 .extension(tunnelDst, vSwitchId)
1137 .setOutput(getTunnelPort(vSwitchId))
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001138 .build();
1139
1140 flowRule = DefaultFlowRule.builder()
1141 .fromApp(appId)
1142 .withSelector(selector)
1143 .withTreatment(treatment)
1144 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001145 .forDevice(vSwitchId)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001146 .forTable(TABLE_DST_IP)
1147 .makePermanent()
1148 .build();
1149
1150 processFlowRule(true, flowRule);
1151 }
1152 }
1153
1154 /**
1155 * Populates flow rules for TUNNEL_ID table.
1156 *
1157 * @param deviceId device id
1158 * @param inPort in port
1159 * @param mac mac address
1160 * @param tunnelId tunnel id
1161 */
1162 private void populateTunnelInRule(DeviceId deviceId, PortNumber inPort, MacAddress mac, long tunnelId) {
1163 TrafficSelector selector = DefaultTrafficSelector.builder()
1164 .matchTunnelId(tunnelId)
1165 .matchEthDst(mac)
1166 .build();
1167
1168 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1169 .setOutput(inPort)
1170 .build();
1171
1172 FlowRule flowRule = DefaultFlowRule.builder()
1173 .fromApp(appId)
1174 .withSelector(selector)
1175 .withTreatment(treatment)
1176 .withPriority(DEFAULT_PRIORITY)
1177 .forDevice(deviceId)
1178 .forTable(TABLE_TUNNEL_IN)
1179 .makePermanent()
1180 .build();
1181
1182 processFlowRule(true, flowRule);
1183 }
1184
1185 /**
1186 * Installs or uninstall a given rule.
1187 *
1188 * @param install true to install, false to uninstall
1189 * @param rule rule
1190 */
1191 private void processFlowRule(boolean install, FlowRule rule) {
1192 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
1193 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
1194
1195 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
1196 @Override
1197 public void onError(FlowRuleOperations ops) {
1198 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
1199 }
1200 }));
1201 }
1202
1203 /**
1204 * Returns tunnel port of the device.
1205 *
1206 * @param deviceId device id
1207 * @return tunnel port number, or null if no tunnel port exists on a given device
1208 */
1209 private PortNumber getTunnelPort(DeviceId deviceId) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001210 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001211 .filter(p -> p.annotations().value(PORT_NAME).contains(tunnelType))
1212 .findFirst().orElse(null);
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001213
1214 return port == null ? null : port.number();
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001215 }
1216
1217 /**
Hyunsun Moon133fd792016-02-09 01:55:48 -08001218 * Returns data plane interface port name of a given device.
Hyunsun Moon4a915152016-01-14 16:56:26 -08001219 *
1220 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -08001221 * @param dpIntf data plane interface port name
1222 * @return data plane interface port number, or null if no such port exists
Hyunsun Moon4a915152016-01-14 16:56:26 -08001223 */
Hyunsun Moon133fd792016-02-09 01:55:48 -08001224 private PortNumber getDpPort(DeviceId deviceId, String dpIntf) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001225 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001226 .filter(p -> p.annotations().value(PORT_NAME).contains(dpIntf) &&
1227 p.isEnabled())
1228 .findFirst().orElse(null);
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001229
1230 return port == null ? null : port.number();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001231 }
1232
Hyunsun Moon6d247342016-02-12 12:48:47 -08001233 /** Returns data plane interface port number of a given host.
1234 *
1235 * @param host host
1236 * @return port number, or null
1237 */
1238 private PortNumber getDpPort(Host host) {
1239 String portName = host.annotations().value(DATA_PLANE_INTF);
1240 return portName == null ? null : getDpPort(host.location().deviceId(), portName);
1241 }
1242
1243 /**
1244 * Returns service vlan from a given host.
1245 *
1246 * @param host host
1247 * @return vlan id, or null
1248 */
1249 private VlanId getServiceVlan(Host host) {
1250 String serviceVlan = host.annotations().value(S_TAG);
1251 return serviceVlan == null ? null : VlanId.vlanId(Short.parseShort(serviceVlan));
1252 }
1253
Hyunsun Moon4a915152016-01-14 16:56:26 -08001254 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001255 * Returns the inport from a given flow rule if the rule contains the match of it.
1256 *
1257 * @param flowRule flow rule
1258 * @return port number, or null if the rule doesn't have inport match
1259 */
1260 private PortNumber getInPort(FlowRule flowRule) {
1261 Criterion criterion = flowRule.selector().getCriterion(IN_PORT);
1262 if (criterion != null && criterion instanceof PortCriterion) {
1263 PortCriterion port = (PortCriterion) criterion;
1264 return port.port();
1265 } else {
1266 return null;
1267 }
1268 }
1269
1270 /**
1271 * Returns the destination mac address from a given flow rule if the rule
1272 * contains the instruction of it.
1273 *
1274 * @param flowRule flow rule
1275 * @return mac address, or null if the rule doesn't have destination mac instruction
1276 */
1277 private MacAddress getDstMacFromTreatment(FlowRule flowRule) {
1278 Instruction instruction = flowRule.treatment().allInstructions().stream()
1279 .filter(inst -> inst instanceof ModEtherInstruction &&
1280 ((ModEtherInstruction) inst).subtype().equals(ETH_DST))
1281 .findFirst()
1282 .orElse(null);
1283
1284 if (instruction == null) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001285 return null;
1286 }
1287
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001288 return ((ModEtherInstruction) instruction).mac();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001289 }
1290
1291 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001292 * Returns the destination mac address from a given flow rule if the rule
1293 * contains the match of it.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001294 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001295 * @param flowRule flow rule
1296 * @return mac address, or null if the rule doesn't have destination mac match
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001297 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001298 private MacAddress getDstMacFromSelector(FlowRule flowRule) {
1299 Criterion criterion = flowRule.selector().getCriterion(Criterion.Type.ETH_DST);
1300 if (criterion != null && criterion instanceof EthCriterion) {
1301 EthCriterion eth = (EthCriterion) criterion;
1302 return eth.mac();
1303 } else {
1304 return null;
1305 }
1306 }
1307
1308 /**
1309 * Returns the destination IP from a given flow rule if the rule contains
1310 * the match of it.
1311 *
1312 * @param flowRule flow rule
1313 * @return ip prefix, or null if the rule doesn't have ip match
1314 */
1315 private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
1316 Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
1317 if (criterion != null && criterion instanceof IPCriterion) {
1318 IPCriterion ip = (IPCriterion) criterion;
1319 return ip.ip();
1320 } else {
1321 return null;
1322 }
1323 }
1324
1325 /**
1326 * Returns the source IP from a given flow rule if the rule contains
1327 * the match of it.
1328 *
1329 * @param flowRule flow rule
1330 * @return ip prefix, or null if the rule doesn't have ip match
1331 */
1332 private IpPrefix getSrcIpFromSelector(FlowRule flowRule) {
1333 Criterion criterion = flowRule.selector().getCriterion(IPV4_SRC);
1334 if (criterion != null && criterion instanceof IPCriterion) {
1335 IPCriterion ip = (IPCriterion) criterion;
1336 return ip.ip();
1337 } else {
1338 return null;
1339 }
1340 }
1341
1342 /**
1343 * Returns the group ID from a given flow rule if the rule contains the
1344 * treatment of it.
1345 *
1346 * @param flowRule flow rule
1347 * @return group id, or null if the rule doesn't have group instruction
1348 */
1349 private GroupId getGroupIdFromTreatment(FlowRule flowRule) {
1350 Instruction instruction = flowRule.treatment().allInstructions().stream()
1351 .filter(inst -> inst instanceof Instructions.GroupInstruction)
1352 .findFirst()
1353 .orElse(null);
1354
1355 if (instruction == null) {
1356 return null;
1357 }
1358
1359 return ((Instructions.GroupInstruction) instruction).groupId();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001360 }
1361
1362 /**
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001363 * Returns the output port number from a given flow rule.
1364 *
1365 * @param flowRule flow rule
1366 * @return port number, or null if the rule does not have output instruction
1367 */
1368 private PortNumber getOutputFromTreatment(FlowRule flowRule) {
1369 Instruction instruction = flowRule.treatment().allInstructions().stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001370 .filter(inst -> inst instanceof Instructions.OutputInstruction)
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001371 .findFirst()
1372 .orElse(null);
1373
1374 if (instruction == null) {
1375 return null;
1376 }
1377
1378 return ((Instructions.OutputInstruction) instruction).port();
1379 }
1380
1381 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -08001382 * Returns if a given flow rule has vlan push instruction or not.
1383 *
1384 * @param flowRule flow rule
1385 * @return true if it includes vlan push, or false
1386 */
1387 private boolean isVlanPushFromTreatment(FlowRule flowRule) {
1388 Instruction instruction = flowRule.treatment().allInstructions().stream()
1389 .filter(inst -> inst instanceof L2ModificationInstruction)
1390 .filter(inst -> ((L2ModificationInstruction) inst).subtype().equals(VLAN_PUSH))
1391 .findAny()
1392 .orElse(null);
1393
1394 return instruction != null;
1395 }
1396
1397 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -08001398 * Creates a new group for a given service.
1399 *
1400 * @param deviceId device id to create a group
1401 * @param service cord service
1402 * @return group id, or null if it fails to create
1403 */
1404 private GroupId createServiceGroup(DeviceId deviceId, CordService service) {
1405 checkNotNull(service);
1406
1407 GroupKey groupKey = getGroupKey(service.id());
1408 Group group = groupService.getGroup(deviceId, groupKey);
1409 GroupId groupId = getGroupId(service.id(), deviceId);
1410
1411 if (group != null) {
1412 log.debug("Group {} is already exist in {}", service.id(), deviceId);
1413 return groupId;
1414 }
1415
1416 GroupBuckets buckets = getServiceGroupBuckets(deviceId, service.segmentationId(), service.hosts());
1417 GroupDescription groupDescription = new DefaultGroupDescription(
1418 deviceId,
1419 GroupDescription.Type.SELECT,
1420 buckets,
1421 groupKey,
1422 groupId.id(),
1423 appId);
1424
1425 groupService.addGroup(groupDescription);
1426
1427 return groupId;
1428 }
1429
1430 /**
1431 * Returns group buckets for a given device.
1432 *
1433 * @param deviceId device id
1434 * @param tunnelId tunnel id
1435 * @param hosts list of host
1436 * @return group buckets
1437 */
1438 private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId, Map<Host, IpAddress> hosts) {
1439 List<GroupBucket> buckets = Lists.newArrayList();
1440
1441 for (Map.Entry<Host, IpAddress> entry : hosts.entrySet()) {
1442 Host host = entry.getKey();
1443 Ip4Address remoteIp = entry.getValue().getIp4Address();
1444 DeviceId hostDevice = host.location().deviceId();
1445
1446 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
1447 .builder()
1448 .setEthDst(host.mac());
1449
1450 if (deviceId.equals(hostDevice)) {
1451 tBuilder.setOutput(host.location().port());
1452 } else {
1453 ExtensionTreatment tunnelDst = getTunnelDst(deviceId, remoteIp);
1454 if (tunnelDst == null) {
1455 continue;
1456 }
1457
1458 tBuilder.extension(tunnelDst, deviceId)
1459 .setTunnelId(tunnelId)
1460 .setOutput(getTunnelPort(hostDevice));
1461 }
1462
1463 buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
1464 }
1465
1466 return new GroupBuckets(buckets);
1467 }
1468
1469 /**
1470 * Returns globally unique group ID.
1471 *
1472 * @param serviceId service id
1473 * @param deviceId device id
1474 * @return group id
1475 */
1476 private GroupId getGroupId(CordServiceId serviceId, DeviceId deviceId) {
1477 return new DefaultGroupId(Objects.hash(serviceId, deviceId));
1478 }
1479
1480 /**
1481 * Returns group key of a service.
1482 *
1483 * @param serviceId service id
1484 * @return group key
1485 */
1486 private GroupKey getGroupKey(CordServiceId serviceId) {
1487 return new DefaultGroupKey(serviceId.id().getBytes());
1488 }
1489
1490 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001491 * Returns extension instruction to set tunnel destination.
1492 *
1493 * @param deviceId device id
1494 * @param remoteIp tunnel destination address
1495 * @return extension treatment or null if it fails to get instruction
1496 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001497 private ExtensionTreatment getTunnelDst(DeviceId deviceId, Ip4Address remoteIp) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001498 try {
Jian Li7532eb12016-04-15 13:22:05 -07001499 Device device = deviceService.getDevice(deviceId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001500
Jian Li7532eb12016-04-15 13:22:05 -07001501 if (device.is(ExtensionTreatmentResolver.class)) {
1502 ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
1503 ExtensionTreatment treatment =
1504 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
1505 treatment.setPropertyValue("tunnelDst", remoteIp);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001506
Jian Li7532eb12016-04-15 13:22:05 -07001507 return treatment;
1508 } else {
1509 log.warn("The extension treatment resolving behaviour is not supported in device {}",
1510 device.id().toString());
1511 return null;
1512 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001513 } catch (ItemNotFoundException | UnsupportedOperationException |
1514 ExtensionPropertyException e) {
1515 log.error("Failed to get extension instruction {}", deviceId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001516 return null;
1517 }
1518 }
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001519
1520 /**
1521 * Returns integration bridges configured in the system.
1522 *
1523 * @return set of device ids
1524 */
1525 private Set<DeviceId> getVirtualSwitches() {
1526 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
1527 if (config == null) {
1528 log.debug("No configuration found for {}", appId.name());
1529 return Sets.newHashSet();
1530 }
1531
1532 return config.cordVtnNodes().stream()
1533 .map(CordVtnNode::intBrId).collect(Collectors.toSet());
1534 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001535}
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001536