Static Pipeline is constructed with the help of AbstractServiceInstance and PipelineO...
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / AbstractServiceInstance.java
1 /*
2  * Copyright (C) 2014 Red Hat, Inc.
3  *
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
7  *
8  * Authors : Madhu Venugopal
9  */
10 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13;
11
12 import java.util.List;
13 import java.util.concurrent.ExecutionException;
14
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
19 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.google.common.base.Preconditions;
41 import com.google.common.collect.Lists;
42 import com.google.common.util.concurrent.CheckedFuture;
43
44 /**
45  * Any ServiceInstance class that extends AbstractServiceInstance to be a part of the pipeline
46  * have 2 basic requirements : <br>
47  * 1. Program a default pipeline flow to take any unmatched traffic to the next table in the pipeline. <br>
48  * 2. Get Pipeline Instructions from AbstractServiceInstance (using getMutablePipelineInstructionBuilder) and
49  *    use it in any matching flows that needs to be further processed by next service in the pipeline.
50  *
51  */
52 public abstract class AbstractServiceInstance {
53     public static final String SERVICE_PROPERTY ="serviceProperty";
54     private Service service;
55     private volatile PipelineOrchestrator orchestrator;
56
57     public AbstractServiceInstance (Service service) {
58         this.service = service;
59     }
60
61     public int getTable() {
62         return service.getTable();
63     }
64
65     public Service getService() {
66         return service;
67     }
68
69     public void setService(Service service) {
70         this.service = service;
71     }
72
73     private NodeBuilder createNodeBuilder(String nodeId) {
74         NodeBuilder builder = new NodeBuilder();
75         builder.setId(new NodeId(nodeId));
76         builder.setKey(new NodeKey(builder.getId()));
77         return builder;
78     }
79
80     /**
81      * This method returns the required Pipeline Instructions to by used by any matching flows that needs
82      * to be further processed by next service in the pipeline.
83      *
84      * Important to note that this is a convenience method which returns a mutable instructionBuilder which
85      * needs to be further adjusted by the concrete ServiceInstance class such as setting the Instruction Order, etc.
86      * @return Newly created InstructionBuilder to be used along with other instructions on the main flow
87      */
88     protected final InstructionBuilder getMutablePipelineInstructionBuilder() {
89         Service nextService = orchestrator.getNextServiceInPipeline(service);
90         if (nextService != null) {
91             return InstructionUtils.createGotoTableInstructions(new InstructionBuilder(), nextService.getTable());
92         } else {
93             return InstructionUtils.createDropInstructions(new InstructionBuilder());
94         }
95     }
96
97     private static final Logger logger = LoggerFactory.getLogger(AbstractServiceInstance.class);
98     private volatile MdsalConsumer mdsalConsumer;
99
100     public void writeFlow(FlowBuilder flowBuilder, NodeBuilder nodeBuilder) {
101         Preconditions.checkNotNull(mdsalConsumer);
102         if (mdsalConsumer == null) {
103             logger.error("ERROR finding MDSAL Service. Its possible that writeFlow is called too soon ?");
104             return;
105         }
106
107         DataBroker dataBroker = mdsalConsumer.getDataBroker();
108         if (dataBroker == null) {
109             logger.error("ERROR finding reference for DataBroker. Please check MD-SAL support on the Controller.");
110             return;
111         }
112
113         ReadWriteTransaction modification = dataBroker.newReadWriteTransaction();
114         InstanceIdentifier<Flow> path1 = InstanceIdentifier.builder(Nodes.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory
115                 .rev130819.nodes.Node.class, nodeBuilder.getKey()).augmentation(FlowCapableNode.class).child(Table.class,
116                 new TableKey(flowBuilder.getTableId())).child(Flow.class, flowBuilder.getKey()).build();
117
118         //modification.put(LogicalDatastoreType.OPERATIONAL, path1, flowBuilder.build());
119         modification.put(LogicalDatastoreType.CONFIGURATION, path1, flowBuilder.build(), true /*createMissingParents*/);
120
121
122         CheckedFuture<Void, TransactionCommitFailedException> commitFuture = modification.submit();
123         try {
124             commitFuture.get();  // TODO: Make it async (See bug 1362)
125             logger.debug("Transaction success for write of Flow "+flowBuilder.getFlowName());
126         } catch (InterruptedException|ExecutionException e) {
127             logger.error(e.getMessage(), e);
128         }
129     }
130
131     /**
132      * Program Default Pipeline Flow.
133      *
134      * @param nodeId Node on which the default pipeline flow is programmed.
135      */
136     protected void programDefaultPipelineRule(String nodeId) {
137         MatchBuilder matchBuilder = new MatchBuilder();
138         FlowBuilder flowBuilder = new FlowBuilder();
139         NodeBuilder nodeBuilder = createNodeBuilder(nodeId);
140
141         // Create the OF Actions and Instructions
142         InstructionsBuilder isb = new InstructionsBuilder();
143
144         // Instructions List Stores Individual Instructions
145         List<Instruction> instructions = Lists.newArrayList();
146
147         // Call the InstructionBuilder Methods Containing Actions
148         InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
149         ib.setOrder(0);
150         ib.setKey(new InstructionKey(0));
151         instructions.add(ib.build());
152
153         // Add InstructionBuilder to the Instruction(s)Builder List
154         isb.setInstruction(instructions);
155
156         // Add InstructionsBuilder to FlowBuilder
157         flowBuilder.setInstructions(isb.build());
158
159         String flowId = "DEFAULT_PIPELINE_FLOW";
160         flowBuilder.setId(new FlowId(flowId));
161         FlowKey key = new FlowKey(new FlowId(flowId));
162         flowBuilder.setMatch(matchBuilder.build());
163         flowBuilder.setPriority(0);
164         flowBuilder.setBarrier(true);
165         flowBuilder.setTableId(service.getTable());
166         flowBuilder.setKey(key);
167         flowBuilder.setFlowName(flowId);
168         flowBuilder.setHardTimeout(0);
169         flowBuilder.setIdleTimeout(0);
170         writeFlow(flowBuilder, nodeBuilder);
171     }
172
173 }