blob: 55c93fb0280f0ffb2ea77a7252a29639d0792bef [file] [log] [blame]
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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
Jian Lic9b4bf12017-06-26 23:50:32 +090018import com.google.common.annotations.Beta;
19import com.google.common.cache.Cache;
20import com.google.common.cache.CacheBuilder;
21import com.google.common.cache.RemovalNotification;
22import io.grpc.stub.StreamObserver;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070023import org.apache.commons.lang3.tuple.Pair;
Yuta HIGUCHI9efba1e2016-07-09 11:07:13 -070024import org.onosproject.grpc.net.link.LinkProviderServiceRpcGrpc.LinkProviderServiceRpcImplBase;
HIGUCHI Yutae3e90632016-05-11 16:44:01 -070025import org.onosproject.grpc.net.link.LinkService.LinkDetectedMsg;
26import org.onosproject.grpc.net.link.LinkService.LinkVanishedMsg;
27import org.onosproject.grpc.net.link.LinkService.Void;
Jian Lic9b4bf12017-06-26 23:50:32 +090028import org.onosproject.grpc.net.link.models.LinkDescriptionProtoOuterClass.LinkDescriptionProto;
29import org.onosproject.grpc.net.link.models.LinkEnumsProto.LinkTypeProto;
30import org.onosproject.grpc.net.models.ConnectPointProtoOuterClass.ConnectPointProto;
31import org.onosproject.grpc.net.models.ConnectPointProtoOuterClass.ConnectPointProto.ElementIdCase;
Jian Lid40252c2017-12-08 04:13:20 +090032import org.onosproject.incubator.protobuf.models.net.LinkProtoTranslator;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080033import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.DeviceId;
Jian Lic9b4bf12017-06-26 23:50:32 +090035import org.onosproject.net.Link.Type;
Yuta HIGUCHI4c7c90a2016-07-06 14:56:49 -070036import org.onosproject.net.LinkKey;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080037import org.onosproject.net.PortNumber;
38import org.onosproject.net.SparseAnnotations;
39import org.onosproject.net.link.DefaultLinkDescription;
40import org.onosproject.net.link.LinkDescription;
41import org.onosproject.net.link.LinkProviderService;
42import org.slf4j.Logger;
43import org.slf4j.LoggerFactory;
44
Jian Lic9b4bf12017-06-26 23:50:32 +090045import java.util.concurrent.ScheduledExecutorService;
46import java.util.concurrent.TimeUnit;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080047
Jian Lic9b4bf12017-06-26 23:50:32 +090048import static com.google.common.base.Preconditions.checkArgument;
49import static com.google.common.base.Preconditions.checkNotNull;
50import static com.google.common.cache.RemovalListeners.asynchronous;
51import static org.onosproject.net.DeviceId.deviceId;
52import static org.onosproject.net.LinkKey.linkKey;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -080053
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 */
Jian Lic9b4bf12017-06-26 23:50:32 +0900177 private ConnectPoint translate(ConnectPointProto 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 */
Jian Lic9b4bf12017-06-26 23:50:32 +0900190 private LinkDescription translate(LinkDescriptionProto linkDescription) {
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800191 ConnectPoint src = translate(linkDescription.getSrc());
192 ConnectPoint dst = translate(linkDescription.getDst());
Jian Lic9b4bf12017-06-26 23:50:32 +0900193 Type type = translate(linkDescription.getType());
Jian Lid40252c2017-12-08 04:13:20 +0900194 SparseAnnotations annotations = LinkProtoTranslator.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
Jian Lic9b4bf12017-06-26 23:50:32 +0900202 * @return {@link Type Link.Type}
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800203 */
Jian Lic9b4bf12017-06-26 23:50:32 +0900204 private Type translate(LinkTypeProto type) {
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800205 switch (type) {
206 case DIRECT:
Jian Lic9b4bf12017-06-26 23:50:32 +0900207 return Type.DIRECT;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800208 case EDGE:
Jian Lic9b4bf12017-06-26 23:50:32 +0900209 return Type.EDGE;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800210 case INDIRECT:
Jian Lic9b4bf12017-06-26 23:50:32 +0900211 return Type.INDIRECT;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800212 case OPTICAL:
Jian Lic9b4bf12017-06-26 23:50:32 +0900213 return Type.INDIRECT;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800214 case TUNNEL:
Jian Lic9b4bf12017-06-26 23:50:32 +0900215 return Type.TUNNEL;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800216 case VIRTUAL:
Jian Lic9b4bf12017-06-26 23:50:32 +0900217 return Type.VIRTUAL;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800218
219 case UNRECOGNIZED:
220 default:
Jian Lic9b4bf12017-06-26 23:50:32 +0900221 return Type.DIRECT;
HIGUCHI Yuta7c1583c2015-12-03 23:08:54 -0800222 }
223 }
224
225}