blob: 99e79a75010df70d21996e15dc579cfdbf12cbfb [file] [log] [blame]
slowr13fa5b02017-08-08 16:32:31 -07001/*
2 * Copyright 2015-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
17package org.onosproject.xran.controller;
18
19import com.google.common.collect.Sets;
20import io.netty.channel.ChannelHandlerContext;
21import io.netty.channel.sctp.SctpMessage;
22import org.apache.commons.lang.exception.ExceptionUtils;
23import org.apache.felix.scr.annotations.*;
24import org.onosproject.core.ApplicationId;
25import org.onosproject.core.CoreService;
26import org.onosproject.net.config.*;
27import org.onosproject.net.config.basics.SubjectFactories;
28import org.onosproject.net.device.DeviceEvent;
29import org.onosproject.net.device.DeviceListener;
30import org.onosproject.net.device.DeviceService;
31import org.onosproject.net.host.HostEvent;
32import org.onosproject.net.host.HostListener;
33import org.onosproject.net.host.HostService;
34import org.onosproject.xran.XranStore;
35import org.onosproject.xran.codecs.api.*;
slowrc153ad92017-08-16 19:47:52 -070036import org.onosproject.xran.codecs.ber.types.BerInteger;
slowr13fa5b02017-08-08 16:32:31 -070037import org.onosproject.xran.codecs.pdu.*;
38import org.onosproject.xran.entities.RnibCell;
39import org.onosproject.xran.entities.RnibLink;
40import org.onosproject.xran.entities.RnibUe;
slowrc86750e2017-08-22 17:26:47 -070041import org.onosproject.xran.identifiers.EcgiCrntiPair;
slowr13fa5b02017-08-08 16:32:31 -070042import org.onosproject.xran.identifiers.LinkId;
slowrc86750e2017-08-22 17:26:47 -070043import org.onosproject.xran.identifiers.contextUpdateHandler;
slowr13fa5b02017-08-08 16:32:31 -070044import org.onosproject.xran.impl.XranConfig;
45import org.onosproject.xran.providers.XranDeviceListener;
46import org.onosproject.xran.providers.XranHostListener;
slowr13fa5b02017-08-08 16:32:31 -070047import org.onosproject.xran.wrapper.CellMap;
48import org.onosproject.xran.wrapper.LinkMap;
49import org.onosproject.xran.wrapper.UeMap;
slowr13fa5b02017-08-08 16:32:31 -070050import org.slf4j.Logger;
51import org.slf4j.LoggerFactory;
52
53import java.io.IOException;
54import java.util.*;
slowrc86750e2017-08-22 17:26:47 -070055import java.util.concurrent.*;
slowr13fa5b02017-08-08 16:32:31 -070056import java.util.stream.Collectors;
57
58import static org.onosproject.net.DeviceId.deviceId;
slowr67d05e42017-08-11 20:37:22 -070059import static org.onosproject.xran.controller.XranChannelHandler.getSctpMessage;
slowr13fa5b02017-08-08 16:32:31 -070060import static org.onosproject.xran.entities.RnibCell.decodeDeviceId;
61import static org.onosproject.xran.entities.RnibCell.uri;
slowrc86750e2017-08-22 17:26:47 -070062import static org.onosproject.xran.entities.RnibUe.hostIdtoUEId;
slowr13fa5b02017-08-08 16:32:31 -070063
64/**
65 * Created by dimitris on 7/20/17.
66 */
67@Component(immediate = true)
68@Service
69public class XranControllerImpl implements XranController {
70 private static final String XRAN_APP_ID = "org.onosproject.xran";
71 private static final Class<XranConfig> CONFIG_CLASS = XranConfig.class;
72
73 private static final Logger log =
74 LoggerFactory.getLogger(XranControllerImpl.class);
75 /* CONFIG */
76 private final InternalNetworkConfigListener configListener =
77 new InternalNetworkConfigListener();
78 /* VARIABLES */
79 private final Controller controller = new Controller();
80 private XranConfig xranConfig;
81 private ApplicationId appId;
slowrc86750e2017-08-22 17:26:47 -070082 private int northbound_timeout;
slowr13fa5b02017-08-08 16:32:31 -070083 /* Services */
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 private DeviceService deviceService;
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 private HostService hostService;
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 private NetworkConfigRegistry registry;
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 private NetworkConfigService configService;
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 private CoreService coreService;
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 private XranStore xranStore;
96 private ConfigFactory<ApplicationId, XranConfig> xranConfigFactory =
97 new ConfigFactory<ApplicationId, XranConfig>(
98 SubjectFactories.APP_SUBJECT_FACTORY, CONFIG_CLASS, "xran") {
99 @Override
100 public XranConfig createConfig() {
101 return new XranConfig();
102 }
103 };
104 /* WRAPPERS */
105 private CellMap cellMap;
106 private UeMap ueMap;
107 private LinkMap linkMap;
108 /* MAPS */
109 private ConcurrentMap<String, ECGI> legitCells = new ConcurrentHashMap<>();
slowrc86750e2017-08-22 17:26:47 -0700110 private ConcurrentMap<ECGI, SynchronousQueue<String>> hoMap = new ConcurrentHashMap<>();
111 private ConcurrentMap<ECGI, SynchronousQueue<String>> RRMCellMap = new ConcurrentHashMap<>();
112 private ConcurrentMap<CRNTI, SynchronousQueue<String>> scellAddMap = new ConcurrentHashMap<>();
113 private ConcurrentMap<EcgiCrntiPair, contextUpdateHandler> contextUpdateMap = new ConcurrentHashMap<>();
114 /* QUEUE */
115 private BlockingQueue<Long> ueIdQueue = new LinkedBlockingQueue<>();
slowr13fa5b02017-08-08 16:32:31 -0700116 /* AGENTS */
117 private InternalXranDeviceAgent deviceAgent = new InternalXranDeviceAgent();
118 private InternalXranHostAgent hostAgent = new InternalXranHostAgent();
119 private InternalXranPacketAgent packetAgent = new InternalXranPacketAgent();
120 /* LISTENERS */
121 private Set<XranDeviceListener> xranDeviceListeners = new CopyOnWriteArraySet<>();
122 private Set<XranHostListener> xranHostListeners = new CopyOnWriteArraySet<>();
123 private InternalDeviceListener device_listener = new InternalDeviceListener();
124 private InternalHostListener host_listener = new InternalHostListener();
125
126 @Activate
127 public void activate() {
128 appId = coreService.registerApplication(XRAN_APP_ID);
129
130 configService.addListener(configListener);
131 registry.registerConfigFactory(xranConfigFactory);
132 deviceService.addListener(device_listener);
133 hostService.addListener(host_listener);
134
135 cellMap = new CellMap(xranStore);
136 ueMap = new UeMap(xranStore);
slowrd337c932017-08-18 13:54:02 -0700137 linkMap = new LinkMap(xranStore, ueMap);
slowr13fa5b02017-08-08 16:32:31 -0700138
139 xranStore.setController(this);
140
141 log.info("XRAN Controller Started");
142 }
143
144 @Deactivate
145 public void deactivate() {
146 controller.stop();
147
148 deviceService.removeListener(device_listener);
149 hostService.removeListener(host_listener);
150
151 legitCells.clear();
152
153 configService.removeListener(configListener);
154 registry.unregisterConfigFactory(xranConfigFactory);
155
156 log.info("XRAN Controller Stopped");
157 }
158
159 @Override
slowrc86750e2017-08-22 17:26:47 -0700160 public SynchronousQueue<String> sendHORequest(RnibLink link_t, RnibLink link_s) throws InterruptedException {
slowr73b4eae2017-08-17 16:09:09 -0700161 ECGI ecgi_t = link_t.getLinkId().getEcgi(),
162 ecgi_s = link_s.getLinkId().getEcgi();
163
slowrc86750e2017-08-22 17:26:47 -0700164 CRNTI crnti = linkMap.getCrnti(link_t.getLinkId().getUeId());
slowr73b4eae2017-08-17 16:09:09 -0700165 ChannelHandlerContext ctx_t = cellMap.getCtx(ecgi_t),
166 ctx_s = cellMap.getCtx(ecgi_s);
slowr67d05e42017-08-11 20:37:22 -0700167
slowrc86750e2017-08-22 17:26:47 -0700168
169 SynchronousQueue<String> queue = new SynchronousQueue<>();
slowr67d05e42017-08-11 20:37:22 -0700170 try {
slowr73b4eae2017-08-17 16:09:09 -0700171 XrancPdu xrancPdu = HORequest.constructPacket(crnti, ecgi_s, ecgi_t);
slowrc86750e2017-08-22 17:26:47 -0700172
173 hoMap.put(ecgi_s, queue);
174
slowr73b4eae2017-08-17 16:09:09 -0700175 ctx_t.writeAndFlush(getSctpMessage(xrancPdu));
176 ctx_s.writeAndFlush(getSctpMessage(xrancPdu));
slowr67d05e42017-08-11 20:37:22 -0700177 } catch (IOException e) {
178 e.printStackTrace();
179 }
180
slowrc86750e2017-08-22 17:26:47 -0700181 ueIdQueue.put(link_t.getLinkId().getUeId());
slowr67d05e42017-08-11 20:37:22 -0700182
183 return queue;
184 }
185
186 @Override
slowr13fa5b02017-08-08 16:32:31 -0700187 public void addListener(XranDeviceListener listener) {
188 xranDeviceListeners.add(listener);
189 }
190
191 @Override
192 public void addListener(XranHostListener listener) {
193 xranHostListeners.add(listener);
194 }
195
196 @Override
197 public void removeListener(XranDeviceListener listener) {
198 xranDeviceListeners.remove(listener);
199 }
200
201 @Override
202 public void removeListener(XranHostListener listener) {
203 xranHostListeners.remove(listener);
204 }
205
slowr67d05e42017-08-11 20:37:22 -0700206 @Override
slowrc86750e2017-08-22 17:26:47 -0700207 public int getNorthbound_timeout() {
208 return northbound_timeout;
209 }
210
211 @Override
212 public void setNorthbound_timeout(int northbound_timeout) {
213 this.northbound_timeout = northbound_timeout;
214 }
215
216 @Override
slowr8ddc2b12017-08-14 14:13:38 -0700217 public SynchronousQueue<String> sendModifiedRRMConf(RRMConfig rrmConfig, boolean xICIC) {
218 ECGI ecgi = rrmConfig.getEcgi();
slowr67d05e42017-08-11 20:37:22 -0700219 ChannelHandlerContext ctx = cellMap.getCtx(ecgi);
220 try {
slowrc86750e2017-08-22 17:26:47 -0700221 XrancPdu pdu;
slowr73b4eae2017-08-17 16:09:09 -0700222
slowr8ddc2b12017-08-14 14:13:38 -0700223 if (xICIC) {
slowr73b4eae2017-08-17 16:09:09 -0700224 CellConfigReport cellConfigReport = cellMap.get(ecgi).getConf();
225 if (cellConfigReport != null) {
226 pdu = XICICConfig.constructPacket(rrmConfig, cellConfigReport);
227 ctx.writeAndFlush(getSctpMessage(pdu));
228 }
slowr8ddc2b12017-08-14 14:13:38 -0700229 } else {
230 pdu = RRMConfig.constructPacket(rrmConfig);
slowr73b4eae2017-08-17 16:09:09 -0700231 ctx.writeAndFlush(getSctpMessage(pdu));
232 SynchronousQueue<String> queue = new SynchronousQueue<>();
slowrc86750e2017-08-22 17:26:47 -0700233 RRMCellMap.put(ecgi, queue);
slowr73b4eae2017-08-17 16:09:09 -0700234 return queue;
slowr8ddc2b12017-08-14 14:13:38 -0700235 }
slowr67d05e42017-08-11 20:37:22 -0700236 } catch (IOException e) {
237 e.printStackTrace();
238 }
slowr67d05e42017-08-11 20:37:22 -0700239
slowr73b4eae2017-08-17 16:09:09 -0700240 return null;
slowr67d05e42017-08-11 20:37:22 -0700241 }
242
slowr89c2ac12017-08-15 16:20:06 -0700243 @Override
244 public SynchronousQueue<String> sendScellAdd(RnibLink link) {
245 RnibCell secondaryCell = link.getLinkId().getCell(),
246 primaryCell = linkMap.getPrimaryCell(link.getLinkId().getUe());
247 ECGI primaryEcgi = primaryCell.getEcgi();
248 ChannelHandlerContext ctx = cellMap.getCtx(primaryEcgi);
249
slowrc86750e2017-08-22 17:26:47 -0700250 CRNTI crnti = linkMap.getCrnti(link.getLinkId().getUeId());
slowr89c2ac12017-08-15 16:20:06 -0700251
252 CellConfigReport cellReport = secondaryCell.getConf();
253
254 if (cellReport != null) {
255 PCIARFCN pciarfcn = new PCIARFCN();
256 pciarfcn.setPci(cellReport.getPci());
257 pciarfcn.setEarfcnDl(cellReport.getEarfcnDl());
258
259 PropScell propScell = new PropScell();
260 propScell.setPciArfcn(pciarfcn);
261
262 XrancPdu pdu = ScellAdd.constructPacket(primaryEcgi, crnti, propScell);
263 try {
264 ctx.writeAndFlush(getSctpMessage(pdu));
265 SynchronousQueue<String> queue = new SynchronousQueue<>();
slowrc86750e2017-08-22 17:26:47 -0700266 scellAddMap.put(crnti, queue);
slowr89c2ac12017-08-15 16:20:06 -0700267
268 return queue;
269 } catch (IOException e) {
270 log.error(ExceptionUtils.getFullStackTrace(e));
271 e.printStackTrace();
272 }
273 }
274 return null;
275 }
276
277 @Override
278 public boolean sendScellDelete(RnibLink link) {
279 RnibCell secondaryCell = link.getLinkId().getCell(),
280 primaryCell = linkMap.getPrimaryCell(link.getLinkId().getUe());
281 ECGI primaryEcgi = primaryCell.getEcgi();
282 ChannelHandlerContext ctx = cellMap.getCtx(primaryEcgi);
283
slowrc86750e2017-08-22 17:26:47 -0700284 CRNTI crnti = linkMap.getCrnti(link.getLinkId().getUeId());
slowr89c2ac12017-08-15 16:20:06 -0700285
286 CellConfigReport cellReport = secondaryCell.getConf();
287
288 if (cellReport != null) {
289 PCIARFCN pciarfcn = new PCIARFCN();
290 pciarfcn.setPci(cellReport.getPci());
291 pciarfcn.setEarfcnDl(cellReport.getEarfcnDl());
292
293 XrancPdu pdu = ScellDelete.constructPacket(primaryEcgi, crnti, pciarfcn);
294
295 try {
296 ctx.writeAndFlush(getSctpMessage(pdu));
297 link.setType(RnibLink.Type.NON_SERVING);
298 return true;
299 } catch (IOException e) {
300 log.error(ExceptionUtils.getFullStackTrace(e));
301 e.printStackTrace();
302 }
303 }
304 return false;
305 }
306
slowr13fa5b02017-08-08 16:32:31 -0700307 private void restartTimer(RnibUe ue) {
308 Timer timer = new Timer();
309 ue.setTimer(timer);
slowr13fa5b02017-08-08 16:32:31 -0700310 timer.schedule(new TimerTask() {
311 @Override
312 public void run() {
slowr67d05e42017-08-11 20:37:22 -0700313 if (ue.getState() == RnibUe.State.IDLE) {
slowr13fa5b02017-08-08 16:32:31 -0700314 hostAgent.removeConnectedHost(ue);
slowrc86750e2017-08-22 17:26:47 -0700315 log.info("UE is removed after {} ms of IDLE", xranConfig.getIdleUeRemoval());
slowr13fa5b02017-08-08 16:32:31 -0700316 } else {
317 log.info("UE not removed cause its ACTIVE");
318 }
319 }
slowrd337c932017-08-18 13:54:02 -0700320 }, xranConfig.getIdleUeRemoval());
slowr13fa5b02017-08-08 16:32:31 -0700321 }
322
323 private void restartTimer(RnibLink link) {
324 Timer timer = new Timer();
325 link.setTimer(timer);
slowr13fa5b02017-08-08 16:32:31 -0700326 timer.schedule(new TimerTask() {
327 @Override
328 public void run() {
329 LinkId linkId = link.getLinkId();
330 xranStore.removeLink(linkId);
slowrc86750e2017-08-22 17:26:47 -0700331 log.info("Link is removed after not receiving Meas Reports for {} ms", xranConfig.getNoMeasLinkRemoval());
slowr13fa5b02017-08-08 16:32:31 -0700332 }
slowrd337c932017-08-18 13:54:02 -0700333 }, xranConfig.getNoMeasLinkRemoval());
slowr13fa5b02017-08-08 16:32:31 -0700334
335 }
336
337 class InternalDeviceListener implements DeviceListener {
338
339 @Override
340 public void event(DeviceEvent event) {
341 log.info("Device Event {}", event);
342 switch (event.type()) {
343 case DEVICE_ADDED: {
344 try {
345 ECGI ecgi = decodeDeviceId(event.subject().id());
346 RnibCell cell = cellMap.get(ecgi);
347 if (cell != null) {
348 Timer timer = new Timer();
349 timer.scheduleAtFixedRate(
350 new TimerTask() {
351 @Override
352 public void run() {
353 CellConfigReport conf = cell.getConf();
354 if (conf == null) {
355 try {
356 ChannelHandlerContext ctx = cellMap.getCtx(ecgi);
slowr8ddc2b12017-08-14 14:13:38 -0700357 XrancPdu xrancPdu = CellConfigRequest.constructPacket(ecgi);
slowr67d05e42017-08-11 20:37:22 -0700358 ctx.writeAndFlush(getSctpMessage(xrancPdu));
slowr13fa5b02017-08-08 16:32:31 -0700359 } catch (IOException e) {
360 log.error(ExceptionUtils.getFullStackTrace(e));
361 e.printStackTrace();
362 }
363 } else {
slowrd337c932017-08-18 13:54:02 -0700364 List<Object> ueNodes = xranStore.getUeNodes();
365 ueNodes.forEach(object -> {
366 RnibUe ue = (RnibUe) object;
367 try {
368 ECGI primary_ecgi = linkMap.getPrimaryCell(ue).getEcgi();
369 ChannelHandlerContext ctx = cellMap.getCtx(primary_ecgi);
370 RXSigMeasConfig.MeasCells measCells = new RXSigMeasConfig.MeasCells();
371 xranStore.getCellNodes().forEach(cell -> {
372 CellConfigReport cellReport = ((RnibCell) cell).getConf();
373 if (cellReport != null) {
374 PCIARFCN pciarfcn = new PCIARFCN();
375 pciarfcn.setPci(cellReport.getPci());
376 pciarfcn.setEarfcnDl(cellReport.getEarfcnDl());
377 measCells.setPCIARFCN(pciarfcn);
378 }
379 });
380 XrancPdu xrancPdu = RXSigMeasConfig.constructPacket(
381 primary_ecgi,
slowrc86750e2017-08-22 17:26:47 -0700382 ue.getCrnti(),
slowrd337c932017-08-18 13:54:02 -0700383 measCells,
384 xranConfig.getRxSignalInterval()
385 );
386 ue.setMeasConfig(xrancPdu.getBody().getRXSigMeasConfig());
387 ctx.writeAndFlush(getSctpMessage(xrancPdu));
388 } catch (IOException e) {
389 log.warn(ExceptionUtils.getFullStackTrace(e));
390 e.printStackTrace();
391 }
392 });
393
slowr13fa5b02017-08-08 16:32:31 -0700394 try {
slowrd337c932017-08-18 13:54:02 -0700395 ChannelHandlerContext ctx = cellMap.getCtx(ecgi);
slowr8ddc2b12017-08-14 14:13:38 -0700396 XrancPdu xrancPdu = L2MeasConfig.constructPacket(ecgi, xranConfig.getL2MeasInterval());
slowr13fa5b02017-08-08 16:32:31 -0700397 cell.setMeasConfig(xrancPdu.getBody().getL2MeasConfig());
slowr67d05e42017-08-11 20:37:22 -0700398 SctpMessage sctpMessage = getSctpMessage(xrancPdu);
slowr13fa5b02017-08-08 16:32:31 -0700399 ctx.writeAndFlush(sctpMessage);
400 } catch (IOException e) {
401 log.error(ExceptionUtils.getFullStackTrace(e));
402 e.printStackTrace();
403 }
404 timer.cancel();
405 timer.purge();
406 }
407 }
408 },
409 0,
410 xranConfig.getConfigRequestInterval() * 1000
411 );
412 }
413 } catch (IOException e) {
414 log.error(ExceptionUtils.getFullStackTrace(e));
415 e.printStackTrace();
416 }
417 break;
418 }
419 default: {
420 break;
421 }
422 }
423 }
424 }
425
426 class InternalHostListener implements HostListener {
427
428 @Override
429 public void event(HostEvent event) {
430 log.info("Host Event {}", event);
431 switch (event.type()) {
432 case HOST_ADDED:
433 case HOST_MOVED: {
slowrc86750e2017-08-22 17:26:47 -0700434 RnibUe ue = ueMap.get(hostIdtoUEId(event.subject().id()));
slowr13fa5b02017-08-08 16:32:31 -0700435 if (ue != null) {
slowr89c2ac12017-08-15 16:20:06 -0700436 ECGI ecgi_primary = linkMap.getPrimaryCell(ue).getEcgi();
slowr13fa5b02017-08-08 16:32:31 -0700437 RnibCell primary = cellMap.get(ecgi_primary);
438 ue.setMeasConfig(null);
439 if (primary != null) {
440 Timer timer = new Timer();
441 timer.scheduleAtFixedRate(
442 new TimerTask() {
443 @Override
444 public void run() {
slowred74ec72017-08-17 11:25:01 -0700445 if (ue.getCapability() == null && primary.getVersion() >= 3) {
slowr13fa5b02017-08-08 16:32:31 -0700446 try {
447 ChannelHandlerContext ctx = cellMap.getCtx(primary.getEcgi());
slowr8ddc2b12017-08-14 14:13:38 -0700448 XrancPdu xrancPdu = UECapabilityEnquiry.constructPacket(
slowr67d05e42017-08-11 20:37:22 -0700449 primary.getEcgi(),
slowrc86750e2017-08-22 17:26:47 -0700450 ue.getCrnti());
slowr67d05e42017-08-11 20:37:22 -0700451 ctx.writeAndFlush(getSctpMessage(xrancPdu));
slowr13fa5b02017-08-08 16:32:31 -0700452 } catch (IOException e) {
453 log.warn(ExceptionUtils.getFullStackTrace(e));
454 e.printStackTrace();
455 }
456 } else {
slowr13fa5b02017-08-08 16:32:31 -0700457 timer.cancel();
458 timer.purge();
459 }
460 }
461 },
462 0,
463 xranConfig.getConfigRequestInterval() * 1000
464 );
slowred74ec72017-08-17 11:25:01 -0700465 if (ue.getMeasConfig() == null) {
466 try {
467 ChannelHandlerContext ctx = cellMap.getCtx(primary.getEcgi());
468 RXSigMeasConfig.MeasCells measCells = new RXSigMeasConfig.MeasCells();
469 xranStore.getCellNodes().forEach(cell -> {
470 CellConfigReport cellReport = ((RnibCell) cell).getConf();
471 if (cellReport != null) {
472 PCIARFCN pciarfcn = new PCIARFCN();
473 pciarfcn.setPci(cellReport.getPci());
474 pciarfcn.setEarfcnDl(cellReport.getEarfcnDl());
475 measCells.setPCIARFCN(pciarfcn);
476 }
477 });
478 XrancPdu xrancPdu = RXSigMeasConfig.constructPacket(
479 primary.getEcgi(),
slowrc86750e2017-08-22 17:26:47 -0700480 ue.getCrnti(),
slowred74ec72017-08-17 11:25:01 -0700481 measCells,
slowrd337c932017-08-18 13:54:02 -0700482 xranConfig.getRxSignalInterval()
slowred74ec72017-08-17 11:25:01 -0700483 );
484 ue.setMeasConfig(xrancPdu.getBody().getRXSigMeasConfig());
485 ctx.writeAndFlush(getSctpMessage(xrancPdu));
486 } catch (IOException e) {
487 log.warn(ExceptionUtils.getFullStackTrace(e));
488 e.printStackTrace();
489 }
490 }
slowr13fa5b02017-08-08 16:32:31 -0700491 }
492 }
493 break;
494 }
495 default: {
496 break;
497 }
498 }
499 }
500 }
501
502 public class InternalXranDeviceAgent implements XranDeviceAgent {
503
504 private final Logger log = LoggerFactory.getLogger(InternalXranDeviceAgent.class);
505
506 @Override
507 public boolean addConnectedCell(String host, ChannelHandlerContext ctx) {
508 ECGI ecgi = legitCells.get(host);
509
510 if (ecgi == null) {
511 log.error("Device is not a legit source; ignoring...");
512 } else {
513 log.info("Device exists in configuration; registering...");
514 RnibCell storeCell = cellMap.get(ecgi);
515 if (storeCell == null) {
516 storeCell = new RnibCell();
517 storeCell.setEcgi(ecgi);
518 cellMap.put(storeCell, ctx);
519
520 for (XranDeviceListener l : xranDeviceListeners) {
521 l.deviceAdded(storeCell);
522 }
523 return true;
524 } else {
525 log.error("Device already registered; ignoring...");
526 }
527 }
528 ctx.close();
529 return false;
530 }
531
532 @Override
533 public boolean removeConnectedCell(String host) {
534 ECGI ecgi = legitCells.get(host);
535 List<RnibLink> linksByECGI = xranStore.getLinksByECGI(ecgi);
536
537 linksByECGI.forEach(rnibLink -> xranStore.removeLink(rnibLink.getLinkId()));
538
539 if (cellMap.remove(ecgi)) {
540 for (XranDeviceListener l : xranDeviceListeners) {
541 l.deviceRemoved(deviceId(uri(ecgi)));
542 }
543 return true;
544 }
545 return false;
546 }
547 }
548
549 public class InternalXranHostAgent implements XranHostAgent {
550
551 @Override
552 public boolean addConnectedHost(RnibUe ue, RnibCell cell, ChannelHandlerContext ctx) {
553
slowrc86750e2017-08-22 17:26:47 -0700554 if (ue.getId() != null && ueMap.get(ue.getId()) != null) {
slowr13fa5b02017-08-08 16:32:31 -0700555 linkMap.putPrimaryLink(cell, ue);
556
slowrc86750e2017-08-22 17:26:47 -0700557 Set<ECGI> ecgiSet = Sets.newConcurrentHashSet();
558
559 ecgiSet.add(xranStore.getLinksByUeId(ue.getId())
slowr13fa5b02017-08-08 16:32:31 -0700560 .stream()
slowrc86750e2017-08-22 17:26:47 -0700561 .filter(l -> l.getType().equals(RnibLink.Type.SERVING_PRIMARY))
562 .findFirst().get().getLinkId().getEcgi());
slowr13fa5b02017-08-08 16:32:31 -0700563
564 for (XranHostListener l : xranHostListeners) {
565 l.hostAdded(ue, ecgiSet);
566 }
567 return true;
568 } else {
slowrd337c932017-08-18 13:54:02 -0700569 ueMap.put(cell, ue);
slowr13fa5b02017-08-08 16:32:31 -0700570 linkMap.putPrimaryLink(cell, ue);
571
572 Set<ECGI> ecgiSet = Sets.newConcurrentHashSet();
573 ecgiSet.add(cell.getEcgi());
574 for (XranHostListener l : xranHostListeners) {
575 l.hostAdded(ue, ecgiSet);
576 }
577 return true;
578 }
579
580 }
581
582 @Override
583 public boolean removeConnectedHost(RnibUe ue) {
slowrc86750e2017-08-22 17:26:47 -0700584 List<RnibLink> links = xranStore.getLinksByUeId(ue.getId());
slowr13fa5b02017-08-08 16:32:31 -0700585 links.forEach(rnibLink -> xranStore.removeLink(rnibLink.getLinkId()));
slowrc86750e2017-08-22 17:26:47 -0700586 if (ueMap.remove(ue.getId())) {
slowr13fa5b02017-08-08 16:32:31 -0700587 for (XranHostListener l : xranHostListeners) {
588 l.hostRemoved(ue.getHostId());
589 }
590 return true;
591 }
592 return false;
593 }
594 }
595
596 public class InternalXranPacketAgent implements XranPacketProcessor {
597 @Override
slowrc86750e2017-08-22 17:26:47 -0700598 public void handlePacket(XrancPdu recv_pdu, ChannelHandlerContext ctx) throws IOException, InterruptedException {
slowr13fa5b02017-08-08 16:32:31 -0700599 XrancPdu send_pdu;
600
601 int apiID = recv_pdu.getHdr().getApiId().intValue();
602 log.debug("Received message: {}", recv_pdu);
603 switch (apiID) {
604 case 1: {
605 // Decode Cell config report.
606 CellConfigReport report = recv_pdu.getBody().getCellConfigReport();
607
608 ECGI ecgi = report.getEcgi();
609
610 RnibCell cell = xranStore.getCell(ecgi);
slowr8ddc2b12017-08-14 14:13:38 -0700611 cell.setVersion(recv_pdu.getHdr().getVer().toString());
slowr13fa5b02017-08-08 16:32:31 -0700612 cell.setConf(report);
slowr507a0822017-08-17 20:54:18 -0700613 cellMap.putPciArfcn(cell);
slowr13fa5b02017-08-08 16:32:31 -0700614 break;
615 }
616 case 2: {
617 // Decode UE Admission Request.
618 UEAdmissionRequest ueAdmissionRequest = recv_pdu.getBody().getUEAdmissionRequest();
619
620 ECGI ecgi = ueAdmissionRequest.getEcgi();
621 if (xranStore.getCell(ecgi) != null) {
622 CRNTI crnti = ueAdmissionRequest.getCrnti();
slowr8ddc2b12017-08-14 14:13:38 -0700623 send_pdu = UEAdmissionResponse.constructPacket(ecgi, crnti, xranConfig.admissionFlag());
slowr67d05e42017-08-11 20:37:22 -0700624 ctx.writeAndFlush(getSctpMessage(send_pdu));
slowr13fa5b02017-08-08 16:32:31 -0700625 } else {
626 log.warn("Could not find ECGI in registered cells: {}", ecgi);
627 }
628 break;
629 }
630 case 4: {
631 // Decode UE Admission Status.
632 UEAdmissionStatus ueAdmissionStatus = recv_pdu.getBody().getUEAdmissionStatus();
633
slowrd337c932017-08-18 13:54:02 -0700634 RnibUe ue = ueMap.get(ueAdmissionStatus.getEcgi(), ueAdmissionStatus.getCrnti());
slowr13fa5b02017-08-08 16:32:31 -0700635 if (ue != null) {
636 if (ueAdmissionStatus.getAdmEstStatus().value.intValue() == 0) {
slowr67d05e42017-08-11 20:37:22 -0700637 ue.setState(RnibUe.State.ACTIVE);
slowr13fa5b02017-08-08 16:32:31 -0700638 } else {
slowr67d05e42017-08-11 20:37:22 -0700639 ue.setState(RnibUe.State.IDLE);
slowr13fa5b02017-08-08 16:32:31 -0700640 }
641 }
slowrc86750e2017-08-22 17:26:47 -0700642
643 if (ueAdmissionStatus.getAdmEstStatus().value.intValue() == 0) {
644 EcgiCrntiPair ecgiCrntiPair = EcgiCrntiPair.valueOf(ueAdmissionStatus.getEcgi(), ueAdmissionStatus.getCrnti());
645 contextUpdateMap.compute(ecgiCrntiPair, (k, v) -> {
646 if (v == null) {
647 v = new contextUpdateHandler();
648 }
649 if (v.setAdmissionStatus(ueAdmissionStatus)) {
650 handleContextUpdate(v.getContextUpdate(), ctx, false);
651 }
652 return v;
653 });
654 }
slowr13fa5b02017-08-08 16:32:31 -0700655 break;
656 }
657 case 5: {
slowrc86750e2017-08-22 17:26:47 -0700658 // Decode UE Context Update.
slowr8ddc2b12017-08-14 14:13:38 -0700659 UEContextUpdate ueContextUpdate = recv_pdu.getBody().getUEContextUpdate();
slowrc86750e2017-08-22 17:26:47 -0700660 EcgiCrntiPair ecgiCrntiPair = EcgiCrntiPair.valueOf(ueContextUpdate.getEcgi(), ueContextUpdate.getCrnti());
slowr13fa5b02017-08-08 16:32:31 -0700661
slowrc86750e2017-08-22 17:26:47 -0700662 contextUpdateMap.compute(ecgiCrntiPair, (k, v) -> {
663 if (v == null) {
664 v = new contextUpdateHandler();
665 }
666 if (v.setContextUpdate(ueContextUpdate)) {
667 HOComplete hoComplete = v.getHoComplete();
668 handleContextUpdate(ueContextUpdate, ctx, hoComplete != null);
669 if (hoComplete != null) {
670 try {
671 hoMap.get(hoComplete.getEcgiS()).put("Hand Over Completed");
672 } catch (InterruptedException e) {
673 log.error(ExceptionUtils.getFullStackTrace(e));
674 e.printStackTrace();
675 } finally {
676 hoMap.remove(hoComplete.getEcgiS());
677 }
678 }
679 }
680 return v;
681 });
slowr73b4eae2017-08-17 16:09:09 -0700682
slowr13fa5b02017-08-08 16:32:31 -0700683 break;
684 }
685 case 6: {
686 // Decode UE Reconfig_Ind.
687 UEReconfigInd ueReconfigInd = recv_pdu.getBody().getUEReconfigInd();
slowrd337c932017-08-18 13:54:02 -0700688 RnibUe ue = ueMap.get(ueReconfigInd.getEcgi(), ueReconfigInd.getCrntiOld());
slowr13fa5b02017-08-08 16:32:31 -0700689
690 if (ue != null) {
slowrc86750e2017-08-22 17:26:47 -0700691 ue.setCrnti(ueReconfigInd.getCrntiNew());
slowr13fa5b02017-08-08 16:32:31 -0700692 } else {
693 log.warn("Could not find UE with this CRNTI: {}", ueReconfigInd.getCrntiOld());
694 }
695 break;
696 }
697 case 7: {
698 // If xRANc wants to deactivate UE, we pass UEReleaseInd from xRANc to eNB.
699 // Decode UE Release_Ind.
700 UEReleaseInd ueReleaseInd = recv_pdu.getBody().getUEReleaseInd();
slowrd337c932017-08-18 13:54:02 -0700701 RnibUe ue = ueMap.get(ueReleaseInd.getEcgi(), ueReleaseInd.getCrnti());
slowr13fa5b02017-08-08 16:32:31 -0700702 if (ue != null) {
slowr67d05e42017-08-11 20:37:22 -0700703 ue.setState(RnibUe.State.IDLE);
slowr13fa5b02017-08-08 16:32:31 -0700704 restartTimer(ue);
705 }
706 break;
707 }
708 case 8: {
709 // Decode Bearer Adm Request
710 BearerAdmissionRequest bearerAdmissionRequest = recv_pdu.getBody().getBearerAdmissionRequest();
711
712 ECGI ecgi = bearerAdmissionRequest.getEcgi();
713 CRNTI crnti = bearerAdmissionRequest.getCrnti();
714 ERABParams erabParams = bearerAdmissionRequest.getErabParams();
715 RnibLink link = linkMap.get(ecgi, crnti);
716 if (link != null) {
717 link.setBearerParameters(erabParams);
718 } else {
719 log.warn("Could not find link between {}-{}", ecgi, crnti);
720 }
721
722 BerInteger numErabs = bearerAdmissionRequest.getNumErabs();
slowr8ddc2b12017-08-14 14:13:38 -0700723 // Encode and send Bearer Admission Response
724 send_pdu = BearerAdmissionResponse.constructPacket(ecgi, crnti, erabParams, numErabs, xranConfig.bearerFlag());
slowr67d05e42017-08-11 20:37:22 -0700725 ctx.writeAndFlush(getSctpMessage(send_pdu));
slowr13fa5b02017-08-08 16:32:31 -0700726 break;
727 }
728 case 10: {
729 //Decode Bearer Admission Status
730 BearerAdmissionStatus bearerAdmissionStatus = recv_pdu.getBody().getBearerAdmissionStatus();
slowr8ddc2b12017-08-14 14:13:38 -0700731 break;
slowr13fa5b02017-08-08 16:32:31 -0700732// ECGI ecgi = bearerAdmissionStatus.getEcgi();
733// CRNTI crnti = bearerAdmissionStatus.getCrnti();
734//
735// RnibLink link = linkMap.get(ecgi, crnti);
slowr13fa5b02017-08-08 16:32:31 -0700736 }
737 case 11: {
738 //Decode Bearer Release Ind
739 BearerReleaseInd bearerReleaseInd = recv_pdu.getBody().getBearerReleaseInd();
740
741 ECGI ecgi = bearerReleaseInd.getEcgi();
742 CRNTI crnti = bearerReleaseInd.getCrnti();
743 RnibLink link = linkMap.get(ecgi, crnti);
744
745 List<ERABID> erabidsRelease = bearerReleaseInd.getErabIds().getERABID();
746 List<ERABParamsItem> erabParamsItem = link.getBearerParameters().getERABParamsItem();
747
748 List<ERABParamsItem> unreleased = erabParamsItem
749 .stream()
750 .filter(item -> {
751 Optional<ERABID> any = erabidsRelease.stream().filter(id -> id.equals(item.getId())).findAny();
752 return !any.isPresent();
753 }).collect(Collectors.toList());
754
755 link.getBearerParameters().setERABParamsItem(new ArrayList<>(unreleased));
slowr13fa5b02017-08-08 16:32:31 -0700756 break;
757 }
758 case 13: {
slowr67d05e42017-08-11 20:37:22 -0700759 HOFailure hoFailure = recv_pdu.getBody().getHOFailure();
760
761 try {
slowrc86750e2017-08-22 17:26:47 -0700762 hoMap.get(hoFailure.getEcgi())
slowr67d05e42017-08-11 20:37:22 -0700763 .put("Hand Over Failed with cause: " + hoFailure.getCause());
764 } catch (InterruptedException e) {
765 log.error(ExceptionUtils.getFullStackTrace(e));
766 e.printStackTrace();
767 } finally {
slowrc86750e2017-08-22 17:26:47 -0700768 hoMap.remove(hoFailure.getEcgi());
769 ueIdQueue.take();
slowr67d05e42017-08-11 20:37:22 -0700770 }
771 break;
slowr8ddc2b12017-08-14 14:13:38 -0700772
slowr67d05e42017-08-11 20:37:22 -0700773 }
slowr8ddc2b12017-08-14 14:13:38 -0700774 case 14: {
slowr67d05e42017-08-11 20:37:22 -0700775 HOComplete hoComplete = recv_pdu.getBody().getHOComplete();
776
slowrc86750e2017-08-22 17:26:47 -0700777 EcgiCrntiPair ecgiCrntiPair = EcgiCrntiPair.valueOf(hoComplete.getEcgiT(), hoComplete.getCrntiNew());
778 contextUpdateMap.compute(ecgiCrntiPair, (k, v) -> {
779 if (v == null) {
780 v = new contextUpdateHandler();
781 }
782 if (v.setHoComplete(hoComplete)) {
783 handleContextUpdate(v.getContextUpdate(), ctx, true);
784
785 try {
786 hoMap.get(hoComplete.getEcgiS()).put("Hand Over Completed");
787 } catch (InterruptedException e) {
788 log.error(ExceptionUtils.getFullStackTrace(e));
789 e.printStackTrace();
790 } finally {
791 hoMap.remove(hoComplete.getEcgiS());
792 }
793 }
794 return v;
795 });
796
slowr67d05e42017-08-11 20:37:22 -0700797 break;
798 }
slowr8ddc2b12017-08-14 14:13:38 -0700799
800 case 16: {
slowr13fa5b02017-08-08 16:32:31 -0700801 // Decode RX Sig Meas Report.
802 RXSigMeasReport rxSigMeasReport = recv_pdu.getBody().getRXSigMeasReport();
803 List<RXSigReport> rxSigReportList = rxSigMeasReport.getCellMeasReports().getRXSigReport();
804
slowrc86750e2017-08-22 17:26:47 -0700805 RnibUe ue = ueMap.get(rxSigMeasReport.getEcgi(), rxSigMeasReport.getCrnti());
806 if (ue != null) {
807 Long ueId = ue.getId();
slowr13fa5b02017-08-08 16:32:31 -0700808
slowrc86750e2017-08-22 17:26:47 -0700809 if (!rxSigReportList.isEmpty()) {
810 rxSigReportList.forEach(rxSigReport -> {
811 RnibCell cell = cellMap.get(rxSigReport.getPciArfcn());
812 if (cell != null) {
813 ECGI ecgi = cell.getEcgi();
814
815 RnibLink link = linkMap.get(ecgi, ueId);
816 if (link == null) {
817 log.warn("Could not find link between: {}-{} | Creating non-serving link..", ecgi, ueId);
818 link = linkMap.putNonServingLink(cell, ueId);
slowrda15d9a2017-08-18 10:33:31 -0700819 }
820
slowrc86750e2017-08-22 17:26:47 -0700821 if (link != null) {
822 if (link.getType().equals(RnibLink.Type.NON_SERVING)) {
823 restartTimer(link);
824 }
slowr13fa5b02017-08-08 16:32:31 -0700825
slowrc86750e2017-08-22 17:26:47 -0700826 RSRQRange rsrq = rxSigReport.getRsrq();
827 RSRPRange rsrp = rxSigReport.getRsrp();
828
829 RnibLink.LinkQuality quality = link.getQuality();
830 quality.setRX(new RnibLink.LinkQuality.RX(
831 rsrp.value.intValue() - 140,
832 (rsrq.value.intValue() * 0.5) - 19.5
833 ));
834 }
835 } else {
836 log.warn("case 16: Could not find cell with PCI-ARFCN: {}", rxSigReport.getPciArfcn());
slowr13fa5b02017-08-08 16:32:31 -0700837 }
slowrc86750e2017-08-22 17:26:47 -0700838 });
839 }
slowr13fa5b02017-08-08 16:32:31 -0700840 }
841 break;
842 }
slowr8ddc2b12017-08-14 14:13:38 -0700843 case 18: {
slowr13fa5b02017-08-08 16:32:31 -0700844 RadioMeasReportPerUE radioMeasReportPerUE = recv_pdu.getBody().getRadioMeasReportPerUE();
845
slowrc86750e2017-08-22 17:26:47 -0700846 RnibUe ue = ueMap.get(radioMeasReportPerUE.getEcgi(), radioMeasReportPerUE.getCrnti());
847 if (ue != null) {
848 Long ueId = ue.getId();
849 List<RadioRepPerServCell> servCells = radioMeasReportPerUE.getRadioReportServCells().getRadioRepPerServCell();
slowr13fa5b02017-08-08 16:32:31 -0700850
slowrc86750e2017-08-22 17:26:47 -0700851 servCells.forEach(servCell -> {
852 RnibCell cell = cellMap.get(servCell.getPciArfcn());
853 if (cell != null) {
854 RnibLink link = linkMap.get(cell.getEcgi(), ueId);
855 if (link != null) {
856 RadioRepPerServCell.CqiHist cqiHist = servCell.getCqiHist();
857 RnibLink.LinkQuality quality = link.getQuality();
slowr13fa5b02017-08-08 16:32:31 -0700858
slowrc86750e2017-08-22 17:26:47 -0700859 final double[] values = {0, 0, 0};
860 final int[] i = {1};
861 cqiHist.getBerInteger().forEach(value -> {
862 values[0] = Math.max(values[0], value.intValue());
863 values[1] += i[0] * value.intValue();
864 values[2] += value.intValue();
865 i[0]++;
866 });
slowr13fa5b02017-08-08 16:32:31 -0700867
slowrc86750e2017-08-22 17:26:47 -0700868 quality.setCQI(new RnibLink.LinkQuality.CQI(
869 cqiHist,
870 values[0],
871 values[1] / values[0]
872 ));
slowr13fa5b02017-08-08 16:32:31 -0700873
slowrc86750e2017-08-22 17:26:47 -0700874 } else {
875 log.warn("Could not find link between: {}-{}", cell.getEcgi(), ueId);
876 }
slowr13fa5b02017-08-08 16:32:31 -0700877 } else {
slowrc86750e2017-08-22 17:26:47 -0700878 log.warn("case 18: Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
slowr13fa5b02017-08-08 16:32:31 -0700879 }
slowrc86750e2017-08-22 17:26:47 -0700880 });
881 }
slowr67d05e42017-08-11 20:37:22 -0700882 break;
slowr13fa5b02017-08-08 16:32:31 -0700883 }
slowr8ddc2b12017-08-14 14:13:38 -0700884 case 19: {
slowr13fa5b02017-08-08 16:32:31 -0700885 RadioMeasReportPerCell radioMeasReportPerCell = recv_pdu.getBody().getRadioMeasReportPerCell();
886 break;
887 }
slowr8ddc2b12017-08-14 14:13:38 -0700888 case 20: {
slowr13fa5b02017-08-08 16:32:31 -0700889 SchedMeasReportPerUE schedMeasReportPerUE = recv_pdu.getBody().getSchedMeasReportPerUE();
slowr13fa5b02017-08-08 16:32:31 -0700890
slowrc86750e2017-08-22 17:26:47 -0700891 RnibUe ue = ueMap.get(schedMeasReportPerUE.getEcgi(), schedMeasReportPerUE.getCrnti());
892 if (ue != null) {
893 Long ueId = ue.getId();
slowr13fa5b02017-08-08 16:32:31 -0700894
slowrc86750e2017-08-22 17:26:47 -0700895 List<SchedMeasRepPerServCell> servCells = schedMeasReportPerUE.getSchedReportServCells()
896 .getSchedMeasRepPerServCell();
897
898 servCells.forEach(servCell -> {
899 RnibCell cell = cellMap.get(servCell.getPciArfcn());
900 if (cell != null) {
901 RnibLink link = linkMap.get(cell.getEcgi(), ueId);
902 if (link != null) {
903 link.getQuality().setMCS(new RnibLink.LinkQuality.MCS(
904 servCell.getMcsDl(),
905 servCell.getMcsUl()
906 ));
907
908 link.setResourceUsage(new RnibLink.ResourceUsage(
909 servCell.getPrbUsage().getPrbUsageDl(),
910 servCell.getPrbUsage().getPrbUsageUl()
911 ));
912 } else {
913 log.warn("Could not find link between: {}-{}", cell.getEcgi(), ueId);
914 }
slowr13fa5b02017-08-08 16:32:31 -0700915 } else {
slowrc86750e2017-08-22 17:26:47 -0700916 log.warn("case 20: Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
slowr13fa5b02017-08-08 16:32:31 -0700917 }
slowrc86750e2017-08-22 17:26:47 -0700918 });
919 }
slowr13fa5b02017-08-08 16:32:31 -0700920 break;
921 }
slowr8ddc2b12017-08-14 14:13:38 -0700922 case 21: {
slowr13fa5b02017-08-08 16:32:31 -0700923 SchedMeasReportPerCell schedMeasReportPerCell = recv_pdu.getBody().getSchedMeasReportPerCell();
slowr13fa5b02017-08-08 16:32:31 -0700924 RnibCell cell = cellMap.get(schedMeasReportPerCell.getEcgi());
925 if (cell != null) {
slowrc153ad92017-08-16 19:47:52 -0700926 cell.setPrbUsage(new RnibCell.PrbUsageContainer(
927 schedMeasReportPerCell.getPrbUsagePcell(),
928 schedMeasReportPerCell.getPrbUsageScell()
929 ));
930
slowr13fa5b02017-08-08 16:32:31 -0700931 cell.setQci(schedMeasReportPerCell.getQciVals());
932 } else {
933 log.warn("Could not find cell with ECGI: {}", schedMeasReportPerCell.getEcgi());
934 }
935 break;
936 }
slowr8ddc2b12017-08-14 14:13:38 -0700937 case 22: {
slowr13fa5b02017-08-08 16:32:31 -0700938 PDCPMeasReportPerUe pdcpMeasReportPerUe = recv_pdu.getBody().getPDCPMeasReportPerUe();
939
slowrc86750e2017-08-22 17:26:47 -0700940 RnibUe ue = ueMap.get(pdcpMeasReportPerUe.getEcgi(), pdcpMeasReportPerUe.getCrnti());
941 if (ue != null) {
942 Long ueId = ue.getId();
943 RnibLink link = linkMap.get(pdcpMeasReportPerUe.getEcgi(), ueId);
944 if (link != null) {
945 link.setPdcpThroughput(new RnibLink.PDCPThroughput(
946 pdcpMeasReportPerUe.getThroughputDl(),
947 pdcpMeasReportPerUe.getThroughputUl()
948 ));
slowrc153ad92017-08-16 19:47:52 -0700949
slowrc86750e2017-08-22 17:26:47 -0700950 link.setPdcpPackDelay(new RnibLink.PDCPPacketDelay(
951 pdcpMeasReportPerUe.getPktDelayDl(),
952 pdcpMeasReportPerUe.getPktDelayUl()
953 ));
954 } else {
955 log.warn("Could not find link between: {}-{}", pdcpMeasReportPerUe.getEcgi(), ueId);
956 }
slowr13fa5b02017-08-08 16:32:31 -0700957 }
958 break;
959 }
slowr8ddc2b12017-08-14 14:13:38 -0700960 case 24: {
961 // Decode UE Capability Info
962 UECapabilityInfo capabilityInfo = recv_pdu.getBody().getUECapabilityInfo();
963
slowrd337c932017-08-18 13:54:02 -0700964 RnibUe ue = ueMap.get(capabilityInfo.getEcgi(), capabilityInfo.getCrnti());
slowr8ddc2b12017-08-14 14:13:38 -0700965 if (ue != null) {
966 ue.setCapability(capabilityInfo);
967 } else {
968 log.warn("Could not find UE with this CRNTI: {}", capabilityInfo.getCrnti());
969 }
970 break;
971 }
972 case 25: {
973 // Don't know what will invoke sending UE CAPABILITY ENQUIRY
974 // Encode and send UE CAPABILITY ENQUIRY
975 UECapabilityEnquiry ueCapabilityEnquiry = recv_pdu.getBody().getUECapabilityEnquiry();
976 XrancPdu xrancPdu = UECapabilityEnquiry.constructPacket(ueCapabilityEnquiry.getEcgi(), ueCapabilityEnquiry.getCrnti());
977 ctx.writeAndFlush(getSctpMessage(xrancPdu));
978 break;
979 }
slowr89c2ac12017-08-15 16:20:06 -0700980 case 27: {
981 //Decode ScellAddStatus
982 ScellAddStatus scellAddStatus = recv_pdu.getBody().getScellAddStatus();
slowrc86750e2017-08-22 17:26:47 -0700983 RnibUe ue = ueMap.get(scellAddStatus.getEcgi(), scellAddStatus.getCrnti());
984 if (ue != null) {
985 Long ueId = ue.getId();
986 try {
987 scellAddMap.get(scellAddStatus.getCrnti()).put("Scell's status: " + scellAddStatus.getStatus());
988 if (scellAddStatus.getStatus().getBerEnum().get(0).value.intValue() == 0) {
slowr89c2ac12017-08-15 16:20:06 -0700989
slowrc86750e2017-08-22 17:26:47 -0700990 scellAddStatus.getScellsInd().getPCIARFCN().forEach(
991 pciarfcn -> {
992 RnibCell cell = cellMap.get(pciarfcn);
993 RnibLink link = linkMap.get(cell.getEcgi(), ueId);
994 link.setType(RnibLink.Type.SERVING_SECONDARY_CA);
995 }
996 );
997 } else {
998 log.error("Scell addition failed.");
999 }
1000 } catch (InterruptedException e) {
1001 log.error(ExceptionUtils.getFullStackTrace(e));
1002 e.printStackTrace();
1003 } finally {
1004 scellAddMap.remove(scellAddStatus.getCrnti());
slowr89c2ac12017-08-15 16:20:06 -07001005 }
slowr89c2ac12017-08-15 16:20:06 -07001006 }
1007 break;
1008 }
1009 // TODO: 28: ScellDelete
slowr8ddc2b12017-08-14 14:13:38 -07001010 case 30: {
1011 // Decode RRMConfig Status
slowr67d05e42017-08-11 20:37:22 -07001012 RRMConfigStatus rrmConfigStatus = recv_pdu.getBody().getRRMConfigStatus();
1013 try {
slowrc86750e2017-08-22 17:26:47 -07001014 RRMCellMap.get(rrmConfigStatus.getEcgi())
slowr67d05e42017-08-11 20:37:22 -07001015 .put("RRM Config's status: " + rrmConfigStatus.getStatus());
1016 } catch (InterruptedException e) {
1017 log.error(ExceptionUtils.getFullStackTrace(e));
1018 e.printStackTrace();
1019 } finally {
slowrc86750e2017-08-22 17:26:47 -07001020 RRMCellMap.remove(rrmConfigStatus.getEcgi());
slowr67d05e42017-08-11 20:37:22 -07001021 }
1022 break;
1023 }
slowr8ddc2b12017-08-14 14:13:38 -07001024 //TODO Case 31: SeNBAdd 32: SeNBAddStatus 33: SeNBDelete
slowr13fa5b02017-08-08 16:32:31 -07001025 case 34: {
1026 TrafficSplitConfig trafficSplitConfig = recv_pdu.getBody().getTrafficSplitConfig();
1027
slowrc86750e2017-08-22 17:26:47 -07001028 RnibUe ue = ueMap.get(trafficSplitConfig.getEcgi(), trafficSplitConfig.getCrnti());
1029 if (ue != null) {
1030 Long ueId = ue.getId();
1031 List<TrafficSplitPercentage> splitPercentages = trafficSplitConfig.getTrafficSplitPercent().getTrafficSplitPercentage();
slowr13fa5b02017-08-08 16:32:31 -07001032
slowrc86750e2017-08-22 17:26:47 -07001033 splitPercentages.forEach(trafficSplitPercentage -> {
1034 RnibCell cell = cellMap.get(trafficSplitPercentage.getEcgi());
1035 if (cell != null) {
1036 RnibLink link = linkMap.get(cell.getEcgi(), ueId);
1037 if (link != null) {
1038 link.setTrafficPercent(trafficSplitPercentage);
1039 } else {
1040 log.warn("Could not find link between: {}-{}", cell.getEcgi(), ueId);
1041 }
slowr13fa5b02017-08-08 16:32:31 -07001042 } else {
slowrc86750e2017-08-22 17:26:47 -07001043 log.warn("Could not find cell with ECGI: {}", trafficSplitConfig.getEcgi());
slowr13fa5b02017-08-08 16:32:31 -07001044 }
slowrc86750e2017-08-22 17:26:47 -07001045 });
1046 }
slowr67d05e42017-08-11 20:37:22 -07001047 break;
slowr13fa5b02017-08-08 16:32:31 -07001048 }
1049 default: {
slowr60d4d102017-08-16 18:33:58 -07001050 log.warn("Wrong API ID: {}", recv_pdu);
slowr67d05e42017-08-11 20:37:22 -07001051 break;
slowr13fa5b02017-08-08 16:32:31 -07001052 }
1053 }
1054
1055 }
slowrc86750e2017-08-22 17:26:47 -07001056
1057 private void handleContextUpdate(UEContextUpdate contextUpdate, ChannelHandlerContext ctx, boolean handoff) {
1058 RnibUe ue;
1059 RnibCell cell = xranStore.getCell(contextUpdate.getEcgi());
1060
1061 if (handoff) {
1062 try {
1063 ue = ueMap.get(ueIdQueue.take());
1064 } catch (InterruptedException e) {
1065 e.printStackTrace();
1066 log.error(ExceptionUtils.getFullStackTrace(e));
1067 ue = new RnibUe();
1068 }
1069 } else {
1070 ue = new RnibUe();
1071 }
1072
1073 ue.setMmeS1apId(contextUpdate.getMMEUES1APID());
1074 ue.setEnbS1apId(contextUpdate.getENBUES1APID());
1075 ue.setCrnti(contextUpdate.getCrnti());
1076
1077 hostAgent.addConnectedHost(ue, cell, ctx);
1078 }
slowr13fa5b02017-08-08 16:32:31 -07001079 }
1080
1081 class InternalNetworkConfigListener implements NetworkConfigListener {
1082
1083 @Override
1084 public void event(NetworkConfigEvent event) {
1085 switch (event.type()) {
1086 case CONFIG_REGISTERED:
1087 break;
1088 case CONFIG_UNREGISTERED:
1089 break;
1090 case CONFIG_ADDED:
1091 case CONFIG_UPDATED:
1092 if (event.configClass() == CONFIG_CLASS) {
1093 handleConfigEvent(event.config());
1094 }
1095 break;
1096 case CONFIG_REMOVED:
1097 break;
1098 default:
1099 break;
1100 }
1101 }
1102
1103 private void handleConfigEvent(Optional<Config> config) {
1104 if (!config.isPresent()) {
1105 return;
1106 }
1107
1108 xranConfig = (XranConfig) config.get();
1109
slowrd337c932017-08-18 13:54:02 -07001110 northbound_timeout = xranConfig.getNorthBoundTimeout();
1111
slowr13fa5b02017-08-08 16:32:31 -07001112 legitCells.putAll(xranConfig.activeCellSet());
1113
1114 controller.start(deviceAgent, hostAgent, packetAgent, xranConfig.getXrancPort());
1115 }
1116 }
1117}