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