Fix netvirtsfc flows
[ovsdb.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / ClassifierService.java
1 /*
2  * Copyright (c) 2014, 2015 Red Hat, 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.ovsdb.openstack.netvirt.providers.openflow13.services;
10
11 import java.math.BigInteger;
12 import java.util.List;
13
14 import org.opendaylight.ovsdb.openstack.netvirt.api.ClassifierProvider;
15 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
16 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
17 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
18 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
19 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
20 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
42
43 import com.google.common.collect.Lists;
44 import org.osgi.framework.BundleContext;
45 import org.osgi.framework.ServiceReference;
46
47 public class ClassifierService extends AbstractServiceInstance implements ClassifierProvider, ConfigInterface {
48     public final static long REG_VALUE_FROM_LOCAL = 0x1L;
49     public final static long REG_VALUE_FROM_REMOTE = 0x2L;
50     public static final Class<? extends NxmNxReg> REG_FIELD = NxmNxReg0.class;
51
52     public ClassifierService() {
53         super(Service.CLASSIFIER);
54     }
55
56     public ClassifierService(Service service) {
57         super(service);
58     }
59
60     /*
61      * (Table:Classifier) Egress VM Traffic Towards TEP
62      * Match: Destination Ethernet Addr and OpenFlow InPort
63      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
64      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
65      * actions=set_field:5->tun_id,goto_table=<next-table>"
66      */
67
68     @Override
69     public void programLocalInPort(Long dpidLong, String segmentationId, Long inPort, String attachedMac, boolean write) {
70         String nodeName = OPENFLOW + dpidLong;
71
72         MatchBuilder matchBuilder = new MatchBuilder();
73         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
74         FlowBuilder flowBuilder = new FlowBuilder();
75
76         // Create the OF Match using MatchBuilder
77         flowBuilder.setMatch(MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
78         // TODO Broken In_Port Match
79         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
80
81         String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
82         // Add Flow Attributes
83         flowBuilder.setId(new FlowId(flowId));
84         FlowKey key = new FlowKey(new FlowId(flowId));
85         flowBuilder.setStrict(true);
86         flowBuilder.setBarrier(false);
87         flowBuilder.setTableId(getTable());
88         flowBuilder.setKey(key);
89         flowBuilder.setFlowName(flowId);
90         flowBuilder.setHardTimeout(0);
91         flowBuilder.setIdleTimeout(0);
92
93         if (write) {
94             // Instantiate the Builders for the OF Actions and Instructions
95             InstructionBuilder ib = new InstructionBuilder();
96             InstructionsBuilder isb = new InstructionsBuilder();
97
98             // Instructions List Stores Individual Instructions
99             List<Instruction> instructions = Lists.newArrayList();
100
101             // TODO Broken SetTunID
102             InstructionUtils.createSetTunnelIdInstructions(ib, new BigInteger(segmentationId));
103             ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
104             List<Action> actionList = aac.getApplyActions().getAction();
105
106             ActionBuilder ab = new ActionBuilder();
107             ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD).build(),
108                     BigInteger.valueOf(REG_VALUE_FROM_LOCAL)));
109             ab.setOrder(1);
110             ab.setKey(new ActionKey(1));
111
112             actionList.add(ab.build());
113
114             ib.setOrder(0);
115             ib.setKey(new InstructionKey(0));
116             instructions.add(ib.build());
117
118             // Next service GOTO Instructions Need to be appended to the List
119             ib = this.getMutablePipelineInstructionBuilder();
120             ib.setOrder(1);
121             ib.setKey(new InstructionKey(1));
122             instructions.add(ib.build());
123
124             // Add InstructionBuilder to the Instruction(s)Builder List
125             isb.setInstruction(instructions);
126
127             // Add InstructionsBuilder to FlowBuilder
128             flowBuilder.setInstructions(isb.build());
129
130             writeFlow(flowBuilder, nodeBuilder);
131         } else {
132             removeFlow(flowBuilder, nodeBuilder);
133         }
134     }
135
136     /*
137      * (Table:Classifier) Egress VM Traffic Towards TEP
138      * Match: Source Ethernet Addr and OpenFlow InPort
139      * Instruction: Set VLANID and GOTO Table Egress (n)
140      * table=0,in_port=2,dl_src=00:00:00:00:00:01 \
141      * actions=push_vlan, set_field:5->vlan_id,goto_table=<Next-Table>"
142      * table=0,in_port=1,vlan_tci=0x0000/0x1fff,dl_src=fa:16:3e:70:2f:c2 actions=push_vlan:0x8100,set_field:6097->vlan_vid,goto_table:20
143      */
144
145     @Override
146     public void programLocalInPortSetVlan(Long dpidLong, String segmentationId, Long inPort, String attachedMac, boolean write) {
147
148         String nodeName = OPENFLOW + dpidLong;
149
150         MatchBuilder matchBuilder = new MatchBuilder();
151         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
152         FlowBuilder flowBuilder = new FlowBuilder();
153
154         // Create the OF Match using MatchBuilder
155         flowBuilder.setMatch(MatchUtils.createEthSrcMatch(matchBuilder, new MacAddress(attachedMac)).build());
156         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
157         /* openflowplugin requires a vlan match to add a vlan */
158         flowBuilder.setMatch(MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(0), false).build());
159
160         String flowId = "LocalMac_"+segmentationId+"_"+inPort+"_"+attachedMac;
161         // Add Flow Attributes
162         flowBuilder.setId(new FlowId(flowId));
163         FlowKey key = new FlowKey(new FlowId(flowId));
164         flowBuilder.setStrict(true);
165         flowBuilder.setBarrier(false);
166         flowBuilder.setTableId(getTable());
167         flowBuilder.setKey(key);
168         flowBuilder.setFlowName(flowId);
169         flowBuilder.setHardTimeout(0);
170         flowBuilder.setIdleTimeout(0);
171
172         if (write) {
173             // Instantiate the Builders for the OF Actions and Instructions
174             InstructionBuilder ib = new InstructionBuilder();
175             InstructionsBuilder isb = new InstructionsBuilder();
176
177             // Instructions List Stores Individual Instructions
178             List<Instruction> instructions = Lists.newArrayList();
179
180             // Set VLAN ID Instruction
181             InstructionUtils.createSetVlanInstructions(ib, new VlanId(Integer.valueOf(segmentationId)));
182             ib.setOrder(0);
183             ib.setKey(new InstructionKey(0));
184             instructions.add(ib.build());
185
186             // Next service GOTO Instructions Need to be appended to the List
187             ib = this.getMutablePipelineInstructionBuilder();
188             ib.setOrder(1);
189             ib.setKey(new InstructionKey(1));
190             instructions.add(ib.build());
191
192             // Add InstructionBuilder to the Instruction(s)Builder List
193             isb.setInstruction(instructions);
194
195             // Add InstructionsBuilder to FlowBuilder
196             flowBuilder.setInstructions(isb.build());
197
198             writeFlow(flowBuilder, nodeBuilder);
199         } else {
200             removeFlow(flowBuilder, nodeBuilder);
201         }
202     }
203
204     /*
205      * (Table:Classifier) Drop frames source from a VM that do not
206      * match the associated MAC address of the local VM.
207      * Match: Low priority anything not matching the VM SMAC
208      * Instruction: Drop
209      * table=0,priority=16384,in_port=1 actions=drop"
210      */
211
212     @Override
213     public void programDropSrcIface(Long dpidLong, Long inPort, boolean write) {
214
215         String nodeName = OPENFLOW + dpidLong;
216
217         MatchBuilder matchBuilder = new MatchBuilder();
218         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
219         FlowBuilder flowBuilder = new FlowBuilder();
220
221         // Create the OF Match using MatchBuilder
222         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, inPort).build());
223
224         if (write) {
225             // Instantiate the Builders for the OF Actions and Instructions
226             InstructionBuilder ib = new InstructionBuilder();
227             InstructionsBuilder isb = new InstructionsBuilder();
228
229             // Instructions List Stores Individual Instructions
230             List<Instruction> instructions = Lists.newArrayList();
231
232             // Call the InstructionBuilder Methods Containing Actions
233             InstructionUtils.createDropInstructions(ib);
234             ib.setOrder(0);
235             ib.setKey(new InstructionKey(0));
236             instructions.add(ib.build());
237
238             // Add InstructionBuilder to the Instruction(s)Builder List
239             isb.setInstruction(instructions);
240
241             // Add InstructionsBuilder to FlowBuilder
242             flowBuilder.setInstructions(isb.build());
243         }
244
245         String flowId = "DropFilter_"+inPort;
246         // Add Flow Attributes
247         flowBuilder.setId(new FlowId(flowId));
248         FlowKey key = new FlowKey(new FlowId(flowId));
249         flowBuilder.setStrict(true);
250         flowBuilder.setBarrier(false);
251         flowBuilder.setTableId(getTable());
252         flowBuilder.setKey(key);
253         flowBuilder.setFlowName(flowId);
254         flowBuilder.setPriority(8192);
255         flowBuilder.setHardTimeout(0);
256         flowBuilder.setIdleTimeout(0);
257         if (write) {
258             writeFlow(flowBuilder, nodeBuilder);
259         } else {
260             removeFlow(flowBuilder, nodeBuilder);
261         }
262     }
263     /*
264      * (Table:0) Ingress Tunnel Traffic
265      * Match: OpenFlow InPort and Tunnel ID
266      * Action: GOTO Local Table (10)
267      * table=0,tun_id=0x5,in_port=10, actions=goto_table:2
268      */
269
270     @Override
271     public void programTunnelIn(Long dpidLong, String segmentationId,
272             Long ofPort, boolean write) {
273
274         String nodeName = OPENFLOW + dpidLong;
275
276         BigInteger tunnelId = new BigInteger(segmentationId);
277         MatchBuilder matchBuilder = new MatchBuilder();
278         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
279         FlowBuilder flowBuilder = new FlowBuilder();
280
281         // Create Match(es) and Set them in the FlowBuilder Object
282         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, tunnelId).build());
283         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, ofPort).build());
284
285         if (write) {
286             // Create the OF Actions and Instructions
287             InstructionBuilder ib = new InstructionBuilder();
288             InstructionsBuilder isb = new InstructionsBuilder();
289
290             // Instructions List Stores Individual Instructions
291             List<Instruction> instructions = Lists.newArrayList();
292
293             List<Action> actionList = Lists.newArrayList();
294             ActionBuilder ab = new ActionBuilder();
295             ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(REG_FIELD).build(),
296                     BigInteger.valueOf(REG_VALUE_FROM_REMOTE)));
297             ab.setOrder(0);
298             ab.setKey(new ActionKey(0));
299             actionList.add(ab.build());
300
301             ApplyActionsBuilder aab = new ApplyActionsBuilder();
302             aab.setAction(actionList);
303             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
304
305             // Call the InstructionBuilder Methods Containing Actions
306             ib.setOrder(0);
307             ib.setKey(new InstructionKey(0));
308             instructions.add(ib.build());
309
310             // Append the default pipeline after the first classification
311             ib = this.getMutablePipelineInstructionBuilder();
312             ib.setOrder(1);
313             ib.setKey(new InstructionKey(1));
314             instructions.add(ib.build());
315
316             // Add InstructionBuilder to the Instruction(s)Builder List
317             isb.setInstruction(instructions);
318
319             // Add InstructionsBuilder to FlowBuilder
320             flowBuilder.setInstructions(isb.build());
321         }
322
323         String flowId = "TunnelIn_"+segmentationId+"_"+ofPort;
324         // Add Flow Attributes
325         flowBuilder.setId(new FlowId(flowId));
326         FlowKey key = new FlowKey(new FlowId(flowId));
327         flowBuilder.setStrict(true);
328         flowBuilder.setBarrier(false);
329         flowBuilder.setTableId(getTable());
330         flowBuilder.setKey(key);
331         flowBuilder.setFlowName(flowId);
332         flowBuilder.setHardTimeout(0);
333         flowBuilder.setIdleTimeout(0);
334
335         if (write) {
336             writeFlow(flowBuilder, nodeBuilder);
337         } else {
338             removeFlow(flowBuilder, nodeBuilder);
339         }
340     }
341
342     /*
343      * (Table:0) Ingress VLAN Traffic
344      * Match: OpenFlow InPort and vlan ID
345      * Action: GOTO Local Table (20)
346      * table=0,vlan_id=0x5,in_port=10, actions=goto_table:2
347      * table=0,in_port=2,dl_vlan=2001 actions=goto_table:20
348      */
349
350     @Override
351     public void programVlanIn(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
352
353         String nodeName = OPENFLOW + dpidLong;
354
355         MatchBuilder matchBuilder = new MatchBuilder();
356         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
357         FlowBuilder flowBuilder = new FlowBuilder();
358
359         // Create Match(es) and Set them in the FlowBuilder Object
360         flowBuilder.setMatch(MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
361         flowBuilder.setMatch(MatchUtils.createInPortMatch(matchBuilder, dpidLong, ethPort).build());
362
363         if (write) {
364             // Create the OF Actions and Instructions
365             InstructionsBuilder isb = new InstructionsBuilder();
366
367             // Instructions List Stores Individual Instructions
368             List<Instruction> instructions = Lists.newArrayList();
369
370             // Append the default pipeline after the first classification
371             InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
372             ib.setOrder(0);
373             ib.setKey(new InstructionKey(0));
374             instructions.add(ib.build());
375
376             // Add InstructionBuilder to the Instruction(s)Builder List
377             isb.setInstruction(instructions);
378
379             // Add InstructionsBuilder to FlowBuilder
380             flowBuilder.setInstructions(isb.build());
381         }
382
383         String flowId = "VlanIn_"+segmentationId+"_"+ethPort;
384         // Add Flow Attributes
385         flowBuilder.setId(new FlowId(flowId));
386         FlowKey key = new FlowKey(new FlowId(flowId));
387         flowBuilder.setStrict(true);
388         flowBuilder.setBarrier(false);
389         flowBuilder.setTableId(getTable());
390         flowBuilder.setKey(key);
391         flowBuilder.setFlowName(flowId);
392         flowBuilder.setHardTimeout(0);
393         flowBuilder.setIdleTimeout(0);
394         if (write) {
395             writeFlow(flowBuilder, nodeBuilder);
396         } else {
397             removeFlow(flowBuilder, nodeBuilder);
398         }
399     }
400
401     /*
402      * Create an LLDP Flow Rule to encapsulate into
403      * a packet_in that is sent to the controller
404      * for topology handling.
405      * Match: Ethertype 0x88CCL
406      * Action: Punt to Controller in a Packet_In msg
407      */
408
409     @Override
410     public void programLLDPPuntRule(Long dpidLong) {
411
412         String nodeName = OPENFLOW + dpidLong;
413         EtherType etherType = new EtherType(0x88CCL);
414
415         MatchBuilder matchBuilder = new MatchBuilder();
416         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
417         FlowBuilder flowBuilder = new FlowBuilder();
418
419         // Create Match(es) and Set them in the FlowBuilder Object
420         flowBuilder.setMatch(MatchUtils.createEtherTypeMatch(matchBuilder, etherType).build());
421
422         // Create the OF Actions and Instructions
423         InstructionBuilder ib = new InstructionBuilder();
424         InstructionsBuilder isb = new InstructionsBuilder();
425
426         // Instructions List Stores Individual Instructions
427         List<Instruction> instructions = Lists.newArrayList();
428
429         // Call the InstructionBuilder Methods Containing Actions
430         InstructionUtils.createSendToControllerInstructions(nodeName, ib);
431         ib.setOrder(0);
432         ib.setKey(new InstructionKey(0));
433         instructions.add(ib.build());
434
435         // Add InstructionBuilder to the Instruction(s)Builder List
436         isb.setInstruction(instructions);
437
438         // Add InstructionsBuilder to FlowBuilder
439         flowBuilder.setInstructions(isb.build());
440
441         String flowId = "LLDP";
442         flowBuilder.setId(new FlowId(flowId));
443         FlowKey key = new FlowKey(new FlowId(flowId));
444         flowBuilder.setBarrier(true);
445         flowBuilder.setTableId(getTable());
446         flowBuilder.setKey(key);
447         flowBuilder.setFlowName(flowId);
448         flowBuilder.setHardTimeout(0);
449         flowBuilder.setIdleTimeout(0);
450         writeFlow(flowBuilder, nodeBuilder);
451     }
452
453     @Override
454     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
455         super.setDependencies(bundleContext.getServiceReference(ClassifierProvider.class.getName()), this);
456     }
457
458     @Override
459     public void setDependencies(Object impl) {}
460 }