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