blob: 49f3c8f1aa39de6678a710b457858023c8ad4b5f [file] [log] [blame]
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001/*
Brian O'Connor8e57fd52016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Hyunsun Moon05f528a2015-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 Moonf9480202016-04-14 16:13:42 -070016package org.onosproject.cordvtn.impl;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080017
Hyunsun Moonba290072015-12-16 20:53:23 -080018import com.google.common.collect.Lists;
19import com.google.common.collect.Maps;
Hyunsun Moon7a9bb122016-03-08 18:07:52 -080020import com.google.common.collect.Sets;
Hyunsun Moonba290072015-12-16 20:53:23 -080021import org.onlab.packet.Ethernet;
Hyunsun Moon3467a262016-01-14 16:56:26 -080022import org.onlab.packet.IPv4;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080023import org.onlab.packet.Ip4Address;
Hyunsun Moonba290072015-12-16 20:53:23 -080024import org.onlab.packet.Ip4Prefix;
25import org.onlab.packet.IpAddress;
26import org.onlab.packet.IpPrefix;
27import org.onlab.packet.MacAddress;
Hyunsun Moon3467a262016-01-14 16:56:26 -080028import org.onlab.packet.TpPort;
Hyunsun Moon01556a52016-02-12 12:48:47 -080029import org.onlab.packet.VlanId;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080030import org.onlab.util.ItemNotFoundException;
Hyunsun Moonf9480202016-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 Moon05f528a2015-11-04 17:34:35 -080035import org.onosproject.core.ApplicationId;
Hyunsun Moonba290072015-12-16 20:53:23 -080036import org.onosproject.core.DefaultGroupId;
37import org.onosproject.core.GroupId;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080038import org.onosproject.net.DeviceId;
Hyunsun Moonba290072015-12-16 20:53:23 -080039import org.onosproject.net.Host;
Hyunsun Moon2bf68e72016-01-15 11:41:14 -080040import org.onosproject.net.Port;
Hyunsun Moonba290072015-12-16 20:53:23 -080041import org.onosproject.net.PortNumber;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080042import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
Hyunsun Moon7a9bb122016-03-08 18:07:52 -080043import org.onosproject.net.config.NetworkConfigRegistry;
Hyunsun Moonba290072015-12-16 20:53:23 -080044import org.onosproject.net.device.DeviceService;
Hyunsun Moon05f528a2015-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 Moonba290072015-12-16 20:53:23 -080050import org.onosproject.net.flow.DefaultFlowRule;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080051import org.onosproject.net.flow.DefaultTrafficSelector;
52import org.onosproject.net.flow.DefaultTrafficTreatment;
Hyunsun Moonba290072015-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 Moon05f528a2015-11-04 17:34:35 -080057import org.onosproject.net.flow.TrafficSelector;
58import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moonba290072015-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 Moon05f528a2015-11-04 17:34:35 -080063import org.onosproject.net.flow.instructions.ExtensionPropertyException;
64import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moonba290072015-12-16 20:53:23 -080065import org.onosproject.net.flow.instructions.Instruction;
66import org.onosproject.net.flow.instructions.Instructions;
Hyunsun Moon01556a52016-02-12 12:48:47 -080067import org.onosproject.net.flow.instructions.L2ModificationInstruction;
Hyunsun Moonba290072015-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;
Hyunsun Moon61e79ee2016-04-14 19:04:23 -070078import org.openstack4j.model.network.Network;
79import org.openstack4j.model.network.Subnet;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080080import org.slf4j.Logger;
81
Hyunsun Moonee37c442016-01-07 01:32:31 -080082import java.util.ArrayList;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080083import java.util.List;
Hyunsun Moonba290072015-12-16 20:53:23 -080084import java.util.Map;
Hyunsun Moonba290072015-12-16 20:53:23 -080085import java.util.Objects;
86import java.util.Set;
87import java.util.stream.Collectors;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080088
Hyunsun Moon05f528a2015-11-04 17:34:35 -080089import static com.google.common.base.Preconditions.checkNotNull;
Hyunsun Moonba290072015-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 Moon05f528a2015-11-04 17:34:35 -080093import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
Hyunsun Moonba290072015-12-16 20:53:23 -080094import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
Hyunsun Moon01556a52016-02-12 12:48:47 -080095import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
Hyunsun Moon05f528a2015-11-04 17:34:35 -080096import static org.slf4j.LoggerFactory.getLogger;
97
98/**
Hyunsun Moonba290072015-12-16 20:53:23 -080099 * Populates rules for CORD VTN service.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800100 */
Hyunsun Moonba290072015-12-16 20:53:23 -0800101public class CordVtnRuleInstaller {
102
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800103 protected final Logger log = getLogger(getClass());
104
Hyunsun Moon3467a262016-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 Moon01556a52016-02-12 12:48:47 -0800111 private static final int TABLE_Q_IN_Q = 6;
Hyunsun Moonba290072015-12-16 20:53:23 -0800112
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800113 private static final int MANAGEMENT_PRIORITY = 55000;
Hyunsun Moon01556a52016-02-12 12:48:47 -0800114 private static final int VSG_PRIORITY = 55000;
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800115 private static final int HIGH_PRIORITY = 50000;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800116 private static final int DEFAULT_PRIORITY = 5000;
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800117 private static final int LOW_PRIORITY = 4000;
Hyunsun Moonba290072015-12-16 20:53:23 -0800118 private static final int LOWEST_PRIORITY = 0;
Hyunsun Moon3467a262016-01-14 16:56:26 -0800119
120 private static final int VXLAN_UDP_PORT = 4789;
Hyunsun Moon01556a52016-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 Moon05f528a2015-11-04 17:34:35 -0800126
127 private final ApplicationId appId;
Hyunsun Moonba290072015-12-16 20:53:23 -0800128 private final FlowRuleService flowRuleService;
129 private final DeviceService deviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800130 private final DriverService driverService;
Hyunsun Moonba290072015-12-16 20:53:23 -0800131 private final GroupService groupService;
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800132 private final NetworkConfigRegistry configRegistry;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800133 private final String tunnelType;
134
135 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800136 * Creates a new rule populator.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800137 *
138 * @param appId application id
Hyunsun Moonba290072015-12-16 20:53:23 -0800139 * @param flowRuleService flow rule service
140 * @param deviceService device service
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800141 * @param driverService driver service
Jian Li248e9202016-01-22 16:46:58 -0800142 * @param groupService group service
Ray Milkey6b6680b2016-04-05 17:39:44 -0700143 * @param configRegistry config registry
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800144 * @param tunnelType tunnel type
145 */
146 public CordVtnRuleInstaller(ApplicationId appId,
Hyunsun Moonba290072015-12-16 20:53:23 -0800147 FlowRuleService flowRuleService,
148 DeviceService deviceService,
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800149 DriverService driverService,
Hyunsun Moonba290072015-12-16 20:53:23 -0800150 GroupService groupService,
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800151 NetworkConfigRegistry configRegistry,
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800152 String tunnelType) {
153 this.appId = appId;
Hyunsun Moonba290072015-12-16 20:53:23 -0800154 this.flowRuleService = flowRuleService;
155 this.deviceService = deviceService;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800156 this.driverService = driverService;
Hyunsun Moonba290072015-12-16 20:53:23 -0800157 this.groupService = groupService;
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800158 this.configRegistry = configRegistry;
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800159 this.tunnelType = checkNotNull(tunnelType);
160 }
161
162 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800163 * Installs table miss rule to a give device.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800164 *
Hyunsun Moonba290072015-12-16 20:53:23 -0800165 * @param deviceId device id to install the rules
Hyunsun Moon126171d2016-02-09 01:55:48 -0800166 * @param dpIntf data plane interface name
167 * @param dpIp data plane ip address
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800168 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800169 public void init(DeviceId deviceId, String dpIntf, IpAddress dpIp) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800170 // default is drop packets which can be accomplished without
171 // a table miss entry for all table.
Hyunsun Moon3467a262016-01-14 16:56:26 -0800172 PortNumber tunnelPort = getTunnelPort(deviceId);
Hyunsun Moon126171d2016-02-09 01:55:48 -0800173 PortNumber dpPort = getDpPort(deviceId, dpIntf);
Hyunsun Moon3467a262016-01-14 16:56:26 -0800174
Hyunsun Moon126171d2016-02-09 01:55:48 -0800175 processFirstTable(deviceId, dpPort, dpIp);
176 processInPortTable(deviceId, tunnelPort, dpPort);
177 processAccessTypeTable(deviceId, dpPort);
Hyunsun Moon01556a52016-02-12 12:48:47 -0800178 processQInQTable(deviceId, dpPort);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800179 }
180
181 /**
Hyunsun Mooncbc885f2016-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 Moonba290072015-12-16 20:53:23 -0800189 * Populates basic rules that connect a VM to the other VMs in the system.
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800190 *
Hyunsun Moonba290072015-12-16 20:53:23 -0800191 * @param host host
Hyunsun Moonba290072015-12-16 20:53:23 -0800192 * @param tunnelIp tunnel ip
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700193 * @param osNet openstack network
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800194 */
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700195 public void populateBasicConnectionRules(Host host, IpAddress tunnelIp, Network osNet) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800196 checkNotNull(host);
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700197 checkNotNull(osNet);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800198
Hyunsun Moonba290072015-12-16 20:53:23 -0800199 DeviceId deviceId = host.location().deviceId();
Hyunsun Moonba290072015-12-16 20:53:23 -0800200 PortNumber inPort = host.location().port();
201 MacAddress dstMac = host.mac();
Hyunsun Mooncb799442016-01-15 20:03:18 -0800202 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700203 long tunnelId = Long.parseLong(osNet.getProviderSegID());
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800204
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700205 Subnet osSubnet = osNet.getNeutronSubnets().stream()
Hyunsun Moonba290072015-12-16 20:53:23 -0800206 .findFirst()
207 .orElse(null);
208
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700209 if (osSubnet == null) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800210 log.error("Failed to get subnet for {}", host.id());
211 return;
212 }
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700213 Ip4Prefix cidr = Ip4Prefix.valueOf(osSubnet.getCidr());
Hyunsun Moonba290072015-12-16 20:53:23 -0800214
215 populateLocalInPortRule(deviceId, inPort, hostIp);
Hyunsun Moon61e79ee2016-04-14 19:04:23 -0700216 populateDirectAccessRule(cidr, cidr);
217 populateServiceIsolationRule(cidr);
Hyunsun Moonba290072015-12-16 20:53:23 -0800218 populateDstIpRule(deviceId, inPort, dstMac, hostIp, tunnelId, tunnelIp);
219 populateTunnelInRule(deviceId, inPort, dstMac, tunnelId);
Hyunsun Moon05f528a2015-11-04 17:34:35 -0800220 }
221
222 /**
Hyunsun Moon703a0912016-02-18 15:37:22 -0800223 * Removes all rules related to a given service VM host.
Hyunsun Moonba290072015-12-16 20:53:23 -0800224 *
225 * @param host host to be removed
226 */
227 public void removeBasicConnectionRules(Host host) {
228 checkNotNull(host);
229
230 DeviceId deviceId = host.location().deviceId();
231 MacAddress mac = host.mac();
232 PortNumber port = host.location().port();
233 IpAddress ip = host.ipAddresses().stream().findFirst().orElse(null);
234
Hyunsun Moonba290072015-12-16 20:53:23 -0800235 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
236 if (flowRule.deviceId().equals(deviceId)) {
237 PortNumber inPort = getInPort(flowRule);
238 if (inPort != null && inPort.equals(port)) {
239 processFlowRule(false, flowRule);
240 continue;
241 }
Hyunsun Moon703a0912016-02-18 15:37:22 -0800242
243 PortNumber output = getOutputFromTreatment(flowRule);
244 if (output != null && output.equals(host.location().port())) {
245 processFlowRule(false, flowRule);
246 }
Hyunsun Moonba290072015-12-16 20:53:23 -0800247 }
248
249 MacAddress dstMac = getDstMacFromTreatment(flowRule);
250 if (dstMac != null && dstMac.equals(mac)) {
251 processFlowRule(false, flowRule);
252 continue;
253 }
254
255 dstMac = getDstMacFromSelector(flowRule);
256 if (dstMac != null && dstMac.equals(mac)) {
257 processFlowRule(false, flowRule);
258 continue;
259 }
260
261 IpPrefix dstIp = getDstIpFromSelector(flowRule);
262 if (dstIp != null && dstIp.equals(ip.toIpPrefix())) {
263 processFlowRule(false, flowRule);
264 }
Hyunsun Moonba290072015-12-16 20:53:23 -0800265 }
266
267 // TODO uninstall same network access rule in access table if no vm exists in the network
268 }
269
270 /**
Hyunsun Moonee37c442016-01-07 01:32:31 -0800271 * Populates service dependency rules.
272 *
273 * @param tService tenant cord service
274 * @param pService provider cord service
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800275 * @param isBidirectional true to enable bidirectional connection between two services
Hyunsun Moonee37c442016-01-07 01:32:31 -0800276 */
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800277 public void populateServiceDependencyRules(CordService tService, CordService pService,
278 boolean isBidirectional) {
Hyunsun Moonee37c442016-01-07 01:32:31 -0800279 checkNotNull(tService);
280 checkNotNull(pService);
281
282 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
283 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
284 Ip4Address serviceIp = pService.serviceIp().getIp4Address();
285
286 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
287 Map<DeviceId, Set<PortNumber>> inPorts = Maps.newHashMap();
288
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800289 getVirtualSwitches().stream().forEach(deviceId -> {
290 GroupId groupId = createServiceGroup(deviceId, pService);
291 outGroups.put(deviceId, groupId);
Hyunsun Moonee37c442016-01-07 01:32:31 -0800292
293 Set<PortNumber> vms = tService.hosts().keySet()
294 .stream()
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800295 .filter(host -> host.location().deviceId().equals(deviceId))
Hyunsun Moonee37c442016-01-07 01:32:31 -0800296 .map(host -> host.location().port())
297 .collect(Collectors.toSet());
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800298 inPorts.put(deviceId, vms);
299 });
Hyunsun Moonee37c442016-01-07 01:32:31 -0800300
301 populateIndirectAccessRule(srcRange, serviceIp, outGroups);
302 populateDirectAccessRule(srcRange, dstRange);
Hyunsun Moon5f7ed8a2016-02-10 17:02:37 -0800303 if (isBidirectional) {
304 populateDirectAccessRule(dstRange, srcRange);
305 }
Hyunsun Moonee37c442016-01-07 01:32:31 -0800306 populateInServiceRule(inPorts, outGroups);
307 }
308
309 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800310 * Removes service dependency rules.
311 *
312 * @param tService tenant cord service
313 * @param pService provider cord service
314 */
315 public void removeServiceDependencyRules(CordService tService, CordService pService) {
316 checkNotNull(tService);
317 checkNotNull(pService);
318
319 Ip4Prefix srcRange = tService.serviceIpRange().getIp4Prefix();
320 Ip4Prefix dstRange = pService.serviceIpRange().getIp4Prefix();
321 IpPrefix serviceIp = pService.serviceIp().toIpPrefix();
322
323 Map<DeviceId, GroupId> outGroups = Maps.newHashMap();
324 GroupKey groupKey = new DefaultGroupKey(pService.id().id().getBytes());
325
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800326 getVirtualSwitches().stream().forEach(deviceId -> {
327 Group group = groupService.getGroup(deviceId, groupKey);
Hyunsun Moonba290072015-12-16 20:53:23 -0800328 if (group != null) {
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800329 outGroups.put(deviceId, group.id());
Hyunsun Moonba290072015-12-16 20:53:23 -0800330 }
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800331 });
Hyunsun Moonba290072015-12-16 20:53:23 -0800332
333 for (FlowRule flowRule : flowRuleService.getFlowRulesById(appId)) {
334 IpPrefix dstIp = getDstIpFromSelector(flowRule);
335 IpPrefix srcIp = getSrcIpFromSelector(flowRule);
336
337 if (dstIp != null && dstIp.equals(serviceIp)) {
338 processFlowRule(false, flowRule);
339 continue;
340 }
341
342 if (dstIp != null && srcIp != null) {
343 if (dstIp.equals(dstRange) && srcIp.equals(srcRange)) {
344 processFlowRule(false, flowRule);
345 continue;
346 }
347
348 if (dstIp.equals(srcRange) && srcIp.equals(dstRange)) {
349 processFlowRule(false, flowRule);
350 continue;
351 }
352 }
353
354 GroupId groupId = getGroupIdFromTreatment(flowRule);
355 if (groupId != null && groupId.equals(outGroups.get(flowRule.deviceId()))) {
356 processFlowRule(false, flowRule);
357 }
358 }
359
360 // TODO remove the group if it is not in use
361 }
362
363 /**
Hyunsun Moonee37c442016-01-07 01:32:31 -0800364 * Updates group buckets for a given service to all devices.
365 *
366 * @param service cord service
367 */
368 public void updateServiceGroup(CordService service) {
369 checkNotNull(service);
370
371 GroupKey groupKey = getGroupKey(service.id());
372
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800373 for (DeviceId deviceId : getVirtualSwitches()) {
Hyunsun Moonee37c442016-01-07 01:32:31 -0800374 Group group = groupService.getGroup(deviceId, groupKey);
375 if (group == null) {
Hyunsun Mooncb799442016-01-15 20:03:18 -0800376 log.trace("No group exists for service {} in {}, do nothing.", service.id(), deviceId);
Hyunsun Moonee37c442016-01-07 01:32:31 -0800377 continue;
378 }
379
380 List<GroupBucket> oldBuckets = group.buckets().buckets();
381 List<GroupBucket> newBuckets = getServiceGroupBuckets(
382 deviceId, service.segmentationId(), service.hosts()).buckets();
383
384 if (oldBuckets.equals(newBuckets)) {
385 continue;
386 }
387
388 List<GroupBucket> bucketsToRemove = new ArrayList<>(oldBuckets);
389 bucketsToRemove.removeAll(newBuckets);
390 if (!bucketsToRemove.isEmpty()) {
391 groupService.removeBucketsFromGroup(
392 deviceId,
393 groupKey,
394 new GroupBuckets(bucketsToRemove),
395 groupKey, appId);
396 }
397
398 List<GroupBucket> bucketsToAdd = new ArrayList<>(newBuckets);
399 bucketsToAdd.removeAll(oldBuckets);
400 if (!bucketsToAdd.isEmpty()) {
401 groupService.addBucketsToGroup(
402 deviceId,
403 groupKey,
404 new GroupBuckets(bucketsToAdd),
405 groupKey, appId);
406 }
407 }
408 }
409
410 /**
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800411 * Populates flow rules for management network access.
412 *
413 * @param host host which has management network interface
414 * @param mService management network service
415 */
416 public void populateManagementNetworkRules(Host host, CordService mService) {
417 checkNotNull(mService);
418
419 DeviceId deviceId = host.location().deviceId();
420 IpAddress hostIp = host.ipAddresses().stream().findFirst().get();
421
422 TrafficSelector selector = DefaultTrafficSelector.builder()
423 .matchEthType(Ethernet.TYPE_ARP)
424 .matchArpTpa(mService.serviceIp().getIp4Address())
425 .build();
426
427 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
428 .setOutput(PortNumber.LOCAL)
429 .build();
430
431 FlowRule flowRule = DefaultFlowRule.builder()
432 .fromApp(appId)
433 .withSelector(selector)
434 .withTreatment(treatment)
435 .withPriority(MANAGEMENT_PRIORITY)
436 .forDevice(deviceId)
437 .forTable(TABLE_FIRST)
438 .makePermanent()
439 .build();
440
441 processFlowRule(true, flowRule);
442
443 selector = DefaultTrafficSelector.builder()
444 .matchInPort(PortNumber.LOCAL)
445 .matchEthType(Ethernet.TYPE_ARP)
446 .matchArpTpa(hostIp.getIp4Address())
447 .build();
448
449 treatment = DefaultTrafficTreatment.builder()
450 .setOutput(host.location().port())
451 .build();
452
453 flowRule = DefaultFlowRule.builder()
454 .fromApp(appId)
455 .withSelector(selector)
456 .withTreatment(treatment)
457 .withPriority(MANAGEMENT_PRIORITY)
458 .forDevice(deviceId)
459 .forTable(TABLE_FIRST)
460 .makePermanent()
461 .build();
462
463 processFlowRule(true, flowRule);
464
465 selector = DefaultTrafficSelector.builder()
466 .matchInPort(PortNumber.LOCAL)
467 .matchEthType(Ethernet.TYPE_IPV4)
468 .matchIPDst(mService.serviceIpRange())
469 .build();
470
471 treatment = DefaultTrafficTreatment.builder()
472 .transition(TABLE_DST_IP)
473 .build();
474
475 flowRule = DefaultFlowRule.builder()
476 .fromApp(appId)
477 .withSelector(selector)
478 .withTreatment(treatment)
479 .withPriority(MANAGEMENT_PRIORITY)
480 .forDevice(deviceId)
481 .forTable(TABLE_FIRST)
482 .makePermanent()
483 .build();
484
485 processFlowRule(true, flowRule);
486
487 selector = DefaultTrafficSelector.builder()
488 .matchEthType(Ethernet.TYPE_IPV4)
489 .matchIPDst(mService.serviceIp().toIpPrefix())
490 .build();
491
492 treatment = DefaultTrafficTreatment.builder()
493 .setOutput(PortNumber.LOCAL)
494 .build();
495
496 flowRule = DefaultFlowRule.builder()
497 .fromApp(appId)
498 .withSelector(selector)
499 .withTreatment(treatment)
500 .withPriority(MANAGEMENT_PRIORITY)
501 .forDevice(deviceId)
502 .forTable(TABLE_ACCESS_TYPE)
503 .makePermanent()
504 .build();
505
506 processFlowRule(true, flowRule);
507 }
508
509 /**
510 * Removes management network access rules.
511 *
512 * @param host host to be removed
513 * @param mService service for management network
514 */
515 public void removeManagementNetworkRules(Host host, CordService mService) {
516 checkNotNull(mService);
Hyunsun Moon703a0912016-02-18 15:37:22 -0800517 // TODO remove management network specific rules
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800518 }
519
520 /**
Hyunsun Moon01556a52016-02-12 12:48:47 -0800521 * Populates rules for vSG VM.
522 *
523 * @param vSgHost vSG host
524 * @param vSgIps set of ip addresses of vSGs running inside the vSG VM
525 */
526 public void populateSubscriberGatewayRules(Host vSgHost, Set<IpAddress> vSgIps) {
527 VlanId serviceVlan = getServiceVlan(vSgHost);
528 PortNumber dpPort = getDpPort(vSgHost);
529
530 if (serviceVlan == null || dpPort == null) {
531 log.warn("Failed to populate rules for vSG VM {}", vSgHost.id());
532 return;
533 }
534
535 // for traffics with s-tag, strip the tag and take through the vSG VM
536 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon703a0912016-02-18 15:37:22 -0800537 .matchInPort(dpPort)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800538 .matchVlanId(serviceVlan)
539 .build();
540
541 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon01556a52016-02-12 12:48:47 -0800542 .setOutput(vSgHost.location().port())
543 .build();
544
545 FlowRule flowRule = DefaultFlowRule.builder()
546 .fromApp(appId)
547 .withSelector(selector)
548 .withTreatment(treatment)
549 .withPriority(DEFAULT_PRIORITY)
550 .forDevice(vSgHost.location().deviceId())
551 .forTable(TABLE_Q_IN_Q)
552 .makePermanent()
553 .build();
554
555 processFlowRule(true, flowRule);
556
557 // for traffics with customer vlan, tag with the service vlan based on input port with
558 // lower priority to avoid conflict with WAN tag
559 selector = DefaultTrafficSelector.builder()
560 .matchInPort(vSgHost.location().port())
Hyunsun Moon703a0912016-02-18 15:37:22 -0800561 .matchVlanId(serviceVlan)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800562 .build();
563
564 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon01556a52016-02-12 12:48:47 -0800565 .setOutput(dpPort)
566 .build();
567
568 flowRule = DefaultFlowRule.builder()
569 .fromApp(appId)
570 .withSelector(selector)
571 .withTreatment(treatment)
Hyunsun Moon703a0912016-02-18 15:37:22 -0800572 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800573 .forDevice(vSgHost.location().deviceId())
574 .forTable(TABLE_Q_IN_Q)
575 .makePermanent()
576 .build();
577
578 processFlowRule(true, flowRule);
579
580 // for traffic coming from WAN, tag 500 and take through the vSG VM
581 // based on destination ip
582 vSgIps.stream().forEach(ip -> {
583 TrafficSelector downstream = DefaultTrafficSelector.builder()
584 .matchEthType(Ethernet.TYPE_IPV4)
585 .matchIPDst(ip.toIpPrefix())
586 .build();
587
588 TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
589 .pushVlan()
590 .setVlanId(VLAN_WAN)
591 .setEthDst(vSgHost.mac())
592 .setOutput(vSgHost.location().port())
593 .build();
594
595 FlowRule downstreamFlowRule = DefaultFlowRule.builder()
596 .fromApp(appId)
597 .withSelector(downstream)
598 .withTreatment(downstreamTreatment)
599 .withPriority(DEFAULT_PRIORITY)
600 .forDevice(vSgHost.location().deviceId())
601 .forTable(TABLE_DST_IP)
602 .makePermanent()
603 .build();
604
605 processFlowRule(true, downstreamFlowRule);
606 });
607
608 // remove downstream flow rules for the vSG not shown in vSgIps
609 for (FlowRule rule : flowRuleService.getFlowRulesById(appId)) {
610 if (!rule.deviceId().equals(vSgHost.location().deviceId())) {
611 continue;
612 }
613 PortNumber output = getOutputFromTreatment(rule);
614 if (output == null || !output.equals(vSgHost.location().port()) ||
615 !isVlanPushFromTreatment(rule)) {
616 continue;
617 }
618
619 IpPrefix dstIp = getDstIpFromSelector(rule);
620 if (dstIp != null && !vSgIps.contains(dstIp.address())) {
621 processFlowRule(false, rule);
622 }
623 }
624 }
625
626 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800627 * Populates default rules on the first table.
Hyunsun Moon126171d2016-02-09 01:55:48 -0800628 * It includes the rules for shuttling vxlan-encapped packets between ovs and
629 * linux stack,and external network connectivity.
Hyunsun Moonba290072015-12-16 20:53:23 -0800630 *
631 * @param deviceId device id
Hyunsun Moon126171d2016-02-09 01:55:48 -0800632 * @param dpPort data plane interface port number
633 * @param dpIp data plane ip address
Hyunsun Moonba290072015-12-16 20:53:23 -0800634 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800635 private void processFirstTable(DeviceId deviceId, PortNumber dpPort, IpAddress dpIp) {
Hyunsun Moon3467a262016-01-14 16:56:26 -0800636 // take vxlan packet out onto the physical port
637 TrafficSelector selector = DefaultTrafficSelector.builder()
638 .matchInPort(PortNumber.LOCAL)
639 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800640
Hyunsun Moon3467a262016-01-14 16:56:26 -0800641 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800642 .setOutput(dpPort)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800643 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800644
Hyunsun Moon3467a262016-01-14 16:56:26 -0800645 FlowRule flowRule = DefaultFlowRule.builder()
646 .fromApp(appId)
647 .withSelector(selector)
648 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800649 .withPriority(HIGH_PRIORITY)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800650 .forDevice(deviceId)
651 .forTable(TABLE_FIRST)
652 .makePermanent()
653 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800654
Hyunsun Moon3467a262016-01-14 16:56:26 -0800655 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800656
Hyunsun Moon3467a262016-01-14 16:56:26 -0800657 // take a vxlan encap'd packet through the Linux stack
658 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800659 .matchInPort(dpPort)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800660 .matchEthType(Ethernet.TYPE_IPV4)
661 .matchIPProtocol(IPv4.PROTOCOL_UDP)
662 .matchUdpDst(TpPort.tpPort(VXLAN_UDP_PORT))
663 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800664
Hyunsun Moon3467a262016-01-14 16:56:26 -0800665 treatment = DefaultTrafficTreatment.builder()
666 .setOutput(PortNumber.LOCAL)
667 .build();
Hyunsun Moonba290072015-12-16 20:53:23 -0800668
Hyunsun Moon3467a262016-01-14 16:56:26 -0800669 flowRule = DefaultFlowRule.builder()
670 .fromApp(appId)
671 .withSelector(selector)
672 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800673 .withPriority(HIGH_PRIORITY)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800674 .forDevice(deviceId)
675 .forTable(TABLE_FIRST)
676 .makePermanent()
677 .build();
678
679 processFlowRule(true, flowRule);
680
Hyunsun Moon126171d2016-02-09 01:55:48 -0800681 // take a packet to the data plane ip through Linux stack
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800682 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800683 .matchInPort(dpPort)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800684 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon126171d2016-02-09 01:55:48 -0800685 .matchIPDst(dpIp.toIpPrefix())
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800686 .build();
687
688 treatment = DefaultTrafficTreatment.builder()
689 .setOutput(PortNumber.LOCAL)
690 .build();
691
692 flowRule = DefaultFlowRule.builder()
693 .fromApp(appId)
694 .withSelector(selector)
695 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800696 .withPriority(HIGH_PRIORITY)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800697 .forDevice(deviceId)
698 .forTable(TABLE_FIRST)
699 .makePermanent()
700 .build();
701
702 processFlowRule(true, flowRule);
703
704 // take an arp packet from physical through Linux stack
705 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800706 .matchInPort(dpPort)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800707 .matchEthType(Ethernet.TYPE_ARP)
Hyunsun Moon01556a52016-02-12 12:48:47 -0800708 .matchArpTpa(dpIp.getIp4Address())
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800709 .build();
710
711 treatment = DefaultTrafficTreatment.builder()
712 .setOutput(PortNumber.LOCAL)
713 .build();
714
715 flowRule = DefaultFlowRule.builder()
716 .fromApp(appId)
717 .withSelector(selector)
718 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800719 .withPriority(HIGH_PRIORITY)
Hyunsun Moon6dbd34b2016-01-15 20:11:41 -0800720 .forDevice(deviceId)
721 .forTable(TABLE_FIRST)
722 .makePermanent()
723 .build();
724
725 processFlowRule(true, flowRule);
726
Hyunsun Moon3467a262016-01-14 16:56:26 -0800727 // take all else to the next table
728 selector = DefaultTrafficSelector.builder()
729 .build();
730
731 treatment = DefaultTrafficTreatment.builder()
732 .transition(TABLE_IN_PORT)
733 .build();
734
735 flowRule = DefaultFlowRule.builder()
736 .fromApp(appId)
737 .withSelector(selector)
738 .withTreatment(treatment)
739 .withPriority(LOWEST_PRIORITY)
740 .forDevice(deviceId)
741 .forTable(TABLE_FIRST)
742 .makePermanent()
743 .build();
744
745 processFlowRule(true, flowRule);
Hyunsun Moon01556a52016-02-12 12:48:47 -0800746
747 // take all vlan tagged packet to the Q_IN_Q table
748 selector = DefaultTrafficSelector.builder()
749 .matchVlanId(VlanId.ANY)
750 .build();
751
752 treatment = DefaultTrafficTreatment.builder()
753 .transition(TABLE_Q_IN_Q)
754 .build();
755
756 flowRule = DefaultFlowRule.builder()
757 .fromApp(appId)
758 .withSelector(selector)
759 .withTreatment(treatment)
760 .withPriority(VSG_PRIORITY)
761 .forDevice(deviceId)
762 .forTable(TABLE_FIRST)
763 .makePermanent()
764 .build();
765
766 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800767 }
768
769 /**
Hyunsun Moon126171d2016-02-09 01:55:48 -0800770 * Forward table miss packets in ACCESS_TYPE table to data plane port.
Hyunsun Moonba290072015-12-16 20:53:23 -0800771 *
772 * @param deviceId device id
Hyunsun Moon126171d2016-02-09 01:55:48 -0800773 * @param dpPort data plane interface port number
Hyunsun Moonba290072015-12-16 20:53:23 -0800774 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800775 private void processAccessTypeTable(DeviceId deviceId, PortNumber dpPort) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800776 TrafficSelector selector = DefaultTrafficSelector.builder()
777 .build();
778
779 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800780 .setOutput(dpPort)
Hyunsun Moonba290072015-12-16 20:53:23 -0800781 .build();
782
783 FlowRule flowRule = DefaultFlowRule.builder()
784 .fromApp(appId)
785 .withSelector(selector)
786 .withTreatment(treatment)
787 .withPriority(LOWEST_PRIORITY)
788 .forDevice(deviceId)
789 .forTable(TABLE_ACCESS_TYPE)
790 .makePermanent()
791 .build();
792
793 processFlowRule(true, flowRule);
794 }
795
796 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -0800797 * Populates default rules for IN_PORT table.
798 * All packets from tunnel port are forwarded to TUNNEL_ID table and all packets
Hyunsun Moon126171d2016-02-09 01:55:48 -0800799 * from data plane interface port to ACCESS_TYPE table.
Hyunsun Moonba290072015-12-16 20:53:23 -0800800 *
801 * @param deviceId device id to install the rules
Hyunsun Moon3467a262016-01-14 16:56:26 -0800802 * @param tunnelPort tunnel port number
Hyunsun Moon126171d2016-02-09 01:55:48 -0800803 * @param dpPort data plane interface port number
Hyunsun Moonba290072015-12-16 20:53:23 -0800804 */
Hyunsun Moon126171d2016-02-09 01:55:48 -0800805 private void processInPortTable(DeviceId deviceId, PortNumber tunnelPort, PortNumber dpPort) {
Hyunsun Moonba290072015-12-16 20:53:23 -0800806 checkNotNull(tunnelPort);
807
808 TrafficSelector selector = DefaultTrafficSelector.builder()
809 .matchInPort(tunnelPort)
810 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800811
Hyunsun Moonba290072015-12-16 20:53:23 -0800812 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
813 .transition(TABLE_TUNNEL_IN)
814 .build();
815
816 FlowRule flowRule = DefaultFlowRule.builder()
817 .fromApp(appId)
818 .withSelector(selector)
819 .withTreatment(treatment)
820 .withPriority(DEFAULT_PRIORITY)
821 .forDevice(deviceId)
822 .forTable(TABLE_IN_PORT)
823 .makePermanent()
824 .build();
825
826 processFlowRule(true, flowRule);
Hyunsun Moon3467a262016-01-14 16:56:26 -0800827
828 selector = DefaultTrafficSelector.builder()
Hyunsun Moon126171d2016-02-09 01:55:48 -0800829 .matchInPort(dpPort)
Hyunsun Moon3467a262016-01-14 16:56:26 -0800830 .build();
831
832 treatment = DefaultTrafficTreatment.builder()
833 .transition(TABLE_DST_IP)
834 .build();
835
836 flowRule = DefaultFlowRule.builder()
837 .fromApp(appId)
838 .withSelector(selector)
839 .withTreatment(treatment)
840 .withPriority(DEFAULT_PRIORITY)
841 .forDevice(deviceId)
842 .forTable(TABLE_IN_PORT)
843 .makePermanent()
844 .build();
845
846 processFlowRule(true, flowRule);
Hyunsun Moonba290072015-12-16 20:53:23 -0800847 }
848
849 /**
Hyunsun Moon01556a52016-02-12 12:48:47 -0800850 * Populates default rules for Q_IN_Q table.
851 *
852 * @param deviceId device id
853 * @param dpPort data plane interface port number
854 */
855 private void processQInQTable(DeviceId deviceId, PortNumber dpPort) {
856 // for traffic going out to WAN, strip vid 500 and take through data plane interface
857 TrafficSelector selector = DefaultTrafficSelector.builder()
858 .matchVlanId(VLAN_WAN)
859 .build();
860
861 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
862 .popVlan()
863 .setOutput(dpPort)
864 .build();
865
866 FlowRule flowRule = DefaultFlowRule.builder()
867 .fromApp(appId)
868 .withSelector(selector)
869 .withTreatment(treatment)
870 .withPriority(DEFAULT_PRIORITY)
871 .forDevice(deviceId)
872 .forTable(TABLE_Q_IN_Q)
873 .makePermanent()
874 .build();
875
876 processFlowRule(true, flowRule);
877
878 selector = DefaultTrafficSelector.builder()
879 .matchVlanId(VLAN_WAN)
880 .matchEthType(Ethernet.TYPE_ARP)
881 .build();
882
883 treatment = DefaultTrafficTreatment.builder()
884 .setOutput(PortNumber.CONTROLLER)
885 .build();
886
887 flowRule = DefaultFlowRule.builder()
888 .fromApp(appId)
889 .withSelector(selector)
890 .withTreatment(treatment)
891 .withPriority(HIGH_PRIORITY)
892 .forDevice(deviceId)
893 .forTable(TABLE_Q_IN_Q)
894 .makePermanent()
895 .build();
896
897 processFlowRule(true, flowRule);
898 }
899
900 /**
Hyunsun Moonba290072015-12-16 20:53:23 -0800901 * Populates rules for local in port in IN_PORT table.
902 * Flows from a given in port, whose source IP is service IP transition
903 * to DST_TYPE table. Other flows transition to IN_SERVICE table.
904 *
905 * @param deviceId device id to install the rules
906 * @param inPort in port
907 * @param srcIp source ip
908 */
909 private void populateLocalInPortRule(DeviceId deviceId, PortNumber inPort, IpAddress srcIp) {
910 TrafficSelector selector = DefaultTrafficSelector.builder()
911 .matchInPort(inPort)
912 .matchEthType(Ethernet.TYPE_IPV4)
913 .matchIPSrc(srcIp.toIpPrefix())
914 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800915
Hyunsun Moonba290072015-12-16 20:53:23 -0800916 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
917 .transition(TABLE_ACCESS_TYPE)
918 .build();
919
920
921 FlowRule flowRule = DefaultFlowRule.builder()
922 .fromApp(appId)
923 .withSelector(selector)
924 .withTreatment(treatment)
925 .withPriority(DEFAULT_PRIORITY)
926 .forDevice(deviceId)
927 .forTable(TABLE_IN_PORT)
928 .makePermanent()
929 .build();
930
931 processFlowRule(true, flowRule);
932
933 selector = DefaultTrafficSelector.builder()
934 .matchInPort(inPort)
935 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800936
Hyunsun Moonba290072015-12-16 20:53:23 -0800937 treatment = DefaultTrafficTreatment.builder()
938 .transition(TABLE_IN_SERVICE)
939 .build();
940
941 flowRule = DefaultFlowRule.builder()
942 .fromApp(appId)
943 .withSelector(selector)
944 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -0800945 .withPriority(LOW_PRIORITY)
Hyunsun Moonba290072015-12-16 20:53:23 -0800946 .forDevice(deviceId)
947 .forTable(TABLE_IN_PORT)
948 .makePermanent()
949 .build();
950
951 processFlowRule(true, flowRule);
952 }
953
954 /**
955 * Populates direct VM access rules for ACCESS_TYPE table.
956 * These rules are installed to all devices.
957 *
958 * @param srcRange source ip range
959 * @param dstRange destination ip range
960 */
961 private void populateDirectAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange) {
962 TrafficSelector selector = DefaultTrafficSelector.builder()
963 .matchEthType(Ethernet.TYPE_IPV4)
964 .matchIPSrc(srcRange)
965 .matchIPDst(dstRange)
966 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -0800967
Hyunsun Moonba290072015-12-16 20:53:23 -0800968 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
969 .transition(TABLE_DST_IP)
970 .build();
971
Hyunsun Moon7004fcf2016-03-08 04:36:02 -0800972
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800973 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moonba290072015-12-16 20:53:23 -0800974 FlowRule flowRuleDirect = DefaultFlowRule.builder()
975 .fromApp(appId)
976 .withSelector(selector)
977 .withTreatment(treatment)
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800978 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800979 .forDevice(deviceId)
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800980 .forTable(TABLE_ACCESS_TYPE)
981 .makePermanent()
982 .build();
983
984 processFlowRule(true, flowRuleDirect);
Hyunsun Moon7a9bb122016-03-08 18:07:52 -0800985 });
Hyunsun Moon1257efc2016-02-01 23:00:56 -0800986 }
987
988 /**
989 * Populates drop rules that does not match any direct access rules but has
990 * destination to a different service network in ACCESS_TYPE table.
991 *
992 * @param dstRange destination ip range
993 */
994 private void populateServiceIsolationRule(Ip4Prefix dstRange) {
995 TrafficSelector selector = DefaultTrafficSelector.builder()
996 .matchEthType(Ethernet.TYPE_IPV4)
997 .matchIPDst(dstRange)
998 .build();
999
1000 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1001 .drop()
1002 .build();
1003
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001004 getVirtualSwitches().stream().forEach(deviceId -> {
Hyunsun Moon1257efc2016-02-01 23:00:56 -08001005 FlowRule flowRuleDirect = DefaultFlowRule.builder()
1006 .fromApp(appId)
1007 .withSelector(selector)
1008 .withTreatment(treatment)
Hyunsun Moon64ec6142016-01-29 18:57:05 -08001009 .withPriority(LOW_PRIORITY)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001010 .forDevice(deviceId)
Hyunsun Moonba290072015-12-16 20:53:23 -08001011 .forTable(TABLE_ACCESS_TYPE)
1012 .makePermanent()
1013 .build();
1014
1015 processFlowRule(true, flowRuleDirect);
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001016 });
Hyunsun Moonba290072015-12-16 20:53:23 -08001017 }
1018
1019 /**
1020 * Populates indirect service access rules for ACCESS_TYPE table.
1021 * These rules are installed to all devices.
1022 *
1023 * @param srcRange source range
1024 * @param serviceIp service ip
1025 * @param outGroups list of output group
1026 */
1027 private void populateIndirectAccessRule(Ip4Prefix srcRange, Ip4Address serviceIp,
1028 Map<DeviceId, GroupId> outGroups) {
1029 TrafficSelector selector = DefaultTrafficSelector.builder()
1030 .matchEthType(Ethernet.TYPE_IPV4)
1031 .matchIPSrc(srcRange)
1032 .matchIPDst(serviceIp.toIpPrefix())
1033 .build();
1034
1035 for (Map.Entry<DeviceId, GroupId> outGroup : outGroups.entrySet()) {
1036 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1037 .group(outGroup.getValue())
1038 .build();
1039
1040 FlowRule flowRule = DefaultFlowRule.builder()
1041 .fromApp(appId)
1042 .withSelector(selector)
1043 .withTreatment(treatment)
Hyunsun Moon1257efc2016-02-01 23:00:56 -08001044 .withPriority(HIGH_PRIORITY)
Hyunsun Moonba290072015-12-16 20:53:23 -08001045 .forDevice(outGroup.getKey())
1046 .forTable(TABLE_ACCESS_TYPE)
1047 .makePermanent()
1048 .build();
1049
1050 processFlowRule(true, flowRule);
1051 }
1052 }
1053
1054 /**
1055 * Populates flow rules for IN_SERVICE table.
1056 *
1057 * @param inPorts list of inports related to the service for each device
1058 * @param outGroups set of output groups
1059 */
1060 private void populateInServiceRule(Map<DeviceId, Set<PortNumber>> inPorts, Map<DeviceId, GroupId> outGroups) {
1061 checkNotNull(inPorts);
1062 checkNotNull(outGroups);
1063
1064 for (Map.Entry<DeviceId, Set<PortNumber>> entry : inPorts.entrySet()) {
1065 Set<PortNumber> ports = entry.getValue();
1066 DeviceId deviceId = entry.getKey();
1067
1068 GroupId groupId = outGroups.get(deviceId);
1069 if (groupId == null) {
1070 continue;
1071 }
1072
1073 ports.stream().forEach(port -> {
1074 TrafficSelector selector = DefaultTrafficSelector.builder()
1075 .matchInPort(port)
1076 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -08001077
Hyunsun Moonba290072015-12-16 20:53:23 -08001078 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1079 .group(groupId)
1080 .build();
1081
1082 FlowRule flowRule = DefaultFlowRule.builder()
1083 .fromApp(appId)
1084 .withSelector(selector)
1085 .withTreatment(treatment)
1086 .withPriority(DEFAULT_PRIORITY)
1087 .forDevice(deviceId)
1088 .forTable(TABLE_IN_SERVICE)
1089 .makePermanent()
1090 .build();
1091
1092 processFlowRule(true, flowRule);
1093 });
1094 }
1095 }
1096
1097 /**
1098 * Populates flow rules for DST_IP table.
1099 *
1100 * @param deviceId device id
1101 * @param inPort in port
1102 * @param dstMac mac address
1103 * @param dstIp destination ip
1104 * @param tunnelId tunnel id
1105 * @param tunnelIp tunnel remote ip
1106 */
1107 private void populateDstIpRule(DeviceId deviceId, PortNumber inPort, MacAddress dstMac,
1108 IpAddress dstIp, long tunnelId, IpAddress tunnelIp) {
1109 TrafficSelector selector = DefaultTrafficSelector.builder()
1110 .matchEthType(Ethernet.TYPE_IPV4)
1111 .matchIPDst(dstIp.toIpPrefix())
1112 .build();
Hyunsun Moon3467a262016-01-14 16:56:26 -08001113
Hyunsun Moonba290072015-12-16 20:53:23 -08001114 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1115 .setEthDst(dstMac)
1116 .setOutput(inPort)
1117 .build();
1118
1119 FlowRule flowRule = DefaultFlowRule.builder()
1120 .fromApp(appId)
1121 .withSelector(selector)
1122 .withTreatment(treatment)
1123 .withPriority(DEFAULT_PRIORITY)
1124 .forDevice(deviceId)
1125 .forTable(TABLE_DST_IP)
1126 .makePermanent()
1127 .build();
1128
1129 processFlowRule(true, flowRule);
1130
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001131 for (DeviceId vSwitchId : getVirtualSwitches()) {
1132 if (vSwitchId.equals(deviceId)) {
Hyunsun Moon7004fcf2016-03-08 04:36:02 -08001133 continue;
1134 }
1135
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001136 ExtensionTreatment tunnelDst = getTunnelDst(vSwitchId, tunnelIp.getIp4Address());
Hyunsun Moonba290072015-12-16 20:53:23 -08001137 if (tunnelDst == null) {
1138 continue;
1139 }
1140
1141 treatment = DefaultTrafficTreatment.builder()
1142 .setEthDst(dstMac)
1143 .setTunnelId(tunnelId)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001144 .extension(tunnelDst, vSwitchId)
1145 .setOutput(getTunnelPort(vSwitchId))
Hyunsun Moonba290072015-12-16 20:53:23 -08001146 .build();
1147
1148 flowRule = DefaultFlowRule.builder()
1149 .fromApp(appId)
1150 .withSelector(selector)
1151 .withTreatment(treatment)
1152 .withPriority(DEFAULT_PRIORITY)
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001153 .forDevice(vSwitchId)
Hyunsun Moonba290072015-12-16 20:53:23 -08001154 .forTable(TABLE_DST_IP)
1155 .makePermanent()
1156 .build();
1157
1158 processFlowRule(true, flowRule);
1159 }
1160 }
1161
1162 /**
1163 * Populates flow rules for TUNNEL_ID table.
1164 *
1165 * @param deviceId device id
1166 * @param inPort in port
1167 * @param mac mac address
1168 * @param tunnelId tunnel id
1169 */
1170 private void populateTunnelInRule(DeviceId deviceId, PortNumber inPort, MacAddress mac, long tunnelId) {
1171 TrafficSelector selector = DefaultTrafficSelector.builder()
1172 .matchTunnelId(tunnelId)
1173 .matchEthDst(mac)
1174 .build();
1175
1176 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
1177 .setOutput(inPort)
1178 .build();
1179
1180 FlowRule flowRule = DefaultFlowRule.builder()
1181 .fromApp(appId)
1182 .withSelector(selector)
1183 .withTreatment(treatment)
1184 .withPriority(DEFAULT_PRIORITY)
1185 .forDevice(deviceId)
1186 .forTable(TABLE_TUNNEL_IN)
1187 .makePermanent()
1188 .build();
1189
1190 processFlowRule(true, flowRule);
1191 }
1192
1193 /**
1194 * Installs or uninstall a given rule.
1195 *
1196 * @param install true to install, false to uninstall
1197 * @param rule rule
1198 */
1199 private void processFlowRule(boolean install, FlowRule rule) {
1200 FlowRuleOperations.Builder oBuilder = FlowRuleOperations.builder();
1201 oBuilder = install ? oBuilder.add(rule) : oBuilder.remove(rule);
1202
1203 flowRuleService.apply(oBuilder.build(new FlowRuleOperationsContext() {
1204 @Override
1205 public void onError(FlowRuleOperations ops) {
1206 log.error(String.format("Failed %s, %s", ops.toString(), rule.toString()));
1207 }
1208 }));
1209 }
1210
1211 /**
1212 * Returns tunnel port of the device.
1213 *
1214 * @param deviceId device id
1215 * @return tunnel port number, or null if no tunnel port exists on a given device
1216 */
1217 private PortNumber getTunnelPort(DeviceId deviceId) {
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001218 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon01556a52016-02-12 12:48:47 -08001219 .filter(p -> p.annotations().value(PORT_NAME).contains(tunnelType))
1220 .findFirst().orElse(null);
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001221
1222 return port == null ? null : port.number();
Hyunsun Moonba290072015-12-16 20:53:23 -08001223 }
1224
1225 /**
Hyunsun Moon126171d2016-02-09 01:55:48 -08001226 * Returns data plane interface port name of a given device.
Hyunsun Moon3467a262016-01-14 16:56:26 -08001227 *
1228 * @param deviceId device id
Hyunsun Moon126171d2016-02-09 01:55:48 -08001229 * @param dpIntf data plane interface port name
1230 * @return data plane interface port number, or null if no such port exists
Hyunsun Moon3467a262016-01-14 16:56:26 -08001231 */
Hyunsun Moon126171d2016-02-09 01:55:48 -08001232 private PortNumber getDpPort(DeviceId deviceId, String dpIntf) {
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001233 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moon01556a52016-02-12 12:48:47 -08001234 .filter(p -> p.annotations().value(PORT_NAME).contains(dpIntf) &&
1235 p.isEnabled())
1236 .findFirst().orElse(null);
Hyunsun Moon2bf68e72016-01-15 11:41:14 -08001237
1238 return port == null ? null : port.number();
Hyunsun Moon3467a262016-01-14 16:56:26 -08001239 }
1240
Hyunsun Moon01556a52016-02-12 12:48:47 -08001241 /** Returns data plane interface port number of a given host.
1242 *
1243 * @param host host
1244 * @return port number, or null
1245 */
1246 private PortNumber getDpPort(Host host) {
1247 String portName = host.annotations().value(DATA_PLANE_INTF);
1248 return portName == null ? null : getDpPort(host.location().deviceId(), portName);
1249 }
1250
1251 /**
1252 * Returns service vlan from a given host.
1253 *
1254 * @param host host
1255 * @return vlan id, or null
1256 */
1257 private VlanId getServiceVlan(Host host) {
1258 String serviceVlan = host.annotations().value(S_TAG);
1259 return serviceVlan == null ? null : VlanId.vlanId(Short.parseShort(serviceVlan));
1260 }
1261
Hyunsun Moon3467a262016-01-14 16:56:26 -08001262 /**
Hyunsun Moonba290072015-12-16 20:53:23 -08001263 * Returns the inport from a given flow rule if the rule contains the match of it.
1264 *
1265 * @param flowRule flow rule
1266 * @return port number, or null if the rule doesn't have inport match
1267 */
1268 private PortNumber getInPort(FlowRule flowRule) {
1269 Criterion criterion = flowRule.selector().getCriterion(IN_PORT);
1270 if (criterion != null && criterion instanceof PortCriterion) {
1271 PortCriterion port = (PortCriterion) criterion;
1272 return port.port();
1273 } else {
1274 return null;
1275 }
1276 }
1277
1278 /**
1279 * Returns the destination mac address from a given flow rule if the rule
1280 * contains the instruction of it.
1281 *
1282 * @param flowRule flow rule
1283 * @return mac address, or null if the rule doesn't have destination mac instruction
1284 */
1285 private MacAddress getDstMacFromTreatment(FlowRule flowRule) {
1286 Instruction instruction = flowRule.treatment().allInstructions().stream()
1287 .filter(inst -> inst instanceof ModEtherInstruction &&
1288 ((ModEtherInstruction) inst).subtype().equals(ETH_DST))
1289 .findFirst()
1290 .orElse(null);
1291
1292 if (instruction == null) {
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001293 return null;
1294 }
1295
Hyunsun Moonba290072015-12-16 20:53:23 -08001296 return ((ModEtherInstruction) instruction).mac();
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001297 }
1298
1299 /**
Hyunsun Moonba290072015-12-16 20:53:23 -08001300 * Returns the destination mac address from a given flow rule if the rule
1301 * contains the match of it.
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001302 *
Hyunsun Moonba290072015-12-16 20:53:23 -08001303 * @param flowRule flow rule
1304 * @return mac address, or null if the rule doesn't have destination mac match
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001305 */
Hyunsun Moonba290072015-12-16 20:53:23 -08001306 private MacAddress getDstMacFromSelector(FlowRule flowRule) {
1307 Criterion criterion = flowRule.selector().getCriterion(Criterion.Type.ETH_DST);
1308 if (criterion != null && criterion instanceof EthCriterion) {
1309 EthCriterion eth = (EthCriterion) criterion;
1310 return eth.mac();
1311 } else {
1312 return null;
1313 }
1314 }
1315
1316 /**
1317 * Returns the destination IP from a given flow rule if the rule contains
1318 * the match of it.
1319 *
1320 * @param flowRule flow rule
1321 * @return ip prefix, or null if the rule doesn't have ip match
1322 */
1323 private IpPrefix getDstIpFromSelector(FlowRule flowRule) {
1324 Criterion criterion = flowRule.selector().getCriterion(IPV4_DST);
1325 if (criterion != null && criterion instanceof IPCriterion) {
1326 IPCriterion ip = (IPCriterion) criterion;
1327 return ip.ip();
1328 } else {
1329 return null;
1330 }
1331 }
1332
1333 /**
1334 * Returns the source IP from a given flow rule if the rule contains
1335 * the match of it.
1336 *
1337 * @param flowRule flow rule
1338 * @return ip prefix, or null if the rule doesn't have ip match
1339 */
1340 private IpPrefix getSrcIpFromSelector(FlowRule flowRule) {
1341 Criterion criterion = flowRule.selector().getCriterion(IPV4_SRC);
1342 if (criterion != null && criterion instanceof IPCriterion) {
1343 IPCriterion ip = (IPCriterion) criterion;
1344 return ip.ip();
1345 } else {
1346 return null;
1347 }
1348 }
1349
1350 /**
1351 * Returns the group ID from a given flow rule if the rule contains the
1352 * treatment of it.
1353 *
1354 * @param flowRule flow rule
1355 * @return group id, or null if the rule doesn't have group instruction
1356 */
1357 private GroupId getGroupIdFromTreatment(FlowRule flowRule) {
1358 Instruction instruction = flowRule.treatment().allInstructions().stream()
1359 .filter(inst -> inst instanceof Instructions.GroupInstruction)
1360 .findFirst()
1361 .orElse(null);
1362
1363 if (instruction == null) {
1364 return null;
1365 }
1366
1367 return ((Instructions.GroupInstruction) instruction).groupId();
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001368 }
1369
1370 /**
Hyunsun Moon64ec6142016-01-29 18:57:05 -08001371 * Returns the output port number from a given flow rule.
1372 *
1373 * @param flowRule flow rule
1374 * @return port number, or null if the rule does not have output instruction
1375 */
1376 private PortNumber getOutputFromTreatment(FlowRule flowRule) {
1377 Instruction instruction = flowRule.treatment().allInstructions().stream()
Hyunsun Moon01556a52016-02-12 12:48:47 -08001378 .filter(inst -> inst instanceof Instructions.OutputInstruction)
Hyunsun Moon64ec6142016-01-29 18:57:05 -08001379 .findFirst()
1380 .orElse(null);
1381
1382 if (instruction == null) {
1383 return null;
1384 }
1385
1386 return ((Instructions.OutputInstruction) instruction).port();
1387 }
1388
1389 /**
Hyunsun Moon01556a52016-02-12 12:48:47 -08001390 * Returns if a given flow rule has vlan push instruction or not.
1391 *
1392 * @param flowRule flow rule
1393 * @return true if it includes vlan push, or false
1394 */
1395 private boolean isVlanPushFromTreatment(FlowRule flowRule) {
1396 Instruction instruction = flowRule.treatment().allInstructions().stream()
1397 .filter(inst -> inst instanceof L2ModificationInstruction)
1398 .filter(inst -> ((L2ModificationInstruction) inst).subtype().equals(VLAN_PUSH))
1399 .findAny()
1400 .orElse(null);
1401
1402 return instruction != null;
1403 }
1404
1405 /**
Hyunsun Moon3467a262016-01-14 16:56:26 -08001406 * Creates a new group for a given service.
1407 *
1408 * @param deviceId device id to create a group
1409 * @param service cord service
1410 * @return group id, or null if it fails to create
1411 */
1412 private GroupId createServiceGroup(DeviceId deviceId, CordService service) {
1413 checkNotNull(service);
1414
1415 GroupKey groupKey = getGroupKey(service.id());
1416 Group group = groupService.getGroup(deviceId, groupKey);
1417 GroupId groupId = getGroupId(service.id(), deviceId);
1418
1419 if (group != null) {
1420 log.debug("Group {} is already exist in {}", service.id(), deviceId);
1421 return groupId;
1422 }
1423
1424 GroupBuckets buckets = getServiceGroupBuckets(deviceId, service.segmentationId(), service.hosts());
1425 GroupDescription groupDescription = new DefaultGroupDescription(
1426 deviceId,
1427 GroupDescription.Type.SELECT,
1428 buckets,
1429 groupKey,
1430 groupId.id(),
1431 appId);
1432
1433 groupService.addGroup(groupDescription);
1434
1435 return groupId;
1436 }
1437
1438 /**
1439 * Returns group buckets for a given device.
1440 *
1441 * @param deviceId device id
1442 * @param tunnelId tunnel id
1443 * @param hosts list of host
1444 * @return group buckets
1445 */
1446 private GroupBuckets getServiceGroupBuckets(DeviceId deviceId, long tunnelId, Map<Host, IpAddress> hosts) {
1447 List<GroupBucket> buckets = Lists.newArrayList();
1448
1449 for (Map.Entry<Host, IpAddress> entry : hosts.entrySet()) {
1450 Host host = entry.getKey();
1451 Ip4Address remoteIp = entry.getValue().getIp4Address();
1452 DeviceId hostDevice = host.location().deviceId();
1453
1454 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
1455 .builder()
1456 .setEthDst(host.mac());
1457
1458 if (deviceId.equals(hostDevice)) {
1459 tBuilder.setOutput(host.location().port());
1460 } else {
1461 ExtensionTreatment tunnelDst = getTunnelDst(deviceId, remoteIp);
1462 if (tunnelDst == null) {
1463 continue;
1464 }
1465
1466 tBuilder.extension(tunnelDst, deviceId)
1467 .setTunnelId(tunnelId)
1468 .setOutput(getTunnelPort(hostDevice));
1469 }
1470
1471 buckets.add(DefaultGroupBucket.createSelectGroupBucket(tBuilder.build()));
1472 }
1473
1474 return new GroupBuckets(buckets);
1475 }
1476
1477 /**
1478 * Returns globally unique group ID.
1479 *
1480 * @param serviceId service id
1481 * @param deviceId device id
1482 * @return group id
1483 */
1484 private GroupId getGroupId(CordServiceId serviceId, DeviceId deviceId) {
1485 return new DefaultGroupId(Objects.hash(serviceId, deviceId));
1486 }
1487
1488 /**
1489 * Returns group key of a service.
1490 *
1491 * @param serviceId service id
1492 * @return group key
1493 */
1494 private GroupKey getGroupKey(CordServiceId serviceId) {
1495 return new DefaultGroupKey(serviceId.id().getBytes());
1496 }
1497
1498 /**
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001499 * Returns extension instruction to set tunnel destination.
1500 *
1501 * @param deviceId device id
1502 * @param remoteIp tunnel destination address
1503 * @return extension treatment or null if it fails to get instruction
1504 */
Hyunsun Moonba290072015-12-16 20:53:23 -08001505 private ExtensionTreatment getTunnelDst(DeviceId deviceId, Ip4Address remoteIp) {
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001506 try {
1507 Driver driver = driverService.getDriver(deviceId);
Hyunsun Moonba290072015-12-16 20:53:23 -08001508 DefaultDriverData driverData = new DefaultDriverData(driver, deviceId);
1509 DriverHandler handler = new DefaultDriverHandler(driverData);
1510 ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001511
Hyunsun Moonba290072015-12-16 20:53:23 -08001512 ExtensionTreatment treatment =
1513 resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001514 treatment.setPropertyValue("tunnelDst", remoteIp);
1515
1516 return treatment;
Hyunsun Moonba290072015-12-16 20:53:23 -08001517 } catch (ItemNotFoundException | UnsupportedOperationException |
1518 ExtensionPropertyException e) {
1519 log.error("Failed to get extension instruction {}", deviceId);
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001520 return null;
1521 }
1522 }
Hyunsun Moon7a9bb122016-03-08 18:07:52 -08001523
1524 /**
1525 * Returns integration bridges configured in the system.
1526 *
1527 * @return set of device ids
1528 */
1529 private Set<DeviceId> getVirtualSwitches() {
1530 CordVtnConfig config = configRegistry.getConfig(appId, CordVtnConfig.class);
1531 if (config == null) {
1532 log.debug("No configuration found for {}", appId.name());
1533 return Sets.newHashSet();
1534 }
1535
1536 return config.cordVtnNodes().stream()
1537 .map(CordVtnNode::intBrId).collect(Collectors.toSet());
1538 }
Hyunsun Moon05f528a2015-11-04 17:34:35 -08001539}
Hyunsun Moonba290072015-12-16 20:53:23 -08001540