2 * Copyright (c) 2014 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.groupbasedpolicy.renderer.ofoverlay;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
18 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
20 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
23 import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
24 import org.opendaylight.sfc.provider.SfcProviderRpc;
25 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRenderedServicePathFirstHopInputBuilder;
26 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.ReadRenderedServicePathFirstHopOutput;
27 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.path.first.hop.info.RenderedServicePathFirstHop;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.SubjectFeatureDefinitions;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Tenants;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinition;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.definitions.ActionDefinitionKey;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.SubjectFeatureInstances;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.subject.feature.instances.ActionInstance;
39 import org.opendaylight.yangtools.concepts.ListenerRegistration;
40 import org.opendaylight.yangtools.yang.binding.DataObject;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.opendaylight.yangtools.yang.common.RpcResult;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 import java.util.concurrent.Future;
47 import java.util.concurrent.ScheduledExecutorService;
50 * Manage all things SFC
52 * This is a bit of a place-holder for functionality
53 * that we'll need to add for SFC integration. This
54 * will likely change a lot.
56 * TODO Move SfcManager out of ofoverlay renderer -- should be something
57 * that's shared by renderers, not specific to ofoverlay
61 public class SfcManager implements AutoCloseable, DataChangeListener {
62 private static final Logger LOG =
63 LoggerFactory.getLogger(SfcManager.class);
65 private final DataBroker dataBroker;
67 private final PolicyResolver policyResolver;
69 private final RpcProviderRegistry rpcRegistry;
70 private final ScheduledExecutorService executor;
71 private final InstanceIdentifier<ActionInstance> allActionInstancesIid;
72 private final ListenerRegistration<DataChangeListener> actionListener;
74 // place-holder - not sure what we'll call it
75 private final String SFC_CHAIN_ACTION = "CHAIN";
76 private final String SFC_CHAIN_NAME = "sfc-chain-name";
77 private final String SFC_RSP_NAME = "rsp-sfc-gbp";
79 public SfcManager(DataBroker dataBroker,
80 PolicyResolver policyResolver,
81 RpcProviderRegistry rpcRegistry,
82 ScheduledExecutorService executor) {
83 this.dataBroker = dataBroker;
84 this.policyResolver = policyResolver;
85 this.rpcRegistry = rpcRegistry;
86 this.executor = executor;
89 * For now, listen to all changes in rules
91 allActionInstancesIid =
92 InstanceIdentifier.builder(Tenants.class)
94 .child(SubjectFeatureInstances.class)
95 .child(ActionInstance.class)
97 actionListener = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
98 allActionInstancesIid, this, DataChangeScope.ONE);
99 LOG.debug("SfcManager: Started");
103 public void onDataChanged(
104 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
106 for (DataObject dao : change.getCreatedData().values()) {
107 if (dao instanceof ActionInstance) {
108 ActionInstance ai = (ActionInstance)dao;
109 LOG.debug("New ActionInstance created");
110 executor.execute(new MatchActionDefTask(ai));
114 // TODO: how to handle deletes (comment out for now)
115 // for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
116 // DataObject old = change.getOriginalData().get(iid);
117 // if (old != null && old instanceof ActionInstance) {
122 for (DataObject dao : change.getUpdatedData().values()) {
123 if (dao instanceof ActionInstance) {
124 ActionInstance ai = (ActionInstance)dao;
125 executor.execute(new MatchActionDefTask(ai));
131 * Private internal class that gets the action definition
132 * referenced by the instance. If the definition has an
133 * action of "chain" (or whatever we decide to use
134 * here), then we need to invoke the SFC API to go
135 * get the chain information, which we'll eventually
136 * use during policy resolution.
141 private class MatchActionDefTask implements Runnable,
142 FutureCallback<Optional<ActionDefinition>> {
143 private final ActionInstance actionInstance;
144 private final InstanceIdentifier<ActionDefinition> adIid;
145 private final ActionDefinitionId id;
147 public MatchActionDefTask(ActionInstance actionInstance) {
148 this.actionInstance = actionInstance;
149 this.id = actionInstance.getActionDefinitionId();
151 adIid = InstanceIdentifier.builder(SubjectFeatureDefinitions.class)
152 .child(ActionDefinition.class,
153 new ActionDefinitionKey(this.id))
159 * Create read transaction with callback
163 ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
164 ListenableFuture<Optional<ActionDefinition>> dao =
165 rot.read(LogicalDatastoreType.OPERATIONAL, adIid);
166 Futures.addCallback(dao, this, executor);
171 public void onFailure(Throwable arg0) {
172 LOG.error("Failure reading ActionDefinition {}", id.getValue());
176 public void onSuccess(Optional<ActionDefinition> dao) {
177 LOG.debug("Found ActionDefinition {}", id.getValue());
178 if (dao instanceof ActionDefinition) {
179 ActionDefinition ad = (ActionDefinition)dao;
180 if (ad.getName().getValue().equals(SFC_CHAIN_ACTION)) {
182 * We have the state we need:
183 * 1) it's a "CHAIN" action
184 * 2) the name is defined in the ActionInstance
186 if (actionInstance.getParameterValue() != null) {
194 * Go get the RenderedServicePath from SFC
196 * TBD: what to do with this once we have it - who to
199 private void getSfcRsp() {
200 for (ParameterValue pv: actionInstance.getParameterValue()) {
201 if (pv.getName().getValue().equals(SFC_CHAIN_NAME)) {
202 // TODO: check for rspFirstHop.getTransportType()
203 ReadRenderedServicePathFirstHopInputBuilder builder =
204 new ReadRenderedServicePathFirstHopInputBuilder();
205 builder.setName(SFC_CHAIN_NAME);
206 Future<RpcResult<ReadRenderedServicePathFirstHopOutput>> result =
207 SfcProviderRpc.getSfcProviderRpc().readRenderedServicePathFirstHop(builder.build());
209 RpcResult<ReadRenderedServicePathFirstHopOutput> output = result.get();
210 if (output.isSuccessful()) {
211 RenderedServicePathFirstHop rspFirstHop =
212 output.getResult().getRenderedServicePathFirstHop();
213 IpAddress ip = rspFirstHop.getIp();
214 PortNumber pn = rspFirstHop.getPort();
215 // TODO: use NSI, NSP, SPI
216 //Short nsi = rspFirstHop.getStartingIndex();
217 //Long nsp = rspFirstHop.getPathId();
218 //Long spi = rspFirstHop.getSymmetricPathId();
220 } catch (Exception e) {
221 // TODO: proper exception handling
231 public void close() throws Exception {
232 if (actionListener != null) actionListener.close();