blob: 36b4c071704d2bedc7fe42662c2b177a741814f5 [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.*;
36import org.onosproject.xran.codecs.pdu.*;
37import org.onosproject.xran.entities.RnibCell;
38import org.onosproject.xran.entities.RnibLink;
39import org.onosproject.xran.entities.RnibUe;
40import org.onosproject.xran.identifiers.LinkId;
41import org.onosproject.xran.impl.XranConfig;
42import org.onosproject.xran.providers.XranDeviceListener;
43import org.onosproject.xran.providers.XranHostListener;
44import org.onosproject.xran.samplemessages.*;
45import org.onosproject.xran.wrapper.CellMap;
46import org.onosproject.xran.wrapper.LinkMap;
47import org.onosproject.xran.wrapper.UeMap;
48import org.openmuc.jasn1.ber.types.BerInteger;
49import org.slf4j.Logger;
50import org.slf4j.LoggerFactory;
51
52import java.io.IOException;
53import java.util.*;
54import java.util.concurrent.ConcurrentHashMap;
55import java.util.concurrent.ConcurrentMap;
56import java.util.concurrent.CopyOnWriteArraySet;
57import java.util.stream.Collectors;
58
59import static org.onosproject.net.DeviceId.deviceId;
60import static org.onosproject.xran.entities.RnibCell.decodeDeviceId;
61import static org.onosproject.xran.entities.RnibCell.uri;
62import static org.onosproject.xran.entities.RnibUe.UeState;
63import static org.onosproject.xran.entities.RnibUe.hostIdtoMME;
64
65/**
66 * Created by dimitris on 7/20/17.
67 */
68@Component(immediate = true)
69@Service
70public class XranControllerImpl implements XranController {
71 private static final String XRAN_APP_ID = "org.onosproject.xran";
72 private static final Class<XranConfig> CONFIG_CLASS = XranConfig.class;
73
74 private static final Logger log =
75 LoggerFactory.getLogger(XranControllerImpl.class);
76 /* CONFIG */
77 private final InternalNetworkConfigListener configListener =
78 new InternalNetworkConfigListener();
79 /* VARIABLES */
80 private final Controller controller = new Controller();
81 private XranConfig xranConfig;
82 private ApplicationId appId;
83 /* 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<>();
110 /* AGENTS */
111 private InternalXranDeviceAgent deviceAgent = new InternalXranDeviceAgent();
112 private InternalXranHostAgent hostAgent = new InternalXranHostAgent();
113 private InternalXranPacketAgent packetAgent = new InternalXranPacketAgent();
114 /* LISTENERS */
115 private Set<XranDeviceListener> xranDeviceListeners = new CopyOnWriteArraySet<>();
116 private Set<XranHostListener> xranHostListeners = new CopyOnWriteArraySet<>();
117 private InternalDeviceListener device_listener = new InternalDeviceListener();
118 private InternalHostListener host_listener = new InternalHostListener();
119
120 @Activate
121 public void activate() {
122 appId = coreService.registerApplication(XRAN_APP_ID);
123
124 configService.addListener(configListener);
125 registry.registerConfigFactory(xranConfigFactory);
126 deviceService.addListener(device_listener);
127 hostService.addListener(host_listener);
128
129 cellMap = new CellMap(xranStore);
130 ueMap = new UeMap(xranStore);
131 linkMap = new LinkMap(xranStore);
132
133 xranStore.setController(this);
134
135 log.info("XRAN Controller Started");
136 }
137
138 @Deactivate
139 public void deactivate() {
140 controller.stop();
141
142 deviceService.removeListener(device_listener);
143 hostService.removeListener(host_listener);
144
145 legitCells.clear();
146
147 configService.removeListener(configListener);
148 registry.unregisterConfigFactory(xranConfigFactory);
149
150 log.info("XRAN Controller Stopped");
151 }
152
153 @Override
154 public void addListener(XranDeviceListener listener) {
155 xranDeviceListeners.add(listener);
156 }
157
158 @Override
159 public void addListener(XranHostListener listener) {
160 xranHostListeners.add(listener);
161 }
162
163 @Override
164 public void removeListener(XranDeviceListener listener) {
165 xranDeviceListeners.remove(listener);
166 }
167
168 @Override
169 public void removeListener(XranHostListener listener) {
170 xranHostListeners.remove(listener);
171 }
172
173 private void restartTimer(RnibUe ue) {
174 Timer timer = new Timer();
175 ue.setTimer(timer);
176 log.info("Starting UE timer...");
177 timer.schedule(new TimerTask() {
178 @Override
179 public void run() {
180 if (ue.getUeState() == UeState.IDLE) {
181 hostAgent.removeConnectedHost(ue);
182 log.info("UE is removed after 10 seconds of IDLE");
183 } else {
184 log.info("UE not removed cause its ACTIVE");
185 }
186 }
187 }, 10000);
188 }
189
190 private void restartTimer(RnibLink link) {
191 Timer timer = new Timer();
192 link.setTimer(timer);
193 log.info("Starting Link timer...");
194 timer.schedule(new TimerTask() {
195 @Override
196 public void run() {
197 LinkId linkId = link.getLinkId();
198 xranStore.removeLink(linkId);
199 log.info("Link is removed after not receiving Meas Reports for 10 seconds");
200 }
201 }, 10000);
202
203 }
204
205 class InternalDeviceListener implements DeviceListener {
206
207 @Override
208 public void event(DeviceEvent event) {
209 log.info("Device Event {}", event);
210 switch (event.type()) {
211 case DEVICE_ADDED: {
212 try {
213 ECGI ecgi = decodeDeviceId(event.subject().id());
214 RnibCell cell = cellMap.get(ecgi);
215 if (cell != null) {
216 Timer timer = new Timer();
217 timer.scheduleAtFixedRate(
218 new TimerTask() {
219 @Override
220 public void run() {
221 CellConfigReport conf = cell.getConf();
222 if (conf == null) {
223 try {
224 ChannelHandlerContext ctx = cellMap.getCtx(ecgi);
225 SctpMessage msg = XranChannelHandler.getSctpMessage(ConfigEncoderDecoder.constructPacket(ecgi));
226 ctx.writeAndFlush(msg);
227 } catch (IOException e) {
228 log.error(ExceptionUtils.getFullStackTrace(e));
229 e.printStackTrace();
230 }
231 } else {
232 // FIXME: maybe remove this map.
233 cellMap.putPciArfcn(cell);
234 try {
235 ChannelHandlerContext ctx = cellMap.
236 getCtx(ecgi);
237 XrancPdu xrancPdu = L2MeasConf.constructPacket(ecgi, xranConfig.getL2MeasInterval());
238 cell.setMeasConfig(xrancPdu.getBody().getL2MeasConfig());
239 SctpMessage sctpMessage = XranChannelHandler.
240 getSctpMessage(xrancPdu);
241 ctx.writeAndFlush(sctpMessage);
242 } catch (IOException e) {
243 log.error(ExceptionUtils.getFullStackTrace(e));
244 e.printStackTrace();
245 }
246 timer.cancel();
247 timer.purge();
248 }
249 }
250 },
251 0,
252 xranConfig.getConfigRequestInterval() * 1000
253 );
254 }
255 } catch (IOException e) {
256 log.error(ExceptionUtils.getFullStackTrace(e));
257 e.printStackTrace();
258 }
259 break;
260 }
261 default: {
262 break;
263 }
264 }
265 }
266 }
267
268 class InternalHostListener implements HostListener {
269
270 @Override
271 public void event(HostEvent event) {
272 log.info("Host Event {}", event);
273 switch (event.type()) {
274 case HOST_ADDED:
275 case HOST_MOVED: {
276 RnibUe ue = ueMap.get(hostIdtoMME(event.subject().id()));
277 if (ue != null) {
278 ECGI ecgi_primary = linkMap.getPrimaryCell(ue);
279 RnibCell primary = cellMap.get(ecgi_primary);
280 ue.setMeasConfig(null);
281 if (primary != null) {
282 Timer timer = new Timer();
283 timer.scheduleAtFixedRate(
284 new TimerTask() {
285 @Override
286 public void run() {
287 if (ue.getCapability() == null) {
288 try {
289 ChannelHandlerContext ctx = cellMap.getCtx(primary.getEcgi());
290 SctpMessage msg = XranChannelHandler.
291 getSctpMessage(UECapabilityEnq.constructPacket(
292 primary.getEcgi(),
293 ue.getRanId()));
294 ctx.writeAndFlush(msg);
295 } catch (IOException e) {
296 log.warn(ExceptionUtils.getFullStackTrace(e));
297 e.printStackTrace();
298 }
299 } else {
300 if (ue.getMeasConfig() == null) {
301 try {
302 ChannelHandlerContext ctx = cellMap.getCtx(primary.getEcgi());
303 RXSigMeasConfig.MeasCells measCells = new RXSigMeasConfig.MeasCells();
304 xranStore.getCellNodes().forEach(cell -> {
305 CellConfigReport cellReport = cell.getConf();
306 if (cellReport != null) {
307 PCIARFCN pciarfcn = new PCIARFCN();
308 pciarfcn.setPci(cellReport.getPci());
309 pciarfcn.setEarfcnDl(cellReport.getEarfcnDl());
310 measCells.setPCIARFCN(pciarfcn);
311 }
312 });
313 XrancPdu xrancPdu = SignalMeasConfig.constructPacket(
314 primary.getEcgi(),
315 ue.getRanId(),
316 measCells,
317 xranConfig.getRxSignalInterval()
318 );
319 ue.setMeasConfig(xrancPdu.getBody().getRXSigMeasConfig());
320 SctpMessage msg = XranChannelHandler.getSctpMessage(xrancPdu);
321 ctx.writeAndFlush(msg);
322 } catch (IOException e) {
323 log.warn(ExceptionUtils.getFullStackTrace(e));
324 e.printStackTrace();
325 }
326 }
327 timer.cancel();
328 timer.purge();
329 }
330 }
331 },
332 0,
333 xranConfig.getConfigRequestInterval() * 1000
334 );
335 }
336 }
337 break;
338 }
339 default: {
340 break;
341 }
342 }
343 }
344 }
345
346 public class InternalXranDeviceAgent implements XranDeviceAgent {
347
348 private final Logger log = LoggerFactory.getLogger(InternalXranDeviceAgent.class);
349
350 @Override
351 public boolean addConnectedCell(String host, ChannelHandlerContext ctx) {
352 ECGI ecgi = legitCells.get(host);
353
354 if (ecgi == null) {
355 log.error("Device is not a legit source; ignoring...");
356 } else {
357 log.info("Device exists in configuration; registering...");
358 RnibCell storeCell = cellMap.get(ecgi);
359 if (storeCell == null) {
360 storeCell = new RnibCell();
361 storeCell.setEcgi(ecgi);
362 cellMap.put(storeCell, ctx);
363
364 for (XranDeviceListener l : xranDeviceListeners) {
365 l.deviceAdded(storeCell);
366 }
367 return true;
368 } else {
369 log.error("Device already registered; ignoring...");
370 }
371 }
372 ctx.close();
373 return false;
374 }
375
376 @Override
377 public boolean removeConnectedCell(String host) {
378 ECGI ecgi = legitCells.get(host);
379 List<RnibLink> linksByECGI = xranStore.getLinksByECGI(ecgi);
380
381 linksByECGI.forEach(rnibLink -> xranStore.removeLink(rnibLink.getLinkId()));
382
383 if (cellMap.remove(ecgi)) {
384 for (XranDeviceListener l : xranDeviceListeners) {
385 l.deviceRemoved(deviceId(uri(ecgi)));
386 }
387 return true;
388 }
389 return false;
390 }
391 }
392
393 public class InternalXranHostAgent implements XranHostAgent {
394
395 @Override
396 public boolean addConnectedHost(RnibUe ue, RnibCell cell, ChannelHandlerContext ctx) {
397
398 if (ueMap.get(ue.getMmeS1apId()) != null) {
399 linkMap.putPrimaryLink(cell, ue);
400
401 Set<ECGI> ecgiSet = xranStore.getLinksByUeId(ue.getMmeS1apId().longValue())
402 .stream()
403 .map(l -> l.getLinkId().getSource())
404 .collect(Collectors.toSet());
405
406 for (XranHostListener l : xranHostListeners) {
407 l.hostAdded(ue, ecgiSet);
408 }
409 return true;
410 } else {
411 ueMap.put(ue);
412 linkMap.putPrimaryLink(cell, ue);
413
414 Set<ECGI> ecgiSet = Sets.newConcurrentHashSet();
415 ecgiSet.add(cell.getEcgi());
416 for (XranHostListener l : xranHostListeners) {
417 l.hostAdded(ue, ecgiSet);
418 }
419 return true;
420 }
421
422 }
423
424 @Override
425 public boolean removeConnectedHost(RnibUe ue) {
426 List<RnibLink> links = xranStore.getLinksByUeId(ue.getMmeS1apId().longValue());
427 links.forEach(rnibLink -> xranStore.removeLink(rnibLink.getLinkId()));
428 if (ueMap.remove(ue.getMmeS1apId())) {
429 for (XranHostListener l : xranHostListeners) {
430 l.hostRemoved(ue.getHostId());
431 }
432 return true;
433 }
434 return false;
435 }
436 }
437
438 public class InternalXranPacketAgent implements XranPacketProcessor {
439 @Override
440 public void handlePacket(XrancPdu recv_pdu, ChannelHandlerContext ctx) throws IOException {
441 XrancPdu send_pdu;
442
443 int apiID = recv_pdu.getHdr().getApiId().intValue();
444 log.debug("Received message: {}", recv_pdu);
445 switch (apiID) {
446 case 1: {
447 // Decode Cell config report.
448 CellConfigReport report = recv_pdu.getBody().getCellConfigReport();
449
450 ECGI ecgi = report.getEcgi();
451
452 RnibCell cell = xranStore.getCell(ecgi);
453 cell.setConf(report);
454
455 break;
456 }
457 case 2: {
458 // Decode UE Admission Request.
459 UEAdmissionRequest ueAdmissionRequest = recv_pdu.getBody().getUEAdmissionRequest();
460
461 ECGI ecgi = ueAdmissionRequest.getEcgi();
462 if (xranStore.getCell(ecgi) != null) {
463 CRNTI crnti = ueAdmissionRequest.getCrnti();
464 send_pdu = UEAdmEncoderDecoder.constructPacket(ecgi, crnti);
465 ctx.writeAndFlush(XranChannelHandler.getSctpMessage(send_pdu));
466 } else {
467 log.warn("Could not find ECGI in registered cells: {}", ecgi);
468 }
469 break;
470 }
471 case 4: {
472 // Decode UE Admission Status.
473 UEAdmissionStatus ueAdmissionStatus = recv_pdu.getBody().getUEAdmissionStatus();
474
475 RnibUe ue = ueMap.get(ueAdmissionStatus.getCrnti());
476 if (ue != null) {
477 if (ueAdmissionStatus.getAdmEstStatus().value.intValue() == 0) {
478 ue.setUeState(UeState.ACTIVE);
479 } else {
480 ue.setUeState(UeState.IDLE);
481 }
482 }
483 break;
484 }
485 case 5: {
486 // Decode UE Admission Context Update.
487 UEAttachComplete ueAttachComplete = recv_pdu.getBody().getUEAttachComplete();
488
489 RnibCell cell = xranStore.getCell(ueAttachComplete.getEcgi());
490
491 RnibUe ue = ueMap.get(ueAttachComplete.getMMEUES1APID());
492 if (ueMap.get(ueAttachComplete.getMMEUES1APID()) == null) {
493 ue = new RnibUe();
494 }
495
496 ue.setMmeS1apId(ueAttachComplete.getMMEUES1APID());
497 ue.setEnbS1apId(ueAttachComplete.getENBUES1APID());
498 ue.setRanId(ueAttachComplete.getCrnti());
499
500 hostAgent.addConnectedHost(ue, cell, ctx);
501 break;
502 }
503 case 6: {
504 // Decode UE Reconfig_Ind.
505 UEReconfigInd ueReconfigInd = recv_pdu.getBody().getUEReconfigInd();
506 RnibUe ue = ueMap.get(ueReconfigInd.getCrntiOld());
507
508 if (ue != null) {
509 ue.setRanId(ueReconfigInd.getCrntiNew());
510 } else {
511 log.warn("Could not find UE with this CRNTI: {}", ueReconfigInd.getCrntiOld());
512 }
513 break;
514 }
515 case 7: {
516 // If xRANc wants to deactivate UE, we pass UEReleaseInd from xRANc to eNB.
517 // Decode UE Release_Ind.
518 UEReleaseInd ueReleaseInd = recv_pdu.getBody().getUEReleaseInd();
519 RnibUe ue = ueMap.get(ueReleaseInd.getCrnti());
520 if (ue != null) {
521 ue.setUeState(UeState.IDLE);
522 restartTimer(ue);
523 }
524 break;
525 }
526 case 8: {
527 // Decode Bearer Adm Request
528 BearerAdmissionRequest bearerAdmissionRequest = recv_pdu.getBody().getBearerAdmissionRequest();
529
530 ECGI ecgi = bearerAdmissionRequest.getEcgi();
531 CRNTI crnti = bearerAdmissionRequest.getCrnti();
532 ERABParams erabParams = bearerAdmissionRequest.getErabParams();
533 RnibLink link = linkMap.get(ecgi, crnti);
534 if (link != null) {
535 link.setBearerParameters(erabParams);
536 } else {
537 log.warn("Could not find link between {}-{}", ecgi, crnti);
538 }
539
540 BerInteger numErabs = bearerAdmissionRequest.getNumErabs();
541
542 send_pdu = BearerEncoderDecoder.constructPacket(ecgi, crnti, erabParams, numErabs);
543 // Encode and send Bearer Admission Response - API ID 9
544 ctx.writeAndFlush(XranChannelHandler.getSctpMessage(send_pdu));
545 break;
546 }
547 case 10: {
548 //Decode Bearer Admission Status
549 BearerAdmissionStatus bearerAdmissionStatus = recv_pdu.getBody().getBearerAdmissionStatus();
550
551// ECGI ecgi = bearerAdmissionStatus.getEcgi();
552// CRNTI crnti = bearerAdmissionStatus.getCrnti();
553//
554// RnibLink link = linkMap.get(ecgi, crnti);
555
556 break;
557 }
558 case 11: {
559 //Decode Bearer Release Ind
560 BearerReleaseInd bearerReleaseInd = recv_pdu.getBody().getBearerReleaseInd();
561
562 ECGI ecgi = bearerReleaseInd.getEcgi();
563 CRNTI crnti = bearerReleaseInd.getCrnti();
564 RnibLink link = linkMap.get(ecgi, crnti);
565
566 List<ERABID> erabidsRelease = bearerReleaseInd.getErabIds().getERABID();
567 List<ERABParamsItem> erabParamsItem = link.getBearerParameters().getERABParamsItem();
568
569 List<ERABParamsItem> unreleased = erabParamsItem
570 .stream()
571 .filter(item -> {
572 Optional<ERABID> any = erabidsRelease.stream().filter(id -> id.equals(item.getId())).findAny();
573 return !any.isPresent();
574 }).collect(Collectors.toList());
575
576 link.getBearerParameters().setERABParamsItem(new ArrayList<>(unreleased));
577
578 break;
579 }
580 case 12: {
581 // Don't know what will invoke sending UE CAPABILITY ENQUIRY
582 // Encode and send UE CAPABILITY ENQUIRY
583 UECapabilityEnquiry ueCapabilityEnquiry = recv_pdu.getBody().getUECapabilityEnquiry();
584 XrancPdu xrancPdu = UECapabilityEnq.constructPacket(ueCapabilityEnquiry.getEcgi(), ueCapabilityEnquiry.getCrnti());
585 ctx.writeAndFlush(XranChannelHandler.getSctpMessage(xrancPdu));
586 break;
587 }
588 case 13: {
589 // Decode UE Capability Info
590 UECapabilityInfo capabilityInfo = recv_pdu.getBody().getUECapabilityInfo();
591
592 RnibUe ue = ueMap.get(capabilityInfo.getCrnti());
593 if (ue != null) {
594 ue.setCapability(capabilityInfo);
595 } else {
596 log.warn("Could not find UE with this CRNTI: {}", capabilityInfo.getCrnti());
597 }
598 break;
599
600 //14, 15, 16 are handoff
601 }
602 case 18: {
603 // Decode RX Sig Meas Report.
604 RXSigMeasReport rxSigMeasReport = recv_pdu.getBody().getRXSigMeasReport();
605 List<RXSigReport> rxSigReportList = rxSigMeasReport.getCellMeasReports().getRXSigReport();
606
607 if (!rxSigReportList.isEmpty()) {
608 rxSigReportList.forEach(rxSigReport -> {
609 RnibCell cell = cellMap.get(rxSigReport.getPciArfcn());
610 if (cell != null) {
611 ECGI ecgi = cell.getEcgi();
612 RnibLink link = linkMap.get(ecgi, rxSigMeasReport.getCrnti());
613 if (link == null) {
614 log.warn("Could not find link between: {}-{} | Creating non-serving link..", ecgi, rxSigMeasReport.getCrnti());
615 link = linkMap.putNonServingLink(cell, rxSigMeasReport.getCrnti());
616
617 if (link != null) {
618 restartTimer(link);
619 }
620 }
621
622 if (link != null) {
623 RSRQRange rsrq = rxSigReport.getRsrq();
624 RSRPRange rsrp = rxSigReport.getRsrp();
625
626 RnibLink.LinkQuality quality = link.getQuality();
627 quality.setRsrp(rsrp.value.intValue() - 140);
628 quality.setRsrq((rsrq.value.intValue() * 0.5) - 19.5);
629 }
630 } else {
631 log.warn("Could not find cell with PCI-ARFCN: {}", rxSigReport.getPciArfcn());
632 }
633 });
634 }
635 break;
636 }
637 case 20: {
638 RadioMeasReportPerUE radioMeasReportPerUE = recv_pdu.getBody().getRadioMeasReportPerUE();
639
640 List<RadioRepPerServCell> servCells = radioMeasReportPerUE.getRadioReportServCells().getRadioRepPerServCell();
641
642 servCells.forEach(servCell -> {
643 RnibCell cell = cellMap.get(servCell.getPciArfcn());
644 if (cell != null) {
645 RnibLink link = linkMap.get(cell.getEcgi(), radioMeasReportPerUE.getCrnti());
646 if (link != null) {
647 RadioRepPerServCell.CqiHist cqiHist = servCell.getCqiHist();
648 RnibLink.LinkQuality quality = link.getQuality();
649 quality.setCqiHist(cqiHist);
650
651 final double[] values = {0, 0, 0};
652 int i = 1;
653 cqiHist.getBerInteger().forEach(value -> {
654 values[0] = Math.max(values[0], value.intValue());
655 values[1] += i * value.intValue();
656 values[2] += value.intValue();
657 });
658
659 quality.setCqiMode(values[0]);
660 quality.setCqiMean(values[1] / values[2]);
661
662 } else {
663 log.warn("Could not find link between: {}-{}", cell.getEcgi(), radioMeasReportPerUE.getCrnti());
664 }
665 } else {
666 log.warn("Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
667 }
668 });
669
670 }
671 case 21: {
672 RadioMeasReportPerCell radioMeasReportPerCell = recv_pdu.getBody().getRadioMeasReportPerCell();
673 break;
674 }
675 case 22: {
676 SchedMeasReportPerUE schedMeasReportPerUE = recv_pdu.getBody().getSchedMeasReportPerUE();
677
678 List<SchedMeasRepPerServCell> servCells = schedMeasReportPerUE.getSchedReportServCells().getSchedMeasRepPerServCell();
679
680 servCells.forEach(servCell -> {
681 RnibCell cell = cellMap.get(servCell.getPciArfcn());
682 if (cell != null) {
683 RnibLink link = linkMap.get(cell.getEcgi(), schedMeasReportPerUE.getCrnti());
684 if (link != null) {
685 link.getQuality().setMcs_dl(servCell.getMcsDl());
686 link.getQuality().setMcs_ul(servCell.getMcsUl());
687
688 link.getResourceUsage().setDl(servCell.getPrbUsage().getPrbUsageDl());
689 link.getResourceUsage().setUl(servCell.getPrbUsage().getPrbUsageUl());
690 } else {
691 log.warn("Could not find link between: {}-{}", cell.getEcgi(), schedMeasReportPerUE.getCrnti());
692 }
693 } else {
694 log.warn("Could not find cell with PCI-ARFCN: {}", servCell.getPciArfcn());
695 }
696 });
697 break;
698 }
699 case 23: {
700 SchedMeasReportPerCell schedMeasReportPerCell = recv_pdu.getBody().getSchedMeasReportPerCell();
701
702 RnibCell cell = cellMap.get(schedMeasReportPerCell.getEcgi());
703 if (cell != null) {
704 cell.setPrimaryPrbUsage(schedMeasReportPerCell.getPrbUsagePcell());
705 cell.setSecondaryPrbUsage(schedMeasReportPerCell.getPrbUsageScell());
706 cell.setQci(schedMeasReportPerCell.getQciVals());
707 } else {
708 log.warn("Could not find cell with ECGI: {}", schedMeasReportPerCell.getEcgi());
709 }
710 break;
711 }
712 case 24: {
713 PDCPMeasReportPerUe pdcpMeasReportPerUe = recv_pdu.getBody().getPDCPMeasReportPerUe();
714
715 RnibLink link = linkMap.get(pdcpMeasReportPerUe.getEcgi(), pdcpMeasReportPerUe.getCrnti());
716 if (link != null) {
717 link.getPdcpThroughput().setDl(pdcpMeasReportPerUe.getThroughputDl());
718 link.getPdcpThroughput().setUl(pdcpMeasReportPerUe.getThroughputUl());
719 link.getPdcpPackDelay().setDl(pdcpMeasReportPerUe.getPktDelayDl());
720 link.getPdcpPackDelay().setUl(pdcpMeasReportPerUe.getPktDelayUl());
721 } else {
722 log.warn("Could not find link between: {}-{}", pdcpMeasReportPerUe.getEcgi(), pdcpMeasReportPerUe.getCrnti());
723 }
724 break;
725 }
726 case 34: {
727 TrafficSplitConfig trafficSplitConfig = recv_pdu.getBody().getTrafficSplitConfig();
728
729 List<TrafficSplitPercentage> splitPercentages = trafficSplitConfig.getTrafficSplitPercent().getTrafficSplitPercentage();
730
731 splitPercentages.forEach(trafficSplitPercentage -> {
732 RnibCell cell = cellMap.get(trafficSplitPercentage.getEcgi());
733 if (cell != null) {
734 RnibLink link = linkMap.get(cell.getEcgi(), trafficSplitConfig.getCrnti());
735 if (link != null) {
736 link.setTrafficPercent(trafficSplitPercentage);
737 } else {
738 log.warn("Could not find link between: {}-{}", cell.getEcgi(), trafficSplitConfig.getCrnti());
739 }
740 } else {
741 log.warn("Could not find cell with ECGI: {}", trafficSplitConfig.getEcgi());
742 }
743 });
744 }
745 default: {
746 log.warn("Wrong API ID");
747 }
748 }
749
750 }
751 }
752
753 class InternalNetworkConfigListener implements NetworkConfigListener {
754
755 @Override
756 public void event(NetworkConfigEvent event) {
757 switch (event.type()) {
758 case CONFIG_REGISTERED:
759 break;
760 case CONFIG_UNREGISTERED:
761 break;
762 case CONFIG_ADDED:
763 case CONFIG_UPDATED:
764 if (event.configClass() == CONFIG_CLASS) {
765 handleConfigEvent(event.config());
766 }
767 break;
768 case CONFIG_REMOVED:
769 break;
770 default:
771 break;
772 }
773 }
774
775 private void handleConfigEvent(Optional<Config> config) {
776 if (!config.isPresent()) {
777 return;
778 }
779
780 xranConfig = (XranConfig) config.get();
781
782 legitCells.putAll(xranConfig.activeCellSet());
783
784 controller.start(deviceAgent, hostAgent, packetAgent, xranConfig.getXrancPort());
785 }
786 }
787}