blob: 8652e187f33947ab52b4d4881c0ab4175f4fa5a2 [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;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080038import org.onosproject.net.DeviceId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080039import org.onosproject.net.Host;
Hyunsun Moon5a4346f2016-01-15 11:41:14 -080040import org.onosproject.net.Port;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080041import org.onosproject.net.PortNumber;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080042import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
Hyunsun Moonfae776d2016-03-08 18:07:52 -080043import org.onosproject.net.config.NetworkConfigRegistry;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080044import org.onosproject.net.device.DeviceService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080045import org.onosproject.net.driver.DefaultDriverData;
46import org.onosproject.net.driver.DefaultDriverHandler;
47import org.onosproject.net.driver.Driver;
48import org.onosproject.net.driver.DriverHandler;
49import org.onosproject.net.driver.DriverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080050import org.onosproject.net.flow.DefaultFlowRule;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080051import org.onosproject.net.flow.DefaultTrafficSelector;
52import org.onosproject.net.flow.DefaultTrafficTreatment;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080053import org.onosproject.net.flow.FlowRule;
54import org.onosproject.net.flow.FlowRuleOperations;
55import org.onosproject.net.flow.FlowRuleOperationsContext;
56import org.onosproject.net.flow.FlowRuleService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080057import org.onosproject.net.flow.TrafficSelector;
58import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080059import org.onosproject.net.flow.criteria.Criterion;
60import org.onosproject.net.flow.criteria.EthCriterion;
61import org.onosproject.net.flow.criteria.IPCriterion;
62import org.onosproject.net.flow.criteria.PortCriterion;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080063import org.onosproject.net.flow.instructions.ExtensionPropertyException;
64import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080065import org.onosproject.net.flow.instructions.Instruction;
66import org.onosproject.net.flow.instructions.Instructions;
Hyunsun Moon6d247342016-02-12 12:48:47 -080067import org.onosproject.net.flow.instructions.L2ModificationInstruction;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080068import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
69import org.onosproject.net.group.DefaultGroupBucket;
70import org.onosproject.net.group.DefaultGroupDescription;
71import org.onosproject.net.group.DefaultGroupKey;
72import org.onosproject.net.group.Group;
73import org.onosproject.net.group.GroupBucket;
74import org.onosproject.net.group.GroupBuckets;
75import org.onosproject.net.group.GroupDescription;
76import org.onosproject.net.group.GroupKey;
77import org.onosproject.net.group.GroupService;
sangho93447f12016-02-24 00:33:22 +090078import org.onosproject.openstackinterface.OpenstackNetwork;
79import org.onosproject.openstackinterface.OpenstackSubnet;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080080import org.slf4j.Logger;
81
Hyunsun Moon4161e6f2016-01-07 01:32:31 -080082import java.util.ArrayList;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080083import java.util.List;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080084import java.util.Map;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080085import java.util.Objects;
86import java.util.Set;
87import java.util.stream.Collectors;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080088
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080089import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080090import static org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT;
91import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_DST;
92import static org.onosproject.net.flow.criteria.Criterion.Type.IPV4_SRC;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080093import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
Hyunsun Moonc71231d2015-12-16 20:53:23 -080094import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
Hyunsun Moon6d247342016-02-12 12:48:47 -080095import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -080096import static org.slf4j.LoggerFactory.getLogger;
97
98/**
Hyunsun Moonc71231d2015-12-16 20:53:23 -080099 * Populates rules for CORD VTN service.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800100 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800101public class CordVtnRuleInstaller {
102
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800103 protected final Logger log = getLogger(getClass());
104
Hyunsun Moon4a915152016-01-14 16:56:26 -0800105 private static final int TABLE_FIRST = 0;
106 private static final int TABLE_IN_PORT = 1;
107 private static final int TABLE_ACCESS_TYPE = 2;
108 private static final int TABLE_IN_SERVICE = 3;
109 private static final int TABLE_DST_IP = 4;
110 private static final int TABLE_TUNNEL_IN = 5;
Hyunsun Moon6d247342016-02-12 12:48:47 -0800111 private static final int TABLE_Q_IN_Q = 6;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800112
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800113 private static final int MANAGEMENT_PRIORITY = 55000;
Hyunsun Moon6d247342016-02-12 12:48:47 -0800114 private static final int VSG_PRIORITY = 55000;
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800115 private static final int HIGH_PRIORITY = 50000;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800116 private static final int DEFAULT_PRIORITY = 5000;
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800117 private static final int LOW_PRIORITY = 4000;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800118 private static final int LOWEST_PRIORITY = 0;
Hyunsun Moon4a915152016-01-14 16:56:26 -0800119
120 private static final int VXLAN_UDP_PORT = 4789;
Hyunsun Moon6d247342016-02-12 12:48:47 -0800121 private static final VlanId VLAN_WAN = VlanId.vlanId((short) 500);
122
123 private static final String PORT_NAME = "portName";
124 private static final String DATA_PLANE_INTF = "dataPlaneIntf";
125 private static final String S_TAG = "stag";
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800126
127 private final ApplicationId appId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800128 private final FlowRuleService flowRuleService;
129 private final DeviceService deviceService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800130 private final DriverService driverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800131 private final GroupService groupService;
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800132 private final NetworkConfigRegistry configRegistry;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800133 private final String tunnelType;
134
135 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800136 * Creates a new rule populator.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800137 *
138 * @param appId application id
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800139 * @param flowRuleService flow rule service
140 * @param deviceService device service
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800141 * @param driverService driver service
Jian Lidfba7392016-01-22 16:46:58 -0800142 * @param groupService group service
Ray Milkeyd4334db2016-04-05 17:39:44 -0700143 * @param configRegistry config registry
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800144 * @param tunnelType tunnel type
145 */
146 public CordVtnRuleInstaller(ApplicationId appId,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800147 FlowRuleService flowRuleService,
148 DeviceService deviceService,
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800149 DriverService driverService,
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800150 GroupService groupService,
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800151 NetworkConfigRegistry configRegistry,
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800152 String tunnelType) {
153 this.appId = appId;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800154 this.flowRuleService = flowRuleService;
155 this.deviceService = deviceService;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800156 this.driverService = driverService;
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800157 this.groupService = groupService;
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800158 this.configRegistry = configRegistry;
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800159 this.tunnelType = checkNotNull(tunnelType);
160 }
161
162 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800163 * Installs table miss rule to a give device.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800164 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800165 * @param deviceId device id to install the rules
Hyunsun Moon133fd792016-02-09 01:55:48 -0800166 * @param dpIntf data plane interface name
167 * @param dpIp data plane ip address
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800168 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800169 public void init(DeviceId deviceId, String dpIntf, IpAddress dpIp) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800170 // default is drop packets which can be accomplished without
171 // a table miss entry for all table.
Hyunsun Moon4a915152016-01-14 16:56:26 -0800172 PortNumber tunnelPort = getTunnelPort(deviceId);
Hyunsun Moon133fd792016-02-09 01:55:48 -0800173 PortNumber dpPort = getDpPort(deviceId, dpIntf);
Hyunsun Moon4a915152016-01-14 16:56:26 -0800174
Hyunsun Moon133fd792016-02-09 01:55:48 -0800175 processFirstTable(deviceId, dpPort, dpIp);
176 processInPortTable(deviceId, tunnelPort, dpPort);
177 processAccessTypeTable(deviceId, dpPort);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800178 processQInQTable(deviceId, dpPort);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800179 }
180
181 /**
Hyunsun Moon2062e7e2016-03-08 15:37:57 -0800182 * Flush flows installed by this application.
183 */
184 public void flushRules() {
185 flowRuleService.getFlowRulesById(appId).forEach(flowRule -> processFlowRule(false, flowRule));
186 }
187
188 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800189 * Populates basic rules that connect a VM to the other VMs in the system.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800190 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800191 * @param host host
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800192 * @param tunnelIp tunnel ip
193 * @param vNet openstack network
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800194 */
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800195 public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, OpenstackNetwork vNet) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800196 checkNotNull(host);
197 checkNotNull(vNet);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800198
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800199 DeviceId deviceId = host.location().deviceId();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800200 PortNumber inPort = host.location().port();
201 MacAddress dstMac = host.mac();
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800202 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800203 long tunnelId = Long.parseLong(vNet.segmentId());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800204
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800205 OpenstackSubnet subnet = vNet.subnets().stream()
206 .findFirst()
207 .orElse(null);
208
209 if (subnet == null) {
210 log.error("Failed to get subnet for {}", host.id());
211 return;
212 }
213
214 populateLocalInPortRule(deviceId, inPort, hostIp);
215 populateDirectAccessRule(Ip4Prefix.valueOf(subnet.cidr()), Ip4Prefix.valueOf(subnet.cidr()));
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800216 populateServiceIsolationRule(Ip4Prefix.valueOf(subnet.cidr()));
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800217 populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
218 populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -0800219 }
220
221 /**
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800222 * Removes all rules related to a given service VM host.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800223 *
224 * @param host host to be removed
225 */
226 public void removeBasicConnectionRules(Host host) {
227 checkNotNull(host);
228
229 DeviceId deviceId = host.location().deviceId();
230 MacAddress mac = host.mac();
231 PortNumber port = host.location().port();
232 IpAddress ip = host.ipAddresses().stream().findFirst().orElse(null);
233
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800234 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
235 if (flowRule.deviceId().equals(deviceId)) {
236 PortNumber inPort = getInPort(flowRule);
237 if (inPort != null && inPort.equals(port)) {
238 processFlowRule(false, flowRule);
239 continue;
240 }
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800241
242 PortNumber output = getOutputFromTreatment(flowRule);
243 if (output != null && output.equals(host.location().port())) {
244 processFlowRule(false, flowRule);
245 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800246 }
247
248 MacAddress dstMac = getDstMacFromTreatment(flowRule);
249 if (dstMac != null && dstMac.equals(mac)) {
250 processFlowRule(false, flowRule);
251 continue;
252 }
253
254 dstMac = getDstMacFromSelector(flowRule);
255 if (dstMac != null && dstMac.equals(mac)) {
256 processFlowRule(false, flowRule);
257 continue;
258 }
259
260 IpPrefix dstIp = getDstIpFromSelector(flowRule);
261 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
262 processFlowRule(false, flowRule);
263 }
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800264 }
265
266 // TODO uninstall same network access rule in access table if no vm exists in the network
267 }
268
269 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800270 * Populates service dependency rules.
271 *
272 * @param tService tenant cord service
273 * @param pService provider cord service
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800274 * @param isBidirectional true to enable bidirectional connection between two services
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800275 */
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800276 public void populateServiceDependencyRules(CordService tService, CordService pService,
277 boolean isBidirectional) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800278 checkNotNull(tService);
279 checkNotNull(pService);
280
281 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
282 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
283 Ip4Address serviceIp = pService.serviceIp().getIp4Address();
284
285 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
286 Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
287
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800288 getVirtualSwitches().stream().forEach(deviceId -> {
289 GroupId groupId = createServiceGroup(deviceId, pService);
290 outGroups.put(deviceId, groupId);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800291
292 Set<PortNumber> vms = tService.hosts().keySet()
293 .stream()
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800294 .filter(host -> host.location().deviceId().equals(deviceId))
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800295 .map(host -> host.location().port())
296 .collect(Collectors.toSet());
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800297 inPorts.put(deviceId, vms);
298 });
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800299
300 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
301 populateDirectAccessRule(srcRange, dstRange);
Hyunsun Moon640f183e2016-02-10 17:02:37 -0800302 if (isBidirectional) {
303 populateDirectAccessRule(dstRange, srcRange);
304 }
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800305 populateInServiceRule(inPorts, outGroups);
306 }
307
308 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800309 * Removes service dependency rules.
310 *
311 * @param tService tenant cord service
312 * @param pService provider cord service
313 */
314 public void removeServiceDependencyRules(CordService tService, CordService pService) {
315 checkNotNull(tService);
316 checkNotNull(pService);
317
318 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
319 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
320 IpPrefix serviceIp = pService.serviceIp().toIpPrefix();
321
322 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
323 GroupKey groupKey = new DefaultGroupKey(pService.id().id().getBytes());
324
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800325 getVirtualSwitches().stream().forEach(deviceId -> {
326 Group group = groupService.getGroup(deviceId, groupKey);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800327 if (group != null) {
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800328 outGroups.put(deviceId, group.id());
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800329 }
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800330 });
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800331
332 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
333 IpPrefix dstIp = getDstIpFromSelector(flowRule);
334 IpPrefix srcIp = getSrcIpFromSelector(flowRule);
335
336 if (dstIp != null && dstIp.equals(serviceIp)) {
337 processFlowRule(false, flowRule);
338 continue;
339 }
340
341 if (dstIp != null && srcIp != null) {
342 if (dstIp.equals(dstRange) && srcIp.equals(srcRange)) {
343 processFlowRule(false, flowRule);
344 continue;
345 }
346
347 if (dstIp.equals(srcRange) && srcIp.equals(dstRange)) {
348 processFlowRule(false, flowRule);
349 continue;
350 }
351 }
352
353 GroupId groupId = getGroupIdFromTreatment(flowRule);
354 if (groupId != null && groupId.equals(outGroups.get(flowRule.deviceId()))) {
355 processFlowRule(false, flowRule);
356 }
357 }
358
359 // TODO remove the group if it is not in use
360 }
361
362 /**
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800363 * Updates group buckets for a given service to all devices.
364 *
365 * @param service cord service
366 */
367 public void updateServiceGroup(CordService service) {
368 checkNotNull(service);
369
370 GroupKey groupKey = getGroupKey(service.id());
371
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800372 for (DeviceId deviceId : getVirtualSwitches()) {
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800373 Group group = groupService.getGroup(deviceId, groupKey);
374 if (group == null) {
Hyunsun Moonb77b60f2016-01-15 20:03:18 -0800375 log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId);
Hyunsun Moon4161e6f2016-01-07 01:32:31 -0800376 continue;
377 }
378
379 List<GroupBucket> oldBuckets = group.buckets().buckets();
380 List<GroupBucket> newBuckets = getServiceGroupBuckets(
381 deviceId, service.segmentationId(), service.hosts()).buckets();
382
383 if (oldBuckets.equals(newBuckets)) {
384 continue;
385 }
386
387 List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
388 bucketsToRemove.removeAll(newBuckets);
389 if (!bucketsToRemove.isEmpty()) {
390 groupService.removeBucketsFromGroup(
391 deviceId,
392 groupKey,
393 new GroupBuckets(bucketsToRemove),
394 groupKey, appId);
395 }
396
397 List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
398 bucketsToAdd.removeAll(oldBuckets);
399 if (!bucketsToAdd.isEmpty()) {
400 groupService.addBucketsToGroup(
401 deviceId,
402 groupKey,
403 new GroupBuckets(bucketsToAdd),
404 groupKey, appId);
405 }
406 }
407 }
408
409 /**
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800410 * Populates flow rules for management network access.
411 *
412 * @param host host which has management network interface
413 * @param mService management network service
414 */
415 public void populateManagementNetworkRules(Host host, CordService mService) {
416 checkNotNull(mService);
417
418 DeviceId deviceId = host.location().deviceId();
419 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
420
421 TrafficSelector selector = DefaultTrafficSelector.builder()
422 .matchEthType(Ethernet.TYPE_ARP)
423 .matchArpTpa(mService.serviceIp().getIp4Address())
424 .build();
425
426 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
427 .setOutput(PortNumber.LOCAL)
428 .build();
429
430 FlowRule flowRule = DefaultFlowRule.builder()
431 .fromApp(appId)
432 .withSelector(selector)
433 .withTreatment(treatment)
434 .withPriority(MANAGEMENT_PRIORITY)
435 .forDevice(deviceId)
436 .forTable(TABLE_FIRST)
437 .makePermanent()
438 .build();
439
440 processFlowRule(true, flowRule);
441
442 selector = DefaultTrafficSelector.builder()
443 .matchInPort(PortNumber.LOCAL)
444 .matchEthType(Ethernet.TYPE_ARP)
445 .matchArpTpa(hostIp.getIp4Address())
446 .build();
447
448 treatment = DefaultTrafficTreatment.builder()
449 .setOutput(host.location().port())
450 .build();
451
452 flowRule = DefaultFlowRule.builder()
453 .fromApp(appId)
454 .withSelector(selector)
455 .withTreatment(treatment)
456 .withPriority(MANAGEMENT_PRIORITY)
457 .forDevice(deviceId)
458 .forTable(TABLE_FIRST)
459 .makePermanent()
460 .build();
461
462 processFlowRule(true, flowRule);
463
464 selector = DefaultTrafficSelector.builder()
465 .matchInPort(PortNumber.LOCAL)
466 .matchEthType(Ethernet.TYPE_IPV4)
467 .matchIPDst(mService.serviceIpRange())
468 .build();
469
470 treatment = DefaultTrafficTreatment.builder()
471 .transition(TABLE_DST_IP)
472 .build();
473
474 flowRule = DefaultFlowRule.builder()
475 .fromApp(appId)
476 .withSelector(selector)
477 .withTreatment(treatment)
478 .withPriority(MANAGEMENT_PRIORITY)
479 .forDevice(deviceId)
480 .forTable(TABLE_FIRST)
481 .makePermanent()
482 .build();
483
484 processFlowRule(true, flowRule);
485
486 selector = DefaultTrafficSelector.builder()
487 .matchEthType(Ethernet.TYPE_IPV4)
488 .matchIPDst(mService.serviceIp().toIpPrefix())
489 .build();
490
491 treatment = DefaultTrafficTreatment.builder()
492 .setOutput(PortNumber.LOCAL)
493 .build();
494
495 flowRule = DefaultFlowRule.builder()
496 .fromApp(appId)
497 .withSelector(selector)
498 .withTreatment(treatment)
499 .withPriority(MANAGEMENT_PRIORITY)
500 .forDevice(deviceId)
501 .forTable(TABLE_ACCESS_TYPE)
502 .makePermanent()
503 .build();
504
505 processFlowRule(true, flowRule);
506 }
507
508 /**
509 * Removes management network access rules.
510 *
511 * @param host host to be removed
512 * @param mService service for management network
513 */
514 public void removeManagementNetworkRules(Host host, CordService mService) {
515 checkNotNull(mService);
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800516 // TODO remove management network specific rules
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800517 }
518
519 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800520 * Populates rules for vSG VM.
521 *
522 * @param vSgHost vSG host
523 * @param vSgIps set of ip addresses of vSGs running inside the vSG VM
524 */
525 public void populateSubscriberGatewayRules(Host vSgHost, Set<IpAddress> vSgIps) {
526 VlanId serviceVlan = getServiceVlan(vSgHost);
527 PortNumber dpPort = getDpPort(vSgHost);
528
529 if (serviceVlan == null || dpPort == null) {
530 log.warn("Failed to populate rules for vSG VM {}", vSgHost.id());
531 return;
532 }
533
534 // for traffics with s-tag, strip the tag and take through the vSG VM
535 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800536 .matchInPort(dpPort)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800537 .matchVlanId(serviceVlan)
538 .build();
539
540 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon6d247342016-02-12 12:48:47 -0800541 .setOutput(vSgHost.location().port())
542 .build();
543
544 FlowRule flowRule = DefaultFlowRule.builder()
545 .fromApp(appId)
546 .withSelector(selector)
547 .withTreatment(treatment)
548 .withPriority(DEFAULT_PRIORITY)
549 .forDevice(vSgHost.location().deviceId())
550 .forTable(TABLE_Q_IN_Q)
551 .makePermanent()
552 .build();
553
554 processFlowRule(true, flowRule);
555
556 // for traffics with customer vlan, tag with the service vlan based on input port with
557 // lower priority to avoid conflict with WAN tag
558 selector = DefaultTrafficSelector.builder()
559 .matchInPort(vSgHost.location().port())
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800560 .matchVlanId(serviceVlan)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800561 .build();
562
563 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon6d247342016-02-12 12:48:47 -0800564 .setOutput(dpPort)
565 .build();
566
567 flowRule = DefaultFlowRule.builder()
568 .fromApp(appId)
569 .withSelector(selector)
570 .withTreatment(treatment)
Hyunsun Moond5f6c3b2016-02-18 15:37:22 -0800571 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800572 .forDevice(vSgHost.location().deviceId())
573 .forTable(TABLE_Q_IN_Q)
574 .makePermanent()
575 .build();
576
577 processFlowRule(true, flowRule);
578
579 // for traffic coming from WAN, tag 500 and take through the vSG VM
580 // based on destination ip
581 vSgIps.stream().forEach(ip -> {
582 TrafficSelector downstream = DefaultTrafficSelector.builder()
583 .matchEthType(Ethernet.TYPE_IPV4)
584 .matchIPDst(ip.toIpPrefix())
585 .build();
586
587 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
588 .pushVlan()
589 .setVlanId(VLAN_WAN)
590 .setEthDst(vSgHost.mac())
591 .setOutput(vSgHost.location().port())
592 .build();
593
594 FlowRule downstreamFlowRule = DefaultFlowRule.builder()
595 .fromApp(appId)
596 .withSelector(downstream)
597 .withTreatment(downstreamTreatment)
598 .withPriority(DEFAULT_PRIORITY)
599 .forDevice(vSgHost.location().deviceId())
600 .forTable(TABLE_DST_IP)
601 .makePermanent()
602 .build();
603
604 processFlowRule(true, downstreamFlowRule);
605 });
606
607 // remove downstream flow rules for the vSG not shown in vSgIps
608 for (FlowRule rule : flowRuleService.getFlowRulesById(appId)) {
609 if (!rule.deviceId().equals(vSgHost.location().deviceId())) {
610 continue;
611 }
612 PortNumber output = getOutputFromTreatment(rule);
613 if (output == null || !output.equals(vSgHost.location().port()) ||
614 !isVlanPushFromTreatment(rule)) {
615 continue;
616 }
617
618 IpPrefix dstIp = getDstIpFromSelector(rule);
619 if (dstIp != null && !vSgIps.contains(dstIp.address())) {
620 processFlowRule(false, rule);
621 }
622 }
623 }
624
625 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800626 * Populates default rules on the first table.
Hyunsun Moon133fd792016-02-09 01:55:48 -0800627 * It includes the rules for shuttling vxlan-encapped packets between ovs and
628 * linux stack,and external network connectivity.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800629 *
630 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -0800631 * @param dpPort data plane interface port number
632 * @param dpIp data plane ip address
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800633 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800634 private void processFirstTable(DeviceId deviceId, PortNumber dpPort, IpAddress dpIp) {
Hyunsun Moon4a915152016-01-14 16:56:26 -0800635 // take vxlan packet out onto the physical port
636 TrafficSelector selector = DefaultTrafficSelector.builder()
637 .matchInPort(PortNumber.LOCAL)
638 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800639
Hyunsun Moon4a915152016-01-14 16:56:26 -0800640 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800641 .setOutput(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800642 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800643
Hyunsun Moon4a915152016-01-14 16:56:26 -0800644 FlowRule flowRule = DefaultFlowRule.builder()
645 .fromApp(appId)
646 .withSelector(selector)
647 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800648 .withPriority(HIGH_PRIORITY)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800649 .forDevice(deviceId)
650 .forTable(TABLE_FIRST)
651 .makePermanent()
652 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800653
Hyunsun Moon4a915152016-01-14 16:56:26 -0800654 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800655
Hyunsun Moon4a915152016-01-14 16:56:26 -0800656 // take a vxlan encap'd packet through the Linux stack
657 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800658 .matchInPort(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800659 .matchEthType(Ethernet.TYPE_IPV4)
660 .matchIPProtocol(IPv4.PROTOCOL_UDP)
661 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
662 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800663
Hyunsun Moon4a915152016-01-14 16:56:26 -0800664 treatment = DefaultTrafficTreatment.builder()
665 .setOutput(PortNumber.LOCAL)
666 .build();
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800667
Hyunsun Moon4a915152016-01-14 16:56:26 -0800668 flowRule = DefaultFlowRule.builder()
669 .fromApp(appId)
670 .withSelector(selector)
671 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800672 .withPriority(HIGH_PRIORITY)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800673 .forDevice(deviceId)
674 .forTable(TABLE_FIRST)
675 .makePermanent()
676 .build();
677
678 processFlowRule(true, flowRule);
679
Hyunsun Moon133fd792016-02-09 01:55:48 -0800680 // take a packet to the data plane ip through Linux stack
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800681 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800682 .matchInPort(dpPort)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800683 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon133fd792016-02-09 01:55:48 -0800684 .matchIPDst(dpIp.toIpPrefix())
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800685 .build();
686
687 treatment = DefaultTrafficTreatment.builder()
688 .setOutput(PortNumber.LOCAL)
689 .build();
690
691 flowRule = DefaultFlowRule.builder()
692 .fromApp(appId)
693 .withSelector(selector)
694 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800695 .withPriority(HIGH_PRIORITY)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800696 .forDevice(deviceId)
697 .forTable(TABLE_FIRST)
698 .makePermanent()
699 .build();
700
701 processFlowRule(true, flowRule);
702
703 // take an arp packet from physical through Linux stack
704 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800705 .matchInPort(dpPort)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800706 .matchEthType(Ethernet.TYPE_ARP)
Hyunsun Moon6d247342016-02-12 12:48:47 -0800707 .matchArpTpa(dpIp.getIp4Address())
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800708 .build();
709
710 treatment = DefaultTrafficTreatment.builder()
711 .setOutput(PortNumber.LOCAL)
712 .build();
713
714 flowRule = DefaultFlowRule.builder()
715 .fromApp(appId)
716 .withSelector(selector)
717 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800718 .withPriority(HIGH_PRIORITY)
Hyunsun Moonb4f85082016-01-15 20:11:41 -0800719 .forDevice(deviceId)
720 .forTable(TABLE_FIRST)
721 .makePermanent()
722 .build();
723
724 processFlowRule(true, flowRule);
725
Hyunsun Moon4a915152016-01-14 16:56:26 -0800726 // take all else to the next table
727 selector = DefaultTrafficSelector.builder()
728 .build();
729
730 treatment = DefaultTrafficTreatment.builder()
731 .transition(TABLE_IN_PORT)
732 .build();
733
734 flowRule = DefaultFlowRule.builder()
735 .fromApp(appId)
736 .withSelector(selector)
737 .withTreatment(treatment)
738 .withPriority(LOWEST_PRIORITY)
739 .forDevice(deviceId)
740 .forTable(TABLE_FIRST)
741 .makePermanent()
742 .build();
743
744 processFlowRule(true, flowRule);
Hyunsun Moon6d247342016-02-12 12:48:47 -0800745
746 // take all vlan tagged packet to the Q_IN_Q table
747 selector = DefaultTrafficSelector.builder()
748 .matchVlanId(VlanId.ANY)
749 .build();
750
751 treatment = DefaultTrafficTreatment.builder()
752 .transition(TABLE_Q_IN_Q)
753 .build();
754
755 flowRule = DefaultFlowRule.builder()
756 .fromApp(appId)
757 .withSelector(selector)
758 .withTreatment(treatment)
759 .withPriority(VSG_PRIORITY)
760 .forDevice(deviceId)
761 .forTable(TABLE_FIRST)
762 .makePermanent()
763 .build();
764
765 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800766 }
767
768 /**
Hyunsun Moon133fd792016-02-09 01:55:48 -0800769 * Forward table miss packets in ACCESS_TYPE table to data plane port.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800770 *
771 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -0800772 * @param dpPort data plane interface port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800773 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800774 private void processAccessTypeTable(DeviceId deviceId, PortNumber dpPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800775 TrafficSelector selector = DefaultTrafficSelector.builder()
776 .build();
777
778 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800779 .setOutput(dpPort)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800780 .build();
781
782 FlowRule flowRule = DefaultFlowRule.builder()
783 .fromApp(appId)
784 .withSelector(selector)
785 .withTreatment(treatment)
786 .withPriority(LOWEST_PRIORITY)
787 .forDevice(deviceId)
788 .forTable(TABLE_ACCESS_TYPE)
789 .makePermanent()
790 .build();
791
792 processFlowRule(true, flowRule);
793 }
794
795 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -0800796 * Populates default rules for IN_PORT table.
797 * All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
Hyunsun Moon133fd792016-02-09 01:55:48 -0800798 * from data plane interface port to ACCESS_TYPE table.
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800799 *
800 * @param deviceId device id to install the rules
Hyunsun Moon4a915152016-01-14 16:56:26 -0800801 * @param tunnelPort tunnel port number
Hyunsun Moon133fd792016-02-09 01:55:48 -0800802 * @param dpPort data plane interface port number
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800803 */
Hyunsun Moon133fd792016-02-09 01:55:48 -0800804 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dpPort) {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800805 checkNotNull(tunnelPort);
806
807 TrafficSelector selector = DefaultTrafficSelector.builder()
808 .matchInPort(tunnelPort)
809 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800810
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800811 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
812 .transition(TABLE_TUNNEL_IN)
813 .build();
814
815 FlowRule flowRule = DefaultFlowRule.builder()
816 .fromApp(appId)
817 .withSelector(selector)
818 .withTreatment(treatment)
819 .withPriority(DEFAULT_PRIORITY)
820 .forDevice(deviceId)
821 .forTable(TABLE_IN_PORT)
822 .makePermanent()
823 .build();
824
825 processFlowRule(true, flowRule);
Hyunsun Moon4a915152016-01-14 16:56:26 -0800826
827 selector = DefaultTrafficSelector.builder()
Hyunsun Moon133fd792016-02-09 01:55:48 -0800828 .matchInPort(dpPort)
Hyunsun Moon4a915152016-01-14 16:56:26 -0800829 .build();
830
831 treatment = DefaultTrafficTreatment.builder()
832 .transition(TABLE_DST_IP)
833 .build();
834
835 flowRule = DefaultFlowRule.builder()
836 .fromApp(appId)
837 .withSelector(selector)
838 .withTreatment(treatment)
839 .withPriority(DEFAULT_PRIORITY)
840 .forDevice(deviceId)
841 .forTable(TABLE_IN_PORT)
842 .makePermanent()
843 .build();
844
845 processFlowRule(true, flowRule);
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800846 }
847
848 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -0800849 * Populates default rules for Q_IN_Q table.
850 *
851 * @param deviceId device id
852 * @param dpPort data plane interface port number
853 */
854 private void processQInQTable(DeviceId deviceId, PortNumber dpPort) {
855 // for traffic going out to WAN, strip vid 500 and take through data plane interface
856 TrafficSelector selector = DefaultTrafficSelector.builder()
857 .matchVlanId(VLAN_WAN)
858 .build();
859
860 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
861 .popVlan()
862 .setOutput(dpPort)
863 .build();
864
865 FlowRule flowRule = DefaultFlowRule.builder()
866 .fromApp(appId)
867 .withSelector(selector)
868 .withTreatment(treatment)
869 .withPriority(DEFAULT_PRIORITY)
870 .forDevice(deviceId)
871 .forTable(TABLE_Q_IN_Q)
872 .makePermanent()
873 .build();
874
875 processFlowRule(true, flowRule);
876
877 selector = DefaultTrafficSelector.builder()
878 .matchVlanId(VLAN_WAN)
879 .matchEthType(Ethernet.TYPE_ARP)
880 .build();
881
882 treatment = DefaultTrafficTreatment.builder()
883 .setOutput(PortNumber.CONTROLLER)
884 .build();
885
886 flowRule = DefaultFlowRule.builder()
887 .fromApp(appId)
888 .withSelector(selector)
889 .withTreatment(treatment)
890 .withPriority(HIGH_PRIORITY)
891 .forDevice(deviceId)
892 .forTable(TABLE_Q_IN_Q)
893 .makePermanent()
894 .build();
895
896 processFlowRule(true, flowRule);
897 }
898
899 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800900 * Populates rules for local in port in IN_PORT table.
901 * Flows from a given in port, whose source IP is service IP transition
902 * to DST_TYPE table. Other flows transition to IN_SERVICE table.
903 *
904 * @param deviceId device id to install the rules
905 * @param inPort in port
906 * @param srcIp source ip
907 */
908 private void populateLocalInPortRule(DeviceId deviceId, PortNumber inPort, IpAddress srcIp) {
909 TrafficSelector selector = DefaultTrafficSelector.builder()
910 .matchInPort(inPort)
911 .matchEthType(Ethernet.TYPE_IPV4)
912 .matchIPSrc(srcIp.toIpPrefix())
913 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800914
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800915 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
916 .transition(TABLE_ACCESS_TYPE)
917 .build();
918
919
920 FlowRule flowRule = DefaultFlowRule.builder()
921 .fromApp(appId)
922 .withSelector(selector)
923 .withTreatment(treatment)
924 .withPriority(DEFAULT_PRIORITY)
925 .forDevice(deviceId)
926 .forTable(TABLE_IN_PORT)
927 .makePermanent()
928 .build();
929
930 processFlowRule(true, flowRule);
931
932 selector = DefaultTrafficSelector.builder()
933 .matchInPort(inPort)
934 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800935
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800936 treatment = DefaultTrafficTreatment.builder()
937 .transition(TABLE_IN_SERVICE)
938 .build();
939
940 flowRule = DefaultFlowRule.builder()
941 .fromApp(appId)
942 .withSelector(selector)
943 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -0800944 .withPriority(LOW_PRIORITY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800945 .forDevice(deviceId)
946 .forTable(TABLE_IN_PORT)
947 .makePermanent()
948 .build();
949
950 processFlowRule(true, flowRule);
951 }
952
953 /**
954 * Populates direct VM access rules for ACCESS_TYPE table.
955 * These rules are installed to all devices.
956 *
957 * @param srcRange source ip range
958 * @param dstRange destination ip range
959 */
960 private void populateDirectAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange) {
961 TrafficSelector selector = DefaultTrafficSelector.builder()
962 .matchEthType(Ethernet.TYPE_IPV4)
963 .matchIPSrc(srcRange)
964 .matchIPDst(dstRange)
965 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -0800966
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800967 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
968 .transition(TABLE_DST_IP)
969 .build();
970
Hyunsun Moon98025542016-03-08 04:36:02 -0800971
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800972 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moonc71231d2015-12-16 20:53:23 -0800973 FlowRule flowRuleDirect = DefaultFlowRule.builder()
974 .fromApp(appId)
975 .withSelector(selector)
976 .withTreatment(treatment)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800977 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800978 .forDevice(deviceId)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800979 .forTable(TABLE_ACCESS_TYPE)
980 .makePermanent()
981 .build();
982
983 processFlowRule(true, flowRuleDirect);
Hyunsun Moonfae776d2016-03-08 18:07:52 -0800984 });
Hyunsun Moon81ab23b2016-02-01 23:00:56 -0800985 }
986
987 /**
988 * Populates drop rules that does not match any direct access rules but has
989 * destination to a different service network in ACCESS_TYPE table.
990 *
991 * @param dstRange destination ip range
992 */
993 private void populateServiceIsolationRule(Ip4Prefix dstRange) {
994 TrafficSelector selector = DefaultTrafficSelector.builder()
995 .matchEthType(Ethernet.TYPE_IPV4)
996 .matchIPDst(dstRange)
997 .build();
998
999 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1000 .drop()
1001 .build();
1002
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001003 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moon81ab23b2016-02-01 23:00:56 -08001004 FlowRule flowRuleDirect = DefaultFlowRule.builder()
1005 .fromApp(appId)
1006 .withSelector(selector)
1007 .withTreatment(treatment)
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001008 .withPriority(LOW_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001009 .forDevice(deviceId)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001010 .forTable(TABLE_ACCESS_TYPE)
1011 .makePermanent()
1012 .build();
1013
1014 processFlowRule(true, flowRuleDirect);
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001015 });
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001016 }
1017
1018 /**
1019 * Populates indirect service access rules for ACCESS_TYPE table.
1020 * These rules are installed to all devices.
1021 *
1022 * @param srcRange source range
1023 * @param serviceIp service ip
1024 * @param outGroups list of output group
1025 */
1026 private void populateIndirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
1027 Map<DeviceId, GroupId> outGroups) {
1028 TrafficSelector selector = DefaultTrafficSelector.builder()
1029 .matchEthType(Ethernet.TYPE_IPV4)
1030 .matchIPSrc(srcRange)
1031 .matchIPDst(serviceIp.toIpPrefix())
1032 .build();
1033
1034 for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
1035 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1036 .group(outGroup.getValue())
1037 .build();
1038
1039 FlowRule flowRule = DefaultFlowRule.builder()
1040 .fromApp(appId)
1041 .withSelector(selector)
1042 .withTreatment(treatment)
Hyunsun Moon81ab23b2016-02-01 23:00:56 -08001043 .withPriority(HIGH_PRIORITY)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001044 .forDevice(outGroup.getKey())
1045 .forTable(TABLE_ACCESS_TYPE)
1046 .makePermanent()
1047 .build();
1048
1049 processFlowRule(true, flowRule);
1050 }
1051 }
1052
1053 /**
1054 * Populates flow rules for IN_SERVICE table.
1055 *
1056 * @param inPorts list of inports related to the service for each device
1057 * @param outGroups set of output groups
1058 */
1059 private void populateInServiceRule(Map<DeviceId, Set<PortNumber>> inPorts, Map<DeviceId, GroupId> outGroups) {
1060 checkNotNull(inPorts);
1061 checkNotNull(outGroups);
1062
1063 for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
1064 Set<PortNumber> ports = entry.getValue();
1065 DeviceId deviceId = entry.getKey();
1066
1067 GroupId groupId = outGroups.get(deviceId);
1068 if (groupId == null) {
1069 continue;
1070 }
1071
1072 ports.stream().forEach(port -> {
1073 TrafficSelector selector = DefaultTrafficSelector.builder()
1074 .matchInPort(port)
1075 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001076
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001077 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1078 .group(groupId)
1079 .build();
1080
1081 FlowRule flowRule = DefaultFlowRule.builder()
1082 .fromApp(appId)
1083 .withSelector(selector)
1084 .withTreatment(treatment)
1085 .withPriority(DEFAULT_PRIORITY)
1086 .forDevice(deviceId)
1087 .forTable(TABLE_IN_SERVICE)
1088 .makePermanent()
1089 .build();
1090
1091 processFlowRule(true, flowRule);
1092 });
1093 }
1094 }
1095
1096 /**
1097 * Populates flow rules for DST_IP table.
1098 *
1099 * @param deviceId device id
1100 * @param inPort in port
1101 * @param dstMac mac address
1102 * @param dstIp destination ip
1103 * @param tunnelId tunnel id
1104 * @param tunnelIp tunnel remote ip
1105 */
1106 private void populateDstIpRule(DeviceId deviceId, PortNumber inPort, MacAddress dstMac,
1107 IpAddress dstIp, long tunnelId, IpAddress tunnelIp) {
1108 TrafficSelector selector = DefaultTrafficSelector.builder()
1109 .matchEthType(Ethernet.TYPE_IPV4)
1110 .matchIPDst(dstIp.toIpPrefix())
1111 .build();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001112
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001113 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1114 .setEthDst(dstMac)
1115 .setOutput(inPort)
1116 .build();
1117
1118 FlowRule flowRule = DefaultFlowRule.builder()
1119 .fromApp(appId)
1120 .withSelector(selector)
1121 .withTreatment(treatment)
1122 .withPriority(DEFAULT_PRIORITY)
1123 .forDevice(deviceId)
1124 .forTable(TABLE_DST_IP)
1125 .makePermanent()
1126 .build();
1127
1128 processFlowRule(true, flowRule);
1129
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001130 for (DeviceId vSwitchId : getVirtualSwitches()) {
1131 if (vSwitchId.equals(deviceId)) {
Hyunsun Moon98025542016-03-08 04:36:02 -08001132 continue;
1133 }
1134
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001135 ExtensionTreatment tunnelDst = getTunnelDst(vSwitchId, tunnelIp.getIp4Address());
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001136 if (tunnelDst == null) {
1137 continue;
1138 }
1139
1140 treatment = DefaultTrafficTreatment.builder()
1141 .setEthDst(dstMac)
1142 .setTunnelId(tunnelId)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001143 .extension(tunnelDst, vSwitchId)
1144 .setOutput(getTunnelPort(vSwitchId))
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001145 .build();
1146
1147 flowRule = DefaultFlowRule.builder()
1148 .fromApp(appId)
1149 .withSelector(selector)
1150 .withTreatment(treatment)
1151 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001152 .forDevice(vSwitchId)
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001153 .forTable(TABLE_DST_IP)
1154 .makePermanent()
1155 .build();
1156
1157 processFlowRule(true, flowRule);
1158 }
1159 }
1160
1161 /**
1162 * Populates flow rules for TUNNEL_ID table.
1163 *
1164 * @param deviceId device id
1165 * @param inPort in port
1166 * @param mac mac address
1167 * @param tunnelId tunnel id
1168 */
1169 private void populateTunnelInRule(DeviceId deviceId, PortNumber inPort, MacAddress mac, long tunnelId) {
1170 TrafficSelector selector = DefaultTrafficSelector.builder()
1171 .matchTunnelId(tunnelId)
1172 .matchEthDst(mac)
1173 .build();
1174
1175 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1176 .setOutput(inPort)
1177 .build();
1178
1179 FlowRule flowRule = DefaultFlowRule.builder()
1180 .fromApp(appId)
1181 .withSelector(selector)
1182 .withTreatment(treatment)
1183 .withPriority(DEFAULT_PRIORITY)
1184 .forDevice(deviceId)
1185 .forTable(TABLE_TUNNEL_IN)
1186 .makePermanent()
1187 .build();
1188
1189 processFlowRule(true, flowRule);
1190 }
1191
1192 /**
1193 * Installs or uninstall a given rule.
1194 *
1195 * @param install true to install, false to uninstall
1196 * @param rule rule
1197 */
1198 private void processFlowRule(boolean install, FlowRule rule) {
1199 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
1200 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
1201
1202 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
1203 @Override
1204 public void onError(FlowRuleOperations ops) {
1205 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
1206 }
1207 }));
1208 }
1209
1210 /**
1211 * Returns tunnel port of the device.
1212 *
1213 * @param deviceId device id
1214 * @return tunnel port number, or null if no tunnel port exists on a given device
1215 */
1216 private PortNumber getTunnelPort(DeviceId deviceId) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001217 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001218 .filter(p -> p.annotations().value(PORT_NAME).contains(tunnelType))
1219 .findFirst().orElse(null);
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001220
1221 return port == null ? null : port.number();
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001222 }
1223
1224 /**
Hyunsun Moon133fd792016-02-09 01:55:48 -08001225 * Returns data plane interface port name of a given device.
Hyunsun Moon4a915152016-01-14 16:56:26 -08001226 *
1227 * @param deviceId device id
Hyunsun Moon133fd792016-02-09 01:55:48 -08001228 * @param dpIntf data plane interface port name
1229 * @return data plane interface port number, or null if no such port exists
Hyunsun Moon4a915152016-01-14 16:56:26 -08001230 */
Hyunsun Moon133fd792016-02-09 01:55:48 -08001231 private PortNumber getDpPort(DeviceId deviceId, String dpIntf) {
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001232 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001233 .filter(p -> p.annotations().value(PORT_NAME).contains(dpIntf) &&
1234 p.isEnabled())
1235 .findFirst().orElse(null);
Hyunsun Moon5a4346f2016-01-15 11:41:14 -08001236
1237 return port == null ? null : port.number();
Hyunsun Moon4a915152016-01-14 16:56:26 -08001238 }
1239
Hyunsun Moon6d247342016-02-12 12:48:47 -08001240 /** Returns data plane interface port number of a given host.
1241 *
1242 * @param host host
1243 * @return port number, or null
1244 */
1245 private PortNumber getDpPort(Host host) {
1246 String portName = host.annotations().value(DATA_PLANE_INTF);
1247 return portName == null ? null : getDpPort(host.location().deviceId(), portName);
1248 }
1249
1250 /**
1251 * Returns service vlan from a given host.
1252 *
1253 * @param host host
1254 * @return vlan id, or null
1255 */
1256 private VlanId getServiceVlan(Host host) {
1257 String serviceVlan = host.annotations().value(S_TAG);
1258 return serviceVlan == null ? null : VlanId.vlanId(Short.parseShort(serviceVlan));
1259 }
1260
Hyunsun Moon4a915152016-01-14 16:56:26 -08001261 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001262 * Returns the inport from a given flow rule if the rule contains the match of it.
1263 *
1264 * @param flowRule flow rule
1265 * @return port number, or null if the rule doesn't have inport match
1266 */
1267 private PortNumber getInPort(FlowRule flowRule) {
1268 Criterion criterion = flowRule.selector().getCriterion(IN_PORT);
1269 if (criterion != null && criterion instanceof PortCriterion) {
1270 PortCriterion port = (PortCriterion) criterion;
1271 return port.port();
1272 } else {
1273 return null;
1274 }
1275 }
1276
1277 /**
1278 * Returns the destination mac address from a given flow rule if the rule
1279 * contains the instruction of it.
1280 *
1281 * @param flowRule flow rule
1282 * @return mac address, or null if the rule doesn't have destination mac instruction
1283 */
1284 private MacAddress getDstMacFromTreatment(FlowRule flowRule) {
1285 Instruction instruction = flowRule.treatment().allInstructions().stream()
1286 .filter(inst -> inst instanceof ModEtherInstruction &&
1287 ((ModEtherInstruction) inst).subtype().equals(ETH_DST))
1288 .findFirst()
1289 .orElse(null);
1290
1291 if (instruction == null) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001292 return null;
1293 }
1294
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001295 return ((ModEtherInstruction) instruction).mac();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001296 }
1297
1298 /**
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001299 * Returns the destination mac address from a given flow rule if the rule
1300 * contains the match of it.
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001301 *
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001302 * @param flowRule flow rule
1303 * @return mac address, or null if the rule doesn't have destination mac match
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001304 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001305 private MacAddress getDstMacFromSelector(FlowRule flowRule) {
1306 Criterion criterion = flowRule.selector().getCriterion(Criterion.Type.ETH_DST);
1307 if (criterion != null && criterion instanceof EthCriterion) {
1308 EthCriterion eth = (EthCriterion) criterion;
1309 return eth.mac();
1310 } else {
1311 return null;
1312 }
1313 }
1314
1315 /**
1316 * Returns the destination IP from a given flow rule if the rule contains
1317 * the match of it.
1318 *
1319 * @param flowRule flow rule
1320 * @return ip prefix, or null if the rule doesn't have ip match
1321 */
1322 private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
1323 Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
1324 if (criterion != null && criterion instanceof IPCriterion) {
1325 IPCriterion ip = (IPCriterion) criterion;
1326 return ip.ip();
1327 } else {
1328 return null;
1329 }
1330 }
1331
1332 /**
1333 * Returns the source IP from a given flow rule if the rule contains
1334 * the match of it.
1335 *
1336 * @param flowRule flow rule
1337 * @return ip prefix, or null if the rule doesn't have ip match
1338 */
1339 private IpPrefix getSrcIpFromSelector(FlowRule flowRule) {
1340 Criterion criterion = flowRule.selector().getCriterion(IPV4_SRC);
1341 if (criterion != null && criterion instanceof IPCriterion) {
1342 IPCriterion ip = (IPCriterion) criterion;
1343 return ip.ip();
1344 } else {
1345 return null;
1346 }
1347 }
1348
1349 /**
1350 * Returns the group ID from a given flow rule if the rule contains the
1351 * treatment of it.
1352 *
1353 * @param flowRule flow rule
1354 * @return group id, or null if the rule doesn't have group instruction
1355 */
1356 private GroupId getGroupIdFromTreatment(FlowRule flowRule) {
1357 Instruction instruction = flowRule.treatment().allInstructions().stream()
1358 .filter(inst -> inst instanceof Instructions.GroupInstruction)
1359 .findFirst()
1360 .orElse(null);
1361
1362 if (instruction == null) {
1363 return null;
1364 }
1365
1366 return ((Instructions.GroupInstruction) instruction).groupId();
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001367 }
1368
1369 /**
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001370 * Returns the output port number from a given flow rule.
1371 *
1372 * @param flowRule flow rule
1373 * @return port number, or null if the rule does not have output instruction
1374 */
1375 private PortNumber getOutputFromTreatment(FlowRule flowRule) {
1376 Instruction instruction = flowRule.treatment().allInstructions().stream()
Hyunsun Moon6d247342016-02-12 12:48:47 -08001377 .filter(inst -> inst instanceof Instructions.OutputInstruction)
Hyunsun Moond52bffc2016-01-29 18:57:05 -08001378 .findFirst()
1379 .orElse(null);
1380
1381 if (instruction == null) {
1382 return null;
1383 }
1384
1385 return ((Instructions.OutputInstruction) instruction).port();
1386 }
1387
1388 /**
Hyunsun Moon6d247342016-02-12 12:48:47 -08001389 * Returns if a given flow rule has vlan push instruction or not.
1390 *
1391 * @param flowRule flow rule
1392 * @return true if it includes vlan push, or false
1393 */
1394 private boolean isVlanPushFromTreatment(FlowRule flowRule) {
1395 Instruction instruction = flowRule.treatment().allInstructions().stream()
1396 .filter(inst -> inst instanceof L2ModificationInstruction)
1397 .filter(inst -> ((L2ModificationInstruction) inst).subtype().equals(VLAN_PUSH))
1398 .findAny()
1399 .orElse(null);
1400
1401 return instruction != null;
1402 }
1403
1404 /**
Hyunsun Moon4a915152016-01-14 16:56:26 -08001405 * Creates a new group for a given service.
1406 *
1407 * @param deviceId device id to create a group
1408 * @param service cord service
1409 * @return group id, or null if it fails to create
1410 */
1411 private GroupId createServiceGroup(DeviceId deviceId, CordService service) {
1412 checkNotNull(service);
1413
1414 GroupKey groupKey = getGroupKey(service.id());
1415 Group group = groupService.getGroup(deviceId, groupKey);
1416 GroupId groupId = getGroupId(service.id(), deviceId);
1417
1418 if (group != null) {
1419 log.debug("Group {} is already exist in {}", service.id(), deviceId);
1420 return groupId;
1421 }
1422
1423 GroupBuckets buckets = getServiceGroupBuckets(deviceId, service.segmentationId(), service.hosts());
1424 GroupDescription groupDescription = new DefaultGroupDescription(
1425 deviceId,
1426 GroupDescription.Type.SELECT,
1427 buckets,
1428 groupKey,
1429 groupId.id(),
1430 appId);
1431
1432 groupService.addGroup(groupDescription);
1433
1434 return groupId;
1435 }
1436
1437 /**
1438 * Returns group buckets for a given device.
1439 *
1440 * @param deviceId device id
1441 * @param tunnelId tunnel id
1442 * @param hosts list of host
1443 * @return group buckets
1444 */
1445 private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId, Map<Host, IpAddress> hosts) {
1446 List<GroupBucket> buckets = Lists.newArrayList();
1447
1448 for (Map.Entry<Host, IpAddress> entry : hosts.entrySet()) {
1449 Host host = entry.getKey();
1450 Ip4Address remoteIp = entry.getValue().getIp4Address();
1451 DeviceId hostDevice = host.location().deviceId();
1452
1453 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
1454 .builder()
1455 .setEthDst(host.mac());
1456
1457 if (deviceId.equals(hostDevice)) {
1458 tBuilder.setOutput(host.location().port());
1459 } else {
1460 ExtensionTreatment tunnelDst = getTunnelDst(deviceId, remoteIp);
1461 if (tunnelDst == null) {
1462 continue;
1463 }
1464
1465 tBuilder.extension(tunnelDst, deviceId)
1466 .setTunnelId(tunnelId)
1467 .setOutput(getTunnelPort(hostDevice));
1468 }
1469
1470 buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
1471 }
1472
1473 return new GroupBuckets(buckets);
1474 }
1475
1476 /**
1477 * Returns globally unique group ID.
1478 *
1479 * @param serviceId service id
1480 * @param deviceId device id
1481 * @return group id
1482 */
1483 private GroupId getGroupId(CordServiceId serviceId, DeviceId deviceId) {
1484 return new DefaultGroupId(Objects.hash(serviceId, deviceId));
1485 }
1486
1487 /**
1488 * Returns group key of a service.
1489 *
1490 * @param serviceId service id
1491 * @return group key
1492 */
1493 private GroupKey getGroupKey(CordServiceId serviceId) {
1494 return new DefaultGroupKey(serviceId.id().getBytes());
1495 }
1496
1497 /**
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001498 * Returns extension instruction to set tunnel destination.
1499 *
1500 * @param deviceId device id
1501 * @param remoteIp tunnel destination address
1502 * @return extension treatment or null if it fails to get instruction
1503 */
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001504 private ExtensionTreatment getTunnelDst(DeviceId deviceId, Ip4Address remoteIp) {
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001505 try {
1506 Driver driver = driverService.getDriver(deviceId);
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001507 DefaultDriverData driverData = new DefaultDriverData(driver, deviceId);
1508 DriverHandler handler = new DefaultDriverHandler(driverData);
1509 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001510
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001511 ExtensionTreatment treatment =
1512 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001513 treatment.setPropertyValue("tunnelDst", remoteIp);
1514
1515 return treatment;
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001516 } catch (ItemNotFoundException | UnsupportedOperationException |
1517 ExtensionPropertyException e) {
1518 log.error("Failed to get extension instruction {}", deviceId);
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001519 return null;
1520 }
1521 }
Hyunsun Moonfae776d2016-03-08 18:07:52 -08001522
1523 /**
1524 * Returns integration bridges configured in the system.
1525 *
1526 * @return set of device ids
1527 */
1528 private Set<DeviceId> getVirtualSwitches() {
1529 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
1530 if (config == null) {
1531 log.debug("No configuration found for {}", appId.name());
1532 return Sets.newHashSet();
1533 }
1534
1535 return config.cordVtnNodes().stream()
1536 .map(CordVtnNode::intBrId).collect(Collectors.toSet());
1537 }
Hyunsun Moon9f0814b2015-11-04 17:34:35 -08001538}
Hyunsun Moonc71231d2015-12-16 20:53:23 -08001539