blob: c40bac6149b8e22f4c543b8cf11c0fa363522858 [file] [log] [blame]
Kyuhwi Choib0718212016-06-01 11:33:27 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Kyuhwi Choib0718212016-06-01 11:33:27 +09003 *
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 */
16
17package org.onosproject.scalablegateway.impl;
18
19import com.google.common.collect.Lists;
20import org.onlab.packet.Ip4Address;
21import org.onosproject.core.ApplicationId;
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -070022import org.onosproject.core.GroupId;
Kyuhwi Choib0718212016-06-01 11:33:27 +090023import org.onosproject.net.DeviceId;
24import org.onosproject.net.Port;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
27import org.onosproject.net.device.DeviceService;
28import org.onosproject.net.driver.DefaultDriverData;
29import org.onosproject.net.driver.DefaultDriverHandler;
30import org.onosproject.net.driver.Driver;
31import org.onosproject.net.driver.DriverHandler;
32import org.onosproject.net.driver.DriverService;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
34import org.onosproject.net.flow.TrafficTreatment;
35import org.onosproject.net.flow.instructions.ExtensionPropertyException;
36import org.onosproject.net.flow.instructions.ExtensionTreatment;
37import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
38import org.onosproject.net.group.DefaultGroupDescription;
39import org.onosproject.net.group.DefaultGroupKey;
Kyuhwi Choib0718212016-06-01 11:33:27 +090040import org.onosproject.net.group.GroupBucket;
41import org.onosproject.net.group.GroupBuckets;
42import org.onosproject.net.group.GroupDescription;
43import org.onosproject.net.group.GroupKey;
44import org.onosproject.net.group.GroupService;
45import org.onosproject.scalablegateway.api.GatewayNode;
46import org.slf4j.Logger;
47import org.slf4j.LoggerFactory;
48
49import java.util.List;
50
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -070051import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Kyuhwi Choib0718212016-06-01 11:33:27 +090052import static org.onosproject.net.group.DefaultGroupBucket.createSelectGroupBucket;
53
54/**
55 * Handles group generation request from ScalableGateway.
56 */
57public class SelectGroupHandler {
58
59 private final Logger log = LoggerFactory.getLogger(getClass());
60
61 private static final String TUNNEL_DESTINATION = "tunnelDst";
62 private static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
Kyuhwi Choib0718212016-06-01 11:33:27 +090063
64 private final GroupService groupService;
65 private final DeviceService deviceService;
66 private final DriverService driverService;
67 private final ApplicationId appId;
68
69 /**
70 * Default constructor.
71 *
72 * @param targetGroupService group service
73 * @param targetDeviceService device service
74 * @param targetDriverService driver service
75 * @param appId application id for group service
76 */
77 public SelectGroupHandler(GroupService targetGroupService, DeviceService targetDeviceService,
78 DriverService targetDriverService, ApplicationId appId) {
79 groupService = targetGroupService;
80 deviceService = targetDeviceService;
81 driverService = targetDriverService;
82 this.appId = appId;
83 }
84
85 /**
86 * Creates select type group description according to given deviceId.
87 *
88 * @param srcDeviceId target device id for group description
89 * @param nodeList gateway node list for bucket action
90 * @return created select type group description
91 */
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -070092 public GroupId createGatewayGroup(DeviceId srcDeviceId, List<GatewayNode> nodeList) {
Kyuhwi Choib0718212016-06-01 11:33:27 +090093 List<GroupBucket> bucketList = generateBucketsForSelectGroup(srcDeviceId, nodeList);
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -070094 GroupId groupId = getGroupId(srcDeviceId);
95 GroupDescription groupDescription = new DefaultGroupDescription(
96 srcDeviceId,
97 GroupDescription.Type.SELECT,
98 new GroupBuckets(bucketList),
99 getGroupKey(srcDeviceId),
100 groupId.id(),
101 appId);
102
103 groupService.addGroup(groupDescription);
104 return groupId;
Kyuhwi Choib0718212016-06-01 11:33:27 +0900105 }
106
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700107 /**
108 * Returns unique group key with supplied source device ID as a hash.
109 *
110 * @param srcDeviceId source device id
111 * @return group key
112 */
113 public GroupKey getGroupKey(DeviceId srcDeviceId) {
114 return new DefaultGroupKey(srcDeviceId.toString().getBytes());
115 }
Kyuhwi Choib0718212016-06-01 11:33:27 +0900116
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700117 private GroupId getGroupId(DeviceId srcDeviceId) {
Yi Tsengfa394de2017-02-01 11:26:40 -0800118 return new GroupId(srcDeviceId.toString().hashCode());
Kyuhwi Choib0718212016-06-01 11:33:27 +0900119 }
120
121 /**
122 * Updates groupBuckets in select type group.
123 *
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700124 * @param deviceId target device id to update the group
Kyuhwi Choib0718212016-06-01 11:33:27 +0900125 * @param nodeList updated gateway node list for bucket action
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700126 * @param isInsert update type(add or remove)
Kyuhwi Choib0718212016-06-01 11:33:27 +0900127 */
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700128 public void updateGatewayGroupBuckets(DeviceId deviceId,
129 List<GatewayNode> nodeList,
130 boolean isInsert) {
Kyuhwi Choib0718212016-06-01 11:33:27 +0900131 List<GroupBucket> bucketList = generateBucketsForSelectGroup(deviceId, nodeList);
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700132 GroupKey groupKey = getGroupKey(deviceId);
133 if (isInsert) {
134 groupService.addBucketsToGroup(
135 deviceId,
136 groupKey,
137 new GroupBuckets(bucketList),
138 groupKey, appId);
Kyuhwi Choib0718212016-06-01 11:33:27 +0900139 } else {
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700140 groupService.removeBucketsFromGroup(
141 deviceId,
142 groupKey,
143 new GroupBuckets(bucketList),
144 groupKey, appId);
Kyuhwi Choib0718212016-06-01 11:33:27 +0900145 }
Kyuhwi Choib0718212016-06-01 11:33:27 +0900146 }
147
148 private List<GroupBucket> generateBucketsForSelectGroup(DeviceId deviceId, List<GatewayNode> nodeList) {
149 List<GroupBucket> bucketList = Lists.newArrayList();
150 nodeList.forEach(node -> {
151 TrafficTreatment tBuilder = DefaultTrafficTreatment.builder()
152 .extension(buildNiciraExtenstion(deviceId, node.getDataIpAddress()), deviceId)
153 .setOutput(getTunnelPort(deviceId))
154 .build();
155 bucketList.add(createSelectGroupBucket(tBuilder));
156 });
157 return bucketList;
158 }
159
160 /**
161 * Builds Nicira extension for tagging remoteIp of vxlan.
162 *
163 * @param id device id of vxlan source device
164 * @param hostIp remote ip of vxlan destination device
165 * @return NiciraExtension Treatment
166 */
167 private ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) {
168 Driver driver = driverService.getDriver(id);
169 DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id));
170 ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class);
171
172 ExtensionTreatment extensionInstruction =
173 resolver.getExtensionInstruction(
174 ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type());
175
176 try {
177 extensionInstruction.setPropertyValue(TUNNEL_DESTINATION, hostIp);
178 } catch (ExtensionPropertyException e) {
179 log.error("Error setting Nicira extension setting {}", e);
180 }
181
182 return extensionInstruction;
183 }
184
185 /**
186 * Returns port number of vxlan tunnel.
187 *
188 * @param deviceId target Device Id
189 * @return portNumber
190 */
191 private PortNumber getTunnelPort(DeviceId deviceId) {
192 Port port = deviceService.getPorts(deviceId).stream()
Hyunsun Moonf9a16ed2016-07-20 21:59:48 -0700193 .filter(p -> p.annotations().value(PORT_NAME).equals(PORTNAME_PREFIX_TUNNEL))
Kyuhwi Choib0718212016-06-01 11:33:27 +0900194 .findAny().orElse(null);
195
196 if (port == null) {
197 log.error("No TunnelPort was created.");
198 return null;
199 }
200 return port.number();
201
202 }
203}