Kyuhwi Choi
Committed by Gerrit Code Review

[ONOS-4480] Implement select group based load balancing

 - Implements select group handler for vxlan tunnel based network
 - Implements update bucket method for select type group

Change-Id: Ic58f298f9be6d5c9c8036fb521c2ffb6d0bb62ee
...@@ -39,6 +39,10 @@ import org.onosproject.net.config.NetworkConfigRegistry; ...@@ -39,6 +39,10 @@ import org.onosproject.net.config.NetworkConfigRegistry;
39 import org.onosproject.net.config.NetworkConfigService; 39 import org.onosproject.net.config.NetworkConfigService;
40 import org.onosproject.net.config.basics.SubjectFactories; 40 import org.onosproject.net.config.basics.SubjectFactories;
41 import org.onosproject.net.device.DeviceService; 41 import org.onosproject.net.device.DeviceService;
42 +import org.onosproject.net.driver.DriverService;
43 +import org.onosproject.net.group.Group;
44 +import org.onosproject.net.group.GroupDescription;
45 +import org.onosproject.net.group.GroupService;
42 import org.onosproject.scalablegateway.api.GatewayNode; 46 import org.onosproject.scalablegateway.api.GatewayNode;
43 import org.onosproject.scalablegateway.api.GatewayNodeConfig; 47 import org.onosproject.scalablegateway.api.GatewayNodeConfig;
44 import org.onosproject.scalablegateway.api.ScalableGatewayService; 48 import org.onosproject.scalablegateway.api.ScalableGatewayService;
...@@ -81,7 +85,14 @@ public class ScalableGatewayManager implements ScalableGatewayService { ...@@ -81,7 +85,14 @@ public class ScalableGatewayManager implements ScalableGatewayService {
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected DeviceService deviceService; 86 protected DeviceService deviceService;
83 87
88 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 + protected DriverService driverService;
90 +
91 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 + protected GroupService groupService;
93 +
84 private GatewayNodeConfig config; 94 private GatewayNodeConfig config;
95 + private SelectGroupHandler selectGroupHandler;
85 96
86 private final NetworkConfigListener configListener = new InternalConfigListener(); 97 private final NetworkConfigListener configListener = new InternalConfigListener();
87 98
...@@ -100,6 +111,7 @@ public class ScalableGatewayManager implements ScalableGatewayService { ...@@ -100,6 +111,7 @@ public class ScalableGatewayManager implements ScalableGatewayService {
100 configRegistry.registerConfigFactory(configFactory); 111 configRegistry.registerConfigFactory(configFactory);
101 configService.addListener(configListener); 112 configService.addListener(configListener);
102 113
114 + selectGroupHandler = new SelectGroupHandler(groupService, deviceService, driverService, appId);
103 readConfiguration(); 115 readConfiguration();
104 116
105 log.info("started"); 117 log.info("started");
...@@ -141,8 +153,10 @@ public class ScalableGatewayManager implements ScalableGatewayService { ...@@ -141,8 +153,10 @@ public class ScalableGatewayManager implements ScalableGatewayService {
141 153
142 @Override 154 @Override
143 public GroupId getGroupIdForGatewayLoadBalance(DeviceId srcDeviceId) { 155 public GroupId getGroupIdForGatewayLoadBalance(DeviceId srcDeviceId) {
144 - //TODO: Implement group generation method by handler 156 + GroupDescription description = selectGroupHandler.createSelectGroupInVxlan(srcDeviceId, getGatewayNodes());
145 - return null; 157 + groupService.addGroup(description);
158 + Group group = groupService.getGroup(description.deviceId(), description.appCookie());
159 + return group != null ? group.id() : null;
146 } 160 }
147 161
148 @Override 162 @Override
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.scalablegateway.impl;
18 +
19 +import com.google.common.collect.Lists;
20 +import org.onlab.packet.Ip4Address;
21 +import org.onosproject.core.ApplicationId;
22 +import org.onosproject.net.DeviceId;
23 +import org.onosproject.net.Port;
24 +import org.onosproject.net.PortNumber;
25 +import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
26 +import org.onosproject.net.device.DeviceService;
27 +import org.onosproject.net.driver.DefaultDriverData;
28 +import org.onosproject.net.driver.DefaultDriverHandler;
29 +import org.onosproject.net.driver.Driver;
30 +import org.onosproject.net.driver.DriverHandler;
31 +import org.onosproject.net.driver.DriverService;
32 +import org.onosproject.net.flow.DefaultTrafficTreatment;
33 +import org.onosproject.net.flow.TrafficTreatment;
34 +import org.onosproject.net.flow.instructions.ExtensionPropertyException;
35 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
36 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
37 +import org.onosproject.net.group.DefaultGroupDescription;
38 +import org.onosproject.net.group.DefaultGroupKey;
39 +import org.onosproject.net.group.Group;
40 +import org.onosproject.net.group.GroupBucket;
41 +import org.onosproject.net.group.GroupBuckets;
42 +import org.onosproject.net.group.GroupDescription;
43 +import org.onosproject.net.group.GroupKey;
44 +import org.onosproject.net.group.GroupService;
45 +import org.onosproject.scalablegateway.api.GatewayNode;
46 +import org.slf4j.Logger;
47 +import org.slf4j.LoggerFactory;
48 +
49 +import java.util.List;
50 +
51 +import static org.onosproject.net.group.DefaultGroupBucket.createSelectGroupBucket;
52 +
53 +/**
54 + * Handles group generation request from ScalableGateway.
55 + */
56 +public class SelectGroupHandler {
57 +
58 + private final Logger log = LoggerFactory.getLogger(getClass());
59 +
60 + private static final String TUNNEL_DESTINATION = "tunnelDst";
61 + private static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
62 + private static final String PORTNAME = "portName";
63 +
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 + */
92 + public GroupDescription createSelectGroupInVxlan(DeviceId srcDeviceId, List<GatewayNode> nodeList) {
93 + List<GroupBucket> bucketList = generateBucketsForSelectGroup(srcDeviceId, nodeList);
94 + GroupKey key = generateGroupKey(srcDeviceId, nodeList);
95 + return new DefaultGroupDescription(srcDeviceId, GroupDescription.Type.SELECT,
96 + new GroupBuckets(bucketList), key, null, appId);
97 + }
98 +
99 + private GroupKey generateGroupKey(DeviceId srcDeviceId, List<GatewayNode> nodeList) {
100 + String cookie = srcDeviceId.toString();
101 + for (GatewayNode node : nodeList) {
102 + cookie = cookie.concat(node.getGatewayDeviceId().toString());
103 + }
104 + return new DefaultGroupKey(cookie.getBytes());
105 +
106 + }
107 +
108 + /**
109 + * Updates groupBuckets in select type group.
110 + *
111 + * @param deviceId target device id for group description
112 + * @param oldAppCookie group key for target group
113 + * @param nodeList updated gateway node list for bucket action
114 + * @param nodeInsertion update type(add or remove)
115 + * @return result of process
116 + */
117 + public boolean updateBucketToSelectGroupInVxlan(DeviceId deviceId, GroupKey oldAppCookie,
118 + List<GatewayNode> nodeList, boolean nodeInsertion) {
119 + List<GroupBucket> bucketList = generateBucketsForSelectGroup(deviceId, nodeList);
120 +
121 + GroupKey newAppCookie = generateGroupKey(deviceId, nodeList);
122 + if (nodeInsertion) {
123 + groupService.addBucketsToGroup(deviceId, oldAppCookie,
124 + new GroupBuckets(bucketList), newAppCookie, appId);
125 + } else {
126 + groupService.removeBucketsFromGroup(deviceId, oldAppCookie,
127 + new GroupBuckets(bucketList), newAppCookie, appId);
128 + }
129 + Group group = groupService.getGroup(deviceId, newAppCookie);
130 + return group != null ? true : false;
131 + }
132 +
133 + private List<GroupBucket> generateBucketsForSelectGroup(DeviceId deviceId, List<GatewayNode> nodeList) {
134 + List<GroupBucket> bucketList = Lists.newArrayList();
135 + nodeList.forEach(node -> {
136 + TrafficTreatment tBuilder = DefaultTrafficTreatment.builder()
137 + .extension(buildNiciraExtenstion(deviceId, node.getDataIpAddress()), deviceId)
138 + .setOutput(getTunnelPort(deviceId))
139 + .build();
140 + bucketList.add(createSelectGroupBucket(tBuilder));
141 + });
142 + return bucketList;
143 + }
144 +
145 + /**
146 + * Builds Nicira extension for tagging remoteIp of vxlan.
147 + *
148 + * @param id device id of vxlan source device
149 + * @param hostIp remote ip of vxlan destination device
150 + * @return NiciraExtension Treatment
151 + */
152 + private ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) {
153 + Driver driver = driverService.getDriver(id);
154 + DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id));
155 + ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class);
156 +
157 + ExtensionTreatment extensionInstruction =
158 + resolver.getExtensionInstruction(
159 + ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type());
160 +
161 + try {
162 + extensionInstruction.setPropertyValue(TUNNEL_DESTINATION, hostIp);
163 + } catch (ExtensionPropertyException e) {
164 + log.error("Error setting Nicira extension setting {}", e);
165 + }
166 +
167 + return extensionInstruction;
168 + }
169 +
170 + /**
171 + * Returns port number of vxlan tunnel.
172 + *
173 + * @param deviceId target Device Id
174 + * @return portNumber
175 + */
176 + private PortNumber getTunnelPort(DeviceId deviceId) {
177 + Port port = deviceService.getPorts(deviceId).stream()
178 + .filter(p -> p.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL))
179 + .findAny().orElse(null);
180 +
181 + if (port == null) {
182 + log.error("No TunnelPort was created.");
183 + return null;
184 + }
185 + return port.number();
186 +
187 + }
188 +}