blob: 053264954b85f939f628936ac9093f1f3ddf876e [file] [log] [blame]
sangho27462c62015-05-14 00:39:53 -07001/*
Brian O'Connor0947d7e2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
sangho27462c62015-05-14 00:39:53 -07003 *
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 */
16package org.onosproject.segmentrouting;
17
sangho4a5c42a2015-05-20 22:16:38 -070018import org.onosproject.net.DeviceId;
19import org.onosproject.net.Link;
sanghobd812f82015-06-29 14:58:47 -070020import org.onosproject.net.link.LinkService;
21import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
Saurav Das261c3002017-06-13 15:35:54 -070022import org.onosproject.segmentrouting.grouphandler.DestinationSet;
sangho4a5c42a2015-05-20 22:16:38 -070023import org.onosproject.store.service.EventuallyConsistentMap;
sangho27462c62015-05-14 00:39:53 -070024import org.slf4j.Logger;
25
26import java.util.ArrayList;
sangho4a5c42a2015-05-20 22:16:38 -070027import java.util.HashSet;
sangho27462c62015-05-14 00:39:53 -070028import java.util.List;
sanghobd812f82015-06-29 14:58:47 -070029import java.util.Map;
sangho4a5c42a2015-05-20 22:16:38 -070030import java.util.Set;
sangho27462c62015-05-14 00:39:53 -070031
32import static org.slf4j.LoggerFactory.getLogger;
33
34/**
35 * Tunnel Handler.
36 */
37public class TunnelHandler {
38 protected final Logger log = getLogger(getClass());
39
sangho4a5c42a2015-05-20 22:16:38 -070040 private final DeviceConfiguration config;
41 private final EventuallyConsistentMap<String, Tunnel> tunnelStore;
sanghobd812f82015-06-29 14:58:47 -070042 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap;
43 private LinkService linkService;
sangho27462c62015-05-14 00:39:53 -070044
Charles Chanb7f75ac2016-01-11 18:28:54 -080045 /**
46 * Result of tunnel creation or removal.
47 */
sanghobd812f82015-06-29 14:58:47 -070048 public enum Result {
Charles Chanb7f75ac2016-01-11 18:28:54 -080049 /**
50 * Success.
51 */
sanghobd812f82015-06-29 14:58:47 -070052 SUCCESS,
Charles Chanb7f75ac2016-01-11 18:28:54 -080053
54 /**
55 * More than one router needs to specified to created a tunnel.
56 */
sanghobd812f82015-06-29 14:58:47 -070057 WRONG_PATH,
Charles Chanb7f75ac2016-01-11 18:28:54 -080058
59 /**
60 * The same tunnel exists already.
61 */
sanghobd812f82015-06-29 14:58:47 -070062 TUNNEL_EXISTS,
Charles Chanb7f75ac2016-01-11 18:28:54 -080063
64 /**
65 * The same tunnel ID exists already.
66 */
sanghobd812f82015-06-29 14:58:47 -070067 ID_EXISTS,
Charles Chanb7f75ac2016-01-11 18:28:54 -080068
69 /**
70 * Tunnel not found.
71 */
sanghobd812f82015-06-29 14:58:47 -070072 TUNNEL_NOT_FOUND,
Charles Chanb7f75ac2016-01-11 18:28:54 -080073
74 /**
75 * Cannot remove the tunnel used by a policy.
76 */
sanghobd812f82015-06-29 14:58:47 -070077 TUNNEL_IN_USE,
Charles Chanb7f75ac2016-01-11 18:28:54 -080078
79 /**
80 * Failed to create/remove groups for the tunnel.
81 */
sanghobd812f82015-06-29 14:58:47 -070082 INTERNAL_ERROR
83 }
84
Charles Chanb7f75ac2016-01-11 18:28:54 -080085 /**
86 * Constructs tunnel handler.
87 *
88 * @param linkService link service
89 * @param deviceConfiguration device configuration
90 * @param groupHandlerMap group handler map
91 * @param tunnelStore tunnel store
92 */
sanghobd812f82015-06-29 14:58:47 -070093 public TunnelHandler(LinkService linkService,
94 DeviceConfiguration deviceConfiguration,
95 Map<DeviceId, DefaultGroupHandler> groupHandlerMap,
sangho4a5c42a2015-05-20 22:16:38 -070096 EventuallyConsistentMap<String, Tunnel> tunnelStore) {
sanghobd812f82015-06-29 14:58:47 -070097 this.linkService = linkService;
98 this.config = deviceConfiguration;
99 this.groupHandlerMap = groupHandlerMap;
sangho4a5c42a2015-05-20 22:16:38 -0700100 this.tunnelStore = tunnelStore;
sangho27462c62015-05-14 00:39:53 -0700101 }
102
103 /**
104 * Creates a tunnel.
105 *
106 * @param tunnel tunnel reference to create a tunnel
sanghobd812f82015-06-29 14:58:47 -0700107 * @return WRONG_PATH if the tunnel path is wrong, ID_EXISTS if the tunnel ID
108 * exists already, TUNNEL_EXISTS if the same tunnel exists, INTERNAL_ERROR
109 * if the tunnel creation failed internally, SUCCESS if the tunnel is created
110 * successfully
sangho27462c62015-05-14 00:39:53 -0700111 */
sanghobd812f82015-06-29 14:58:47 -0700112 public Result createTunnel(Tunnel tunnel) {
sangho4a5c42a2015-05-20 22:16:38 -0700113
114 if (tunnel.labelIds().isEmpty() || tunnel.labelIds().size() < 3) {
115 log.error("More than one router needs to specified to created a tunnel");
sanghobd812f82015-06-29 14:58:47 -0700116 return Result.WRONG_PATH;
sangho4a5c42a2015-05-20 22:16:38 -0700117 }
118
119 if (tunnelStore.containsKey(tunnel.id())) {
120 log.warn("The same tunnel ID exists already");
sanghobd812f82015-06-29 14:58:47 -0700121 return Result.ID_EXISTS;
sangho4a5c42a2015-05-20 22:16:38 -0700122 }
123
124 if (tunnelStore.containsValue(tunnel)) {
125 log.warn("The same tunnel exists already");
sanghobd812f82015-06-29 14:58:47 -0700126 return Result.TUNNEL_EXISTS;
sangho4a5c42a2015-05-20 22:16:38 -0700127 }
128
129 int groupId = createGroupsForTunnel(tunnel);
130 if (groupId < 0) {
131 log.error("Failed to create groups for the tunnel");
sanghobd812f82015-06-29 14:58:47 -0700132 return Result.INTERNAL_ERROR;
sangho4a5c42a2015-05-20 22:16:38 -0700133 }
134
135 tunnel.setGroupId(groupId);
136 tunnelStore.put(tunnel.id(), tunnel);
137
sanghobd812f82015-06-29 14:58:47 -0700138 return Result.SUCCESS;
sangho27462c62015-05-14 00:39:53 -0700139 }
140
141 /**
142 * Removes the tunnel with the tunnel ID given.
143 *
144 * @param tunnelInfo tunnel information to delete tunnels
sanghobd812f82015-06-29 14:58:47 -0700145 * @return TUNNEL_NOT_FOUND if the tunnel to remove does not exists,
146 * INTERNAL_ERROR if the tunnel creation failed internally, SUCCESS
147 * if the tunnel is created successfully.
sangho27462c62015-05-14 00:39:53 -0700148 */
sanghobd812f82015-06-29 14:58:47 -0700149 public Result removeTunnel(Tunnel tunnelInfo) {
sangho27462c62015-05-14 00:39:53 -0700150
sangho4a5c42a2015-05-20 22:16:38 -0700151 Tunnel tunnel = tunnelStore.get(tunnelInfo.id());
sangho27462c62015-05-14 00:39:53 -0700152 if (tunnel != null) {
sangho4a5c42a2015-05-20 22:16:38 -0700153 DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
154 if (tunnel.isAllowedToRemoveGroup()) {
sanghobd812f82015-06-29 14:58:47 -0700155 if (groupHandlerMap.get(deviceId).removeGroup(tunnel.groupId())) {
sangho4a5c42a2015-05-20 22:16:38 -0700156 tunnelStore.remove(tunnel.id());
157 } else {
158 log.error("Failed to remove the tunnel {}", tunnelInfo.id());
sanghobd812f82015-06-29 14:58:47 -0700159 return Result.INTERNAL_ERROR;
sangho4a5c42a2015-05-20 22:16:38 -0700160 }
161 } else {
162 log.debug("The group is not removed because it is being used.");
163 tunnelStore.remove(tunnel.id());
164 }
sangho27462c62015-05-14 00:39:53 -0700165 } else {
sanghobd812f82015-06-29 14:58:47 -0700166 log.error("No tunnel found for tunnel ID {}", tunnelInfo.id());
167 return Result.TUNNEL_NOT_FOUND;
sangho27462c62015-05-14 00:39:53 -0700168 }
sanghobd812f82015-06-29 14:58:47 -0700169
170 return Result.SUCCESS;
sangho27462c62015-05-14 00:39:53 -0700171 }
172
173 /**
174 * Returns the tunnel with the tunnel ID given.
175 *
176 * @param tid Tunnel ID
177 * @return Tunnel reference
178 */
179 public Tunnel getTunnel(String tid) {
sangho4a5c42a2015-05-20 22:16:38 -0700180 return tunnelStore.get(tid);
sangho27462c62015-05-14 00:39:53 -0700181 }
182
183 /**
184 * Returns all tunnels.
185 *
186 * @return list of Tunnels
187 */
188 public List<Tunnel> getTunnels() {
189 List<Tunnel> tunnels = new ArrayList<>();
sangho4a5c42a2015-05-20 22:16:38 -0700190 tunnelStore.values().forEach(tunnel -> tunnels.add(
sangho27462c62015-05-14 00:39:53 -0700191 new DefaultTunnel((DefaultTunnel) tunnel)));
192
193 return tunnels;
194 }
sangho4a5c42a2015-05-20 22:16:38 -0700195
196 private int createGroupsForTunnel(Tunnel tunnel) {
197
Charles Chan9bec8a32015-12-01 10:00:51 -0800198 Set<Integer> portNumbers;
sanghobd812f82015-06-29 14:58:47 -0700199 final int groupError = -1;
sangho4a5c42a2015-05-20 22:16:38 -0700200
201 DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
202 if (deviceId == null) {
203 log.warn("No device found for SID {}", tunnel.labelIds().get(0));
sanghobd812f82015-06-29 14:58:47 -0700204 return groupError;
205 } else if (groupHandlerMap.get(deviceId) == null) {
206 log.warn("group handler not found for {}", deviceId);
207 return groupError;
sangho4a5c42a2015-05-20 22:16:38 -0700208 }
209 Set<DeviceId> deviceIds = new HashSet<>();
210 int sid = tunnel.labelIds().get(1);
211 if (config.isAdjacencySid(deviceId, sid)) {
212 portNumbers = config.getPortsForAdjacencySid(deviceId, sid);
sanghobd812f82015-06-29 14:58:47 -0700213 for (Link link: linkService.getDeviceEgressLinks(deviceId)) {
sangho4a5c42a2015-05-20 22:16:38 -0700214 for (Integer port: portNumbers) {
215 if (link.src().port().toLong() == port) {
216 deviceIds.add(link.dst().deviceId());
217 }
218 }
219 }
220 } else {
221 deviceIds.add(config.getDeviceId(sid));
222 }
Pier Ventre229fd0b2016-10-31 16:49:19 -0700223 // For these NeighborSet isMpls is meaningless.
Andreas Pantelopoulosb281ae22018-05-01 14:56:05 -0700224 // TODO : Revisit this, the code and also the type
225 DestinationSet ns = DestinationSet.createTypePushBos(
226 tunnel.labelIds().get(2),
227 DeviceId.NONE);
sangho4a5c42a2015-05-20 22:16:38 -0700228
229 // If the tunnel reuses any existing groups, then tunnel handler
230 // should not remove the group.
sanghobd812f82015-06-29 14:58:47 -0700231 if (groupHandlerMap.get(deviceId).hasNextObjectiveId(ns)) {
sangho4a5c42a2015-05-20 22:16:38 -0700232 tunnel.allowToRemoveGroup(false);
233 } else {
234 tunnel.allowToRemoveGroup(true);
235 }
sangho4a5c42a2015-05-20 22:16:38 -0700236
Saurav Das261c3002017-06-13 15:35:54 -0700237 return groupHandlerMap.get(deviceId).getNextObjectiveId(ns, null, null, true);
sangho4a5c42a2015-05-20 22:16:38 -0700238 }
239
sangho27462c62015-05-14 00:39:53 -0700240}