Added range type to subject-feature-definition/parameter
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / FlowTable.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
10
11 import java.util.HashMap;
12 import java.util.Map;
13
14 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.Dirty;
17 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
24 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import com.google.common.base.Optional;
29
30 /**
31  * Base class for managing flow tables
32  * @author readams
33  */
34 public abstract class FlowTable extends OfTable {
35     protected static final Logger LOG =
36             LoggerFactory.getLogger(FlowTable.class);
37
38     public FlowTable(OfTableCtx ctx) {
39         super(ctx);
40     }
41
42     // *******
43     // OfTable
44     // *******
45
46     @Override
47     public void update(NodeId nodeId, PolicyInfo policyInfo,
48                        Dirty dirty) throws Exception {
49         ReadWriteTransaction t = ctx.dataBroker.newReadWriteTransaction();
50         InstanceIdentifier<Table> tiid =
51                 FlowUtils.createTablePath(nodeId, getTableId());
52         Optional<Table> r =
53                 t.read(LogicalDatastoreType.CONFIGURATION, tiid).get();
54
55         // Unfortunately, we need to construct a unique string ID for each
56         // flow which is redundant with all the information in the flow itself
57         // We'll build this map so at least we don't have to be O(n^2)
58         HashMap<String, FlowCtx> flowMap = new HashMap<>();
59
60         if (r.isPresent()) {
61             Table curTable = (Table)r.get();
62
63             if (curTable.getFlow() != null) {
64                 for (Flow f : curTable.getFlow()) {
65                     flowMap.put(f.getId().getValue(), new FlowCtx(f));
66                 }
67             }
68         }
69
70         sync(t, tiid, flowMap, nodeId, policyInfo, dirty);
71
72         for (FlowCtx fx : flowMap.values()) {
73             if (!fx.visited) {
74                 t.delete(LogicalDatastoreType.CONFIGURATION,
75                          FlowUtils.createFlowPath(tiid, fx.f.getKey()));
76             }
77         }
78
79         t.submit().get();
80         //ListenableFuture<Void> result = t.submit();
81         //Futures.addCallback(result, updateCallback);
82     }
83
84     // *********
85     // FlowTable
86     // *********
87
88     /**
89      * Sync flow state using the flow map
90      * @throws Exception
91      */
92     public abstract void sync(ReadWriteTransaction t,
93                               InstanceIdentifier<Table> tiid,
94                               Map<String, FlowCtx> flowMap,
95                               NodeId nodeId, PolicyInfo policyInfo, 
96                               Dirty dirty) throws Exception;
97
98     /**
99      * Get the table ID being manipulated
100      */
101     public abstract short getTableId();
102
103     // ***************
104     // Utility methods
105     // ***************
106
107     /**
108      * Get a base flow builder with some common features already set
109      */
110     protected FlowBuilder base() {
111         return new FlowBuilder()
112             .setTableId(getTableId())
113             .setBarrier(false)
114             .setHardTimeout(0)
115             .setIdleTimeout(0);
116     }
117
118     /**
119      * "Visit" a flow ID by checking if it already exists and if so marking
120      * the {@link FlowCtx} visited bit.
121      * @param flowMap the map containing the existing flows for this table
122      * @param flowId the ID for the flow
123      * @return <code>true</code> if the flow needs to be added
124      */
125     protected static boolean visit(Map<String, FlowCtx> flowMap,
126                                    String flowId) {
127         FlowCtx c = flowMap.get(flowId);
128         if (c != null) {
129             c.visited = true;
130             return false;
131         }
132         return true;
133     }
134
135     /**
136      * Write the given flow to the transaction
137      */
138     protected static void writeFlow(ReadWriteTransaction t,
139                                     InstanceIdentifier<Table> tiid,
140                                     Flow flow) {
141         LOG.trace("{} {}", flow.getId(), flow);
142         t.put(LogicalDatastoreType.CONFIGURATION,
143               FlowUtils.createFlowPath(tiid, flow.getId()),
144               flow, true);
145     }
146
147     /**
148      * Write a drop flow for the given ethertype at the given priority.
149      * If the ethertype is null, then drop all traffic
150      */
151     protected void dropFlow(ReadWriteTransaction t,
152                             InstanceIdentifier<Table> tiid,
153                             Map<String, FlowCtx> flowMap,
154                             Integer priority, Long etherType) {
155         FlowId flowid = new FlowId(new StringBuilder()
156             .append("drop|")
157             .append(etherType)
158             .toString());
159         if (visit(flowMap, flowid.getValue())) {
160             FlowBuilder flowb = base()
161                 .setId(flowid)
162                 .setPriority(priority)
163                 .setInstructions(FlowUtils.dropInstructions());
164             if (etherType != null)
165                 flowb.setMatch(new MatchBuilder()
166                     .setEthernetMatch(FlowUtils.ethernetMatch(null, null, 
167                                                               etherType))
168                         .build());
169             writeFlow(t, tiid, flowb.build());
170         }
171     }
172
173     /**
174      * Context object for keeping track of flow state
175      */
176     protected static class FlowCtx {
177         Flow f;
178         boolean visited = false;
179
180         public FlowCtx(Flow f) {
181             super();
182             this.f = f;
183         }
184     }
185 }