blob: 65349cd9c15dc46768d90ae64ca0ab74b0f27a8f [file] [log] [blame]
Matteo Scandoloaa2adde2021-09-13 12:45:32 -07001/*
Joey Armstrong7f6d6d22023-01-09 17:09:50 -05002 * Copyright 2021-2023 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandoloaa2adde2021-09-13 12:45:32 -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 */
16
17package org.opencord.olt.impl;
18
19import org.onosproject.cluster.ClusterService;
20import org.onosproject.cluster.LeadershipService;
21import org.onosproject.cluster.NodeId;
22import org.onosproject.mastership.MastershipService;
23import org.onosproject.net.Device;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.Port;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.device.DeviceService;
Gustavo Silva29fb20e2022-05-26 09:59:54 -030028import org.opencord.olt.OltDeviceServiceInterface;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070029import org.opencord.sadis.BaseInformationService;
30import org.opencord.sadis.SadisService;
31import org.opencord.sadis.SubscriberAndDeviceInformation;
32import org.osgi.service.component.annotations.Activate;
33import org.osgi.service.component.annotations.Component;
34import org.osgi.service.component.annotations.Reference;
35import org.osgi.service.component.annotations.ReferenceCardinality;
36import org.osgi.service.component.annotations.ReferencePolicy;
37import org.slf4j.Logger;
38
39import java.util.List;
40import java.util.Optional;
41
42import static org.slf4j.LoggerFactory.getLogger;
43
44/**
45 * The implementation of the OltDeviceService.
46 */
47@Component(immediate = true)
48public class OltDeviceService implements OltDeviceServiceInterface {
49
50 protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
51 private final Logger log = getLogger(getClass());
52
53 @Reference(cardinality = ReferenceCardinality.OPTIONAL,
54 bind = "bindSadisService",
55 unbind = "unbindSadisService",
56 policy = ReferencePolicy.DYNAMIC)
57 protected volatile SadisService sadisService;
58
59 @Reference(cardinality = ReferenceCardinality.MANDATORY)
60 protected DeviceService deviceService;
61
62 @Reference(cardinality = ReferenceCardinality.MANDATORY)
63 protected ClusterService clusterService;
64
65 @Reference(cardinality = ReferenceCardinality.MANDATORY)
66 protected MastershipService mastershipService;
67
68 @Reference(cardinality = ReferenceCardinality.MANDATORY)
69 protected LeadershipService leadershipService;
70
71 @Activate
72 public void activate() {
73 log.info("Activated");
74 }
75
76 /**
77 * Returns true if the device is an OLT.
78 *
79 * @param device the Device to be checked
80 * @return boolean
81 */
82 public boolean isOlt(Device device) {
83 return getOltInfo(device) != null;
84 }
85
86 private SubscriberAndDeviceInformation getOltInfo(Device dev) {
87 if (subsService == null) {
88 return null;
89 }
90 String devSerialNo = dev.serialNumber();
91 return subsService.get(devSerialNo);
92 }
93
94
95 /**
96 * Returns true if the port is an NNI Port on the OLT.
97 * NOTE: We can check if a port is a NNI based on the SADIS config, specifically the uplinkPort section
98 *
99 * @param dev the Device this port belongs to
100 * @param portNumber the PortNumber to be checked
101 * @return boolean
102 */
103 @Override
104 public boolean isNniPort(Device dev, PortNumber portNumber) {
105 SubscriberAndDeviceInformation deviceInfo = getOltInfo(dev);
106 return deviceInfo != null && portNumber.toLong() == deviceInfo.uplinkPort();
107 }
108
109 @Override
110 public Optional<Port> getNniPort(Device device) {
111 SubscriberAndDeviceInformation deviceInfo = getOltInfo(device);
112 if (deviceInfo == null) {
113 return Optional.empty();
114 }
115 List<Port> ports = deviceService.getPorts(device.id());
116 if (log.isTraceEnabled()) {
117 log.trace("Get NNI Port looks for NNI in: {}", ports);
118 }
119 return ports.stream()
120 .filter(p -> p.number().toLong() == deviceInfo.uplinkPort())
121 .findFirst();
122 }
123
124 protected void bindSadisService(SadisService service) {
125 this.subsService = service.getSubscriberInfoService();
126 log.info("Sadis service is loaded");
127 }
128
129 protected void unbindSadisService(SadisService service) {
130 this.subsService = null;
131 log.info("Sadis service is unloaded");
132 }
133
134 /**
135 * Checks for mastership or falls back to leadership on deviceId.
136 * If the device is available use mastership,
137 * otherwise fallback on leadership.
138 * Leadership on the device topic is needed because the master can be NONE
139 * in case the device went away, we still need to handle events
140 * consistently
141 *
142 * @param deviceId The device ID to check.
143 * @return boolean (true if the current instance is managing the device)
144 */
145 @Override
146 public boolean isLocalLeader(DeviceId deviceId) {
147 if (deviceService.isAvailable(deviceId)) {
148 return mastershipService.isLocalMaster(deviceId);
149 } else {
150 // Fallback with Leadership service - device id is used as topic
151 NodeId leader = leadershipService.runForLeadership(
152 deviceId.toString()).leaderNodeId();
153 // Verify if this node is the leader
154 return clusterService.getLocalNode().id().equals(leader);
155 }
156 }
157}