2 * Copyright (c) 2014, 2017 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.applications.frm.impl;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.util.Objects;
15 import java.util.Optional;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.atomic.AtomicLong;
18 import javax.annotation.Nonnull;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
23 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
24 import org.opendaylight.openflowplugin.api.openflow.configuration.ConfigurationService;
25 import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager;
26 import org.opendaylight.openflowplugin.applications.frm.FlowNodeReconciliation;
27 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesCommiter;
28 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
29 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesProperty;
30 import org.opendaylight.openflowplugin.applications.frm.NodeConfigurator;
31 import org.opendaylight.openflowplugin.applications.frm.nodeconfigurator.NodeConfiguratorImpl;
32 import org.opendaylight.openflowplugin.applications.frm.recovery.OpenflowServiceRecoveryHandler;
33 import org.opendaylight.openflowplugin.applications.reconciliation.NotificationRegistration;
34 import org.opendaylight.openflowplugin.applications.reconciliation.ReconciliationManager;
35 import org.opendaylight.serviceutils.srm.RecoverableListener;
36 import org.opendaylight.serviceutils.srm.ServiceRecoveryRegistry;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.onf.bundle.service.rev170124.SalBundleService;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.arbitrator.reconcile.service.rev180227.ArbitratorReconcileService;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.forwardingrules.manager.config.rev160511.ForwardingRulesManagerConfig;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.frm.reconciliation.service.rev180227.FrmReconciliationService;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.rf.state.rev170713.ResultState;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
57 * forwardingrules-manager org.opendaylight.openflowplugin.applications.frm.impl
60 * Manager and middle point for whole module. It contains ActiveNodeHolder and
61 * provide all RPC services.
64 public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
65 private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesManagerImpl.class);
67 static final int STARTUP_LOOP_TICK = 500;
68 static final int STARTUP_LOOP_MAX_RETRIES = 8;
69 private static final int FRM_RECONCILIATION_PRIORITY = Integer.getInteger("frm.reconciliation.priority", 1);
70 private static final String SERVICE_NAME = "FRM";
72 private final AtomicLong txNum = new AtomicLong();
73 private final DataBroker dataService;
74 private final SalFlowService salFlowService;
75 private final SalGroupService salGroupService;
76 private final SalMeterService salMeterService;
77 private final SalTableService salTableService;
78 private final ClusterSingletonServiceProvider clusterSingletonServiceProvider;
79 private final SalBundleService salBundleService;
80 private final AutoCloseable configurationServiceRegistration;
81 private final MastershipChangeServiceManager mastershipChangeServiceManager;
82 private final RpcProviderRegistry rpcRegistry;
83 private ForwardingRulesCommiter<Flow> flowListener;
84 private ForwardingRulesCommiter<Group> groupListener;
85 private ForwardingRulesCommiter<Meter> meterListener;
86 private ForwardingRulesCommiter<TableFeatures> tableListener;
87 private FlowNodeReconciliation nodeListener;
88 private NotificationRegistration reconciliationNotificationRegistration;
89 private FlowNodeConnectorInventoryTranslatorImpl flowNodeConnectorInventoryTranslatorImpl;
90 private DeviceMastershipManager deviceMastershipManager;
91 private final ReconciliationManager reconciliationManager;
92 private DevicesGroupRegistry devicesGroupRegistry;
93 private NodeConfigurator nodeConfigurator;
94 private ArbitratorReconcileService arbitratorReconciliationManager;
95 private boolean disableReconciliation;
96 private boolean staleMarkingEnabled;
97 private int reconciliationRetryCount;
98 private boolean isBundleBasedReconciliationEnabled;
99 private final OpenflowServiceRecoveryHandler openflowServiceRecoveryHandler;
100 private final ServiceRecoveryRegistry serviceRecoveryRegistry;
102 public ForwardingRulesManagerImpl(final DataBroker dataBroker, final RpcProviderRegistry rpcRegistry,
103 final ForwardingRulesManagerConfig config,
104 final MastershipChangeServiceManager mastershipChangeServiceManager,
105 final ClusterSingletonServiceProvider clusterSingletonService,
106 final ConfigurationService configurationService,
107 final ReconciliationManager reconciliationManager,
108 final OpenflowServiceRecoveryHandler openflowServiceRecoveryHandler,
109 final ServiceRecoveryRegistry serviceRecoveryRegistry) {
110 disableReconciliation = config.isDisableReconciliation();
111 staleMarkingEnabled = config.isStaleMarkingEnabled();
112 reconciliationRetryCount = config.getReconciliationRetryCount();
113 isBundleBasedReconciliationEnabled = config.isBundleBasedReconciliationEnabled();
114 this.configurationServiceRegistration = configurationService.registerListener(this);
115 this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
116 this.clusterSingletonServiceProvider = Preconditions.checkNotNull(clusterSingletonService,
117 "ClusterSingletonService provider can not be null");
118 this.reconciliationManager = reconciliationManager;
119 this.rpcRegistry = rpcRegistry;
120 this.mastershipChangeServiceManager = mastershipChangeServiceManager;
122 Preconditions.checkArgument(rpcRegistry != null, "RpcProviderRegistry can not be null !");
124 this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
125 "RPC SalFlowService not found.");
126 this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
127 "RPC SalGroupService not found.");
128 this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
129 "RPC SalMeterService not found.");
130 this.salTableService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalTableService.class),
131 "RPC SalTableService not found.");
132 this.salBundleService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalBundleService.class),
133 "RPC SalBundlService not found.");
134 this.openflowServiceRecoveryHandler = Preconditions.checkNotNull(openflowServiceRecoveryHandler,
135 "Openflow service recovery handler cannot be null");
136 this.serviceRecoveryRegistry = Preconditions.checkNotNull(serviceRecoveryRegistry,
137 "Service recovery registry cannot be null");
138 this.arbitratorReconciliationManager = Preconditions
139 .checkNotNull(rpcRegistry.getRpcService(ArbitratorReconcileService.class),
140 "ArbitratorReconciliationManager can not be null!");
144 public void start() {
145 nodeConfigurator = new NodeConfiguratorImpl();
146 this.devicesGroupRegistry = new DevicesGroupRegistry();
148 this.nodeListener = new FlowNodeReconciliationImpl(this, dataService, SERVICE_NAME, FRM_RECONCILIATION_PRIORITY,
149 ResultState.DONOTHING);
150 if (this.isReconciliationDisabled()) {
151 LOG.debug("Reconciliation is disabled by user");
153 this.reconciliationNotificationRegistration = reconciliationManager.registerService(this.nodeListener);
154 LOG.debug("Reconciliation is enabled by user and successfully registered to the reconciliation framework");
156 this.deviceMastershipManager = new DeviceMastershipManager(clusterSingletonServiceProvider, this.nodeListener,
157 dataService, mastershipChangeServiceManager);
158 this.deviceMastershipManager.setRoutedRpcReg(rpcRegistry.addRoutedRpcImplementation(
159 FrmReconciliationService.class, new FrmReconciliationServiceImpl(this)));
160 flowNodeConnectorInventoryTranslatorImpl = new FlowNodeConnectorInventoryTranslatorImpl(dataService);
162 this.flowListener = new FlowForwarder(this, dataService);
163 this.groupListener = new GroupForwarder(this, dataService);
164 this.meterListener = new MeterForwarder(this, dataService);
165 this.tableListener = new TableForwarder(this, dataService);
166 LOG.info("ForwardingRulesManager has started successfully.");
170 public void close() throws Exception {
171 configurationServiceRegistration.close();
173 if (this.flowListener != null) {
174 this.flowListener.close();
175 this.flowListener = null;
177 if (this.groupListener != null) {
178 this.groupListener.close();
179 this.groupListener = null;
181 if (this.meterListener != null) {
182 this.meterListener.close();
183 this.meterListener = null;
185 if (this.tableListener != null) {
186 this.tableListener.close();
187 this.tableListener = null;
189 if (this.nodeListener != null) {
190 this.nodeListener.close();
191 this.nodeListener = null;
193 if (deviceMastershipManager != null) {
194 deviceMastershipManager.close();
196 if (this.reconciliationNotificationRegistration != null) {
197 this.reconciliationNotificationRegistration.close();
198 this.reconciliationNotificationRegistration = null;
203 public ReadOnlyTransaction getReadTransaction() {
204 return dataService.newReadOnlyTransaction();
208 public String getNewTransactionId() {
209 return "DOM-" + txNum.getAndIncrement();
213 public boolean isNodeActive(InstanceIdentifier<FlowCapableNode> ident) {
214 return deviceMastershipManager.isNodeActive(ident.firstKeyOf(Node.class).getId());
218 public boolean checkNodeInOperationalDataStore(InstanceIdentifier<FlowCapableNode> ident) {
219 boolean result = false;
220 InstanceIdentifier<Node> nodeIid = ident.firstIdentifierOf(Node.class);
221 try (ReadOnlyTransaction transaction = dataService.newReadOnlyTransaction()) {
222 ListenableFuture<com.google.common.base.Optional<Node>> future = transaction
223 .read(LogicalDatastoreType.OPERATIONAL, nodeIid);
224 com.google.common.base.Optional<Node> optionalDataObject = future.get();
225 if (optionalDataObject.isPresent()) {
228 LOG.debug("{}: Failed to read {}", Thread.currentThread().getStackTrace()[1], nodeIid);
230 } catch (ExecutionException | InterruptedException e) {
231 LOG.warn("Failed to read {} ", nodeIid, e);
238 public SalFlowService getSalFlowService() {
239 return salFlowService;
243 public SalGroupService getSalGroupService() {
244 return salGroupService;
248 public SalMeterService getSalMeterService() {
249 return salMeterService;
253 public SalTableService getSalTableService() {
254 return salTableService;
258 public DevicesGroupRegistry getDevicesGroupRegistry() {
259 return this.devicesGroupRegistry;
263 public SalBundleService getSalBundleService() {
264 return salBundleService;
268 public ForwardingRulesCommiter<Flow> getFlowCommiter() {
273 public ForwardingRulesCommiter<Group> getGroupCommiter() {
274 return groupListener;
278 public ForwardingRulesCommiter<Meter> getMeterCommiter() {
279 return meterListener;
283 public ForwardingRulesCommiter<TableFeatures> getTableFeaturesCommiter() {
284 return tableListener;
288 public ArbitratorReconcileService getArbitratorReconciliationManager() {
289 return arbitratorReconciliationManager;
293 public boolean isReconciliationDisabled() {
294 return disableReconciliation;
298 public boolean isStaleMarkingEnabled() {
299 return staleMarkingEnabled;
303 public int getReconciliationRetryCount() {
304 return reconciliationRetryCount;
308 public void addRecoverableListener(RecoverableListener recoverableListener) {
309 serviceRecoveryRegistry.addRecoverableListener(openflowServiceRecoveryHandler.buildServiceRegistryKey(),
310 recoverableListener);
314 public FlowNodeConnectorInventoryTranslatorImpl getFlowNodeConnectorInventoryTranslatorImpl() {
315 return flowNodeConnectorInventoryTranslatorImpl;
319 public NodeConfigurator getNodeConfigurator() {
320 return nodeConfigurator;
323 public FlowNodeReconciliation getNodeListener() {
328 public boolean isBundleBasedReconciliationEnabled() {
329 return isBundleBasedReconciliationEnabled;
333 public boolean isNodeOwner(InstanceIdentifier<FlowCapableNode> ident) {
334 return Objects.nonNull(ident) && deviceMastershipManager.isDeviceMastered(ident.firstKeyOf(Node.class).getId());
338 public void setDeviceMastershipManager(final DeviceMastershipManager deviceMastershipManager) {
339 this.deviceMastershipManager = deviceMastershipManager;
343 public void onPropertyChanged(@Nonnull final String propertyName, @Nonnull final String propertyValue) {
344 Optional.ofNullable(ForwardingRulesProperty.forValue(propertyName)).ifPresent(forwardingRulesProperty -> {
345 switch (forwardingRulesProperty) {
346 case DISABLE_RECONCILIATION:
347 disableReconciliation = Boolean.valueOf(propertyValue);
349 case STALE_MARKING_ENABLED:
350 staleMarkingEnabled = Boolean.valueOf(propertyValue);
352 case RECONCILIATION_RETRY_COUNT:
353 reconciliationRetryCount = Integer.parseInt(propertyValue);
355 case BUNDLE_BASED_RECONCILIATION_ENABLED:
356 isBundleBasedReconciliationEnabled = Boolean.valueOf(propertyValue);
359 LOG.warn("No forwarding rule property found.");