blob: 69f9cfd23a40c5656e7c7604055777606f8b10a4 [file] [log] [blame]
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -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 */
16package org.onosproject.incubator.rpc.grpc;
17
18import static com.google.common.base.Preconditions.checkArgument;
19import static com.google.common.base.Preconditions.checkNotNull;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070020import static com.google.common.cache.RemovalListeners.asynchronous;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080021import static org.onosproject.net.DeviceId.deviceId;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070022import static org.onosproject.net.LinkKey.linkKey;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080023
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070024import java.util.concurrent.ScheduledExecutorService;
25import java.util.concurrent.TimeUnit;
26
27import org.apache.commons.lang3.tuple.Pair;
HIGUCHI Yutae3e90632016-05-11 16:44:01 -070028import org.onosproject.grpc.net.Link.ConnectPoint.ElementIdCase;
29import org.onosproject.grpc.net.Link.LinkType;
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -070030import org.onosproject.grpc.net.link.LinkProviderServiceRpcGrpc.LinkProviderServiceRpcImplBase;
HIGUCHI Yutae3e90632016-05-11 16:44:01 -070031import org.onosproject.grpc.net.link.LinkService.LinkDetectedMsg;
32import org.onosproject.grpc.net.link.LinkService.LinkVanishedMsg;
33import org.onosproject.grpc.net.link.LinkService.Void;
Aaron Kruglikov9f95f992017-06-23 14:15:25 +090034import org.onosproject.incubator.protobuf.models.ProtobufUtils;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080035import org.onosproject.net.ConnectPoint;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.Link;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070038import org.onosproject.net.LinkKey;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080039import org.onosproject.net.PortNumber;
40import org.onosproject.net.SparseAnnotations;
41import org.onosproject.net.link.DefaultLinkDescription;
42import org.onosproject.net.link.LinkDescription;
43import org.onosproject.net.link.LinkProviderService;
44import org.slf4j.Logger;
45import org.slf4j.LoggerFactory;
46
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070047import com.google.common.cache.Cache;
48import com.google.common.cache.CacheBuilder;
49import com.google.common.cache.RemovalNotification;
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -070050import com.google.common.annotations.Beta;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080051
52import io.grpc.stub.StreamObserver;
53
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070054// Only single instance will be created and bound to gRPC LinkProviderService
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080055/**
56 * Server-side implementation of gRPC version of LinkProviderService.
57 */
58@Beta
59final class LinkProviderServiceServerProxy
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -070060 extends LinkProviderServiceRpcImplBase {
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080061
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070062 /**
63 * Silence time in seconds, until link gets treated as vanished.
64 */
65 private static final int EVICT_LIMIT = 3 * 3;
66
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080067 private final Logger log = LoggerFactory.getLogger(getClass());
68
69 private final GrpcRemoteServiceServer server;
70
HIGUCHI Yuta6381a242016-03-13 23:29:10 -070071 // TODO implement aging mechanism to automatically remove
72 // stale links reported by dead client, etc.
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070073 /**
74 * Evicting Cache to track last seen time.
75 */
76 private final Cache<Pair<String, LinkKey>, LinkDescription> lastSeen;
HIGUCHI Yuta6381a242016-03-13 23:29:10 -070077
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080078 LinkProviderServiceServerProxy(GrpcRemoteServiceServer server) {
79 this.server = checkNotNull(server);
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070080 ScheduledExecutorService executor = server.getSharedExecutor();
81 lastSeen = CacheBuilder.newBuilder()
82 .expireAfterWrite(EVICT_LIMIT, TimeUnit.SECONDS)
83 .removalListener(asynchronous(this::onRemove, executor))
84 .build();
85
86 executor.scheduleWithFixedDelay(lastSeen::cleanUp,
87 EVICT_LIMIT, EVICT_LIMIT, TimeUnit.SECONDS);
88 }
89
90 private void onRemove(RemovalNotification<Pair<String, LinkKey>, LinkDescription> n) {
91 if (n.wasEvicted()) {
92 getLinkProviderServiceFor(n.getKey().getLeft())
93 .linkVanished(n.getValue());
94 }
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080095 }
96
97 /**
98 * Gets or creates {@link LinkProviderService} registered for given ProviderId scheme.
99 *
100 * @param scheme ProviderId scheme.
101 * @return {@link LinkProviderService}
102 */
103 private LinkProviderService getLinkProviderServiceFor(String scheme) {
104 return server.getLinkProviderServiceFor(scheme);
105 }
106
107 @Override
108 public void linkDetected(LinkDetectedMsg request,
109 StreamObserver<Void> responseObserver) {
110
111 try {
112 onLinkDetected(request, responseObserver);
113 // If onNext call was not mandatory, it can be removed.
114 responseObserver.onNext(Void.getDefaultInstance());
115 responseObserver.onCompleted();
116 } catch (Exception e) {
117 log.error("Exception caught", e);
118 responseObserver.onError(e);
119 }
120 }
121
122 private void onLinkDetected(LinkDetectedMsg request,
123 StreamObserver<Void> responseObserver) {
124 String scheme = request.getProviderId();
125
126 LinkProviderService linkProviderService = getLinkProviderServiceFor(scheme);
127
128 LinkDescription linkDescription = translate(request.getLinkDescription());
129 linkProviderService.linkDetected(linkDescription);
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700130 lastSeen.put(Pair.of(scheme, linkKey(linkDescription)), linkDescription);
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800131 }
132
133 @Override
134 public void linkVanished(LinkVanishedMsg request,
135 StreamObserver<Void> responseObserver) {
136 try {
137 onLinksVanished(request, responseObserver);
138 // If onNext call was not mandatory, it can be removed.
139 responseObserver.onNext(Void.getDefaultInstance());
140 responseObserver.onCompleted();
141 } catch (Exception e) {
142 log.error("Exception caught", e);
143 responseObserver.onError(e);
144 }
145 }
146
147 private void onLinksVanished(LinkVanishedMsg request,
148 StreamObserver<Void> responseObserver) {
149 String scheme = request.getProviderId();
150 switch (request.getSubjectCase()) {
151 case CONNECT_POINT:
152 ConnectPoint cp = translate(request.getConnectPoint());
153 getLinkProviderServiceFor(scheme).linksVanished(cp);
154 break;
155 case DEVICE_ID:
156 DeviceId did = deviceId(request.getDeviceId());
157 getLinkProviderServiceFor(scheme).linksVanished(did);
158 break;
159 case LINK_DESCRIPTION:
160 LinkDescription desc = translate(request.getLinkDescription());
161 getLinkProviderServiceFor(scheme).linkVanished(desc);
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -0700162 lastSeen.invalidate(Pair.of(scheme, linkKey(desc)));
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800163 break;
164 case SUBJECT_NOT_SET:
165 default:
166 // do nothing
167 break;
168 }
169 }
170
171 /**
172 * Translates gRPC message to corresponding ONOS object.
173 *
174 * @param connectPoint gRPC message.
175 * @return {@link ConnectPoint}
176 */
HIGUCHI Yutae3e90632016-05-11 16:44:01 -0700177 private ConnectPoint translate(org.onosproject.grpc.net.Link.ConnectPoint connectPoint) {
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800178 checkArgument(connectPoint.getElementIdCase() == ElementIdCase.DEVICE_ID,
179 "Only DeviceId supported.");
180 return new ConnectPoint(deviceId(connectPoint.getDeviceId()),
181 PortNumber.fromString(connectPoint.getPortNumber()));
182 }
183
184 /**
185 * Translates gRPC message to corresponding ONOS object.
186 *
187 * @param linkDescription gRPC message
188 * @return {@link LinkDescription}
189 */
HIGUCHI Yutae3e90632016-05-11 16:44:01 -0700190 private LinkDescription translate(org.onosproject.grpc.net.Link.LinkDescription linkDescription) {
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800191 ConnectPoint src = translate(linkDescription.getSrc());
192 ConnectPoint dst = translate(linkDescription.getDst());
193 Link.Type type = translate(linkDescription.getType());
HIGUCHI Yuta06c1a3f2016-05-23 12:54:55 -0700194 SparseAnnotations annotations = ProtobufUtils.asAnnotations(linkDescription.getAnnotations());
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800195 return new DefaultLinkDescription(src, dst, type, annotations);
196 }
197
198 /**
199 * Translates gRPC message to corresponding ONOS object.
200 *
201 * @param type gRPC message enum
HIGUCHI Yutae3e90632016-05-11 16:44:01 -0700202 * @return {@link org.onosproject.net.Link.Type Link.Type}
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800203 */
204 private Link.Type translate(LinkType type) {
205 switch (type) {
206 case DIRECT:
207 return Link.Type.DIRECT;
208 case EDGE:
209 return Link.Type.EDGE;
210 case INDIRECT:
211 return Link.Type.INDIRECT;
212 case OPTICAL:
213 return Link.Type.INDIRECT;
214 case TUNNEL:
215 return Link.Type.TUNNEL;
216 case VIRTUAL:
217 return Link.Type.VIRTUAL;
218
219 case UNRECOGNIZED:
220 default:
221 return Link.Type.DIRECT;
222 }
223 }
224
225}