Merge "Clean up logging"
[netvirt.git] / openstack / net-virt-providers / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / providers / openflow13 / services / L2ForwardingService.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.L2ForwardingProvider;
16 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
17 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
18 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
19 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
20 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
21 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
47 import org.osgi.framework.BundleContext;
48 import org.osgi.framework.ServiceReference;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import com.google.common.collect.Lists;
53
54 public class L2ForwardingService extends AbstractServiceInstance implements ConfigInterface, L2ForwardingProvider {
55     private static final Logger LOG = LoggerFactory.getLogger(L2ForwardingService.class);
56     public L2ForwardingService() {
57         super(Service.L2_FORWARDING);
58     }
59
60     public L2ForwardingService(Service service) {
61         super(service);
62     }
63
64     /*
65      * (Table:L2Forwarding) Local Unicast
66      * Match: Tunnel ID and dMAC
67      * Action: Output Port
68      * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 goto:<next-table>
69      */
70     @Override
71     public void programLocalUcastOut(Long dpidLong, String segmentationId,
72             Long localPort, String attachedMac, boolean write) {
73
74         String nodeName = OPENFLOW + dpidLong;
75
76         MatchBuilder matchBuilder = new MatchBuilder();
77         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
78         FlowBuilder flowBuilder = new FlowBuilder();
79
80         // Create the OF Match using MatchBuilder
81         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
82         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
83
84         String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
85         // Add Flow Attributes
86         flowBuilder.setId(new FlowId(flowId));
87         FlowKey key = new FlowKey(new FlowId(flowId));
88         flowBuilder.setStrict(true);
89         flowBuilder.setBarrier(false);
90         flowBuilder.setTableId(getTable());
91         flowBuilder.setKey(key);
92         flowBuilder.setFlowName(flowId);
93         flowBuilder.setHardTimeout(0);
94         flowBuilder.setIdleTimeout(0);
95
96         if (write) {
97             // Instantiate the Builders for the OF Actions and Instructions
98             InstructionBuilder ib = new InstructionBuilder();
99             InstructionsBuilder isb = new InstructionsBuilder();
100
101             // Instructions List Stores Individual Instructions
102             List<Instruction> instructions = Lists.newArrayList();
103
104             // Set the Output Port/Iface
105             InstructionUtils.createOutputPortInstructions(ib, dpidLong, localPort);
106             ib.setOrder(0);
107             ib.setKey(new InstructionKey(0));
108             instructions.add(ib.build());
109
110             // Add InstructionBuilder to the Instruction(s)Builder List
111             isb.setInstruction(instructions);
112
113             // Add InstructionsBuilder to FlowBuilder
114             flowBuilder.setInstructions(isb.build());
115             writeFlow(flowBuilder, nodeBuilder);
116         } else {
117             removeFlow(flowBuilder, nodeBuilder);
118         }
119     }
120     /*
121      * (Table:2) Local VLAN unicast
122      * Match: VLAN ID and dMAC
123      * Action: Output Port
124      * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
125      * table=110,dl_vlan=2001,dl_dst=fa:16:3e:a3:3b:cc actions=pop_vlan,output:1
126      */
127
128     @Override
129     public void programLocalVlanUcastOut (Long dpidLong, String segmentationId, Long localPort, String attachedMac, boolean write) {
130
131         String nodeName = OPENFLOW + dpidLong;
132
133         MatchBuilder matchBuilder = new MatchBuilder();
134         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
135         FlowBuilder flowBuilder = new FlowBuilder();
136
137         // Create the OF Match using MatchBuilder
138         flowBuilder.setMatch(
139                 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
140         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
141
142         String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
143         // Add Flow Attributes
144         flowBuilder.setId(new FlowId(flowId));
145         FlowKey key = new FlowKey(new FlowId(flowId));
146         flowBuilder.setStrict(true);
147         flowBuilder.setBarrier(false);
148         flowBuilder.setTableId(getTable());
149         flowBuilder.setKey(key);
150         flowBuilder.setFlowName(flowId);
151         flowBuilder.setHardTimeout(0);
152         flowBuilder.setIdleTimeout(0);
153
154         if (write) {
155             // Instantiate the Builders for the OF Actions and Instructions
156             InstructionBuilder ib = new InstructionBuilder();
157             InstructionsBuilder isb = new InstructionsBuilder();
158
159             // Instructions List Stores Individual Instructions
160             List<Instruction> instructions = Lists.newArrayList();
161             List<Instruction> instructions_tmp = Lists.newArrayList();
162
163             /* Strip vlan and store to tmp instruction space*/
164             InstructionUtils.createPopVlanInstructions(ib);
165             ib.setOrder(0);
166             ib.setKey(new InstructionKey(0));
167             instructions_tmp.add(ib.build());
168
169             // Set the Output Port/Iface
170             ib = new InstructionBuilder();
171             InstructionUtils.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
172             ib.setOrder(1);
173             ib.setKey(new InstructionKey(0));
174             instructions.add(ib.build());
175
176             // Add InstructionBuilder to the Instruction(s)Builder List
177             isb.setInstruction(instructions);
178
179             // Add InstructionsBuilder to FlowBuilder
180             flowBuilder.setInstructions(isb.build());
181             writeFlow(flowBuilder, nodeBuilder);
182         } else {
183             removeFlow(flowBuilder, nodeBuilder);
184         }
185     }
186
187
188     /**
189      * Utility function used by the flooding logic to allow a flow to be resubmitted
190      * to the local port flooding rule, after being outputed to all available tunnel
191      * or VLAN egress ports.
192      */
193     private void appendResubmitLocalFlood(InstructionBuilder ib) {
194
195         //Update the ApplyActions instructions
196         ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
197         List<Action> actionList = aac.getApplyActions().getAction();
198
199         int index = actionList.size();
200         ActionBuilder ab = new ActionBuilder();
201         ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(ClassifierService.REG_FIELD).build(),
202                 BigInteger.valueOf(ClassifierService.REG_VALUE_FROM_REMOTE)));
203         ab.setOrder(index);
204         ab.setKey(new ActionKey(index));
205         actionList.add(ab.build());
206
207         index++;
208         ab = new ActionBuilder();
209         ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
210         ab.setOrder(index);
211         ab.setKey(new ActionKey(index));
212         actionList.add(ab.build());
213     }
214
215     /*
216      * (Table:2) Local Broadcast Flood
217      * Match: Tunnel ID and dMAC (::::FF:FF)
218      * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
219      * actions=output:2,3,4,5
220      */
221
222     @Override
223     public void programLocalBcastOut(Long dpidLong, String segmentationId, Long localPort, boolean write) {
224
225         String nodeName = OPENFLOW + dpidLong;
226
227         MatchBuilder matchBuilder = new MatchBuilder();
228         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
229         FlowBuilder flowBuilder = new FlowBuilder();
230
231         // Create the OF Match using MatchBuilder
232         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
233         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
234         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
235                 new MacAddress("01:00:00:00:00:00")).build());
236
237         String flowId = "BcastOut_"+segmentationId;
238         // Add Flow Attributes
239         flowBuilder.setId(new FlowId(flowId));
240         FlowKey key = new FlowKey(new FlowId(flowId));
241         flowBuilder.setStrict(true);
242         flowBuilder.setBarrier(false);
243         flowBuilder.setTableId(getTable());
244         flowBuilder.setKey(key);
245         flowBuilder.setPriority(16384);
246         flowBuilder.setFlowName(flowId);
247         flowBuilder.setHardTimeout(0);
248         flowBuilder.setIdleTimeout(0);
249         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
250         // Instantiate the Builders for the OF Actions and Instructions
251         InstructionBuilder ib = new InstructionBuilder();
252         InstructionsBuilder isb = new InstructionsBuilder();
253         List<Instruction> instructions = Lists.newArrayList();
254         List<Instruction> existingInstructions = null;
255         if (flow != null) {
256             Instructions ins = flow.getInstructions();
257             if (ins != null) {
258                 existingInstructions = ins.getInstruction();
259             }
260         }
261
262         if (write) {
263             // Create output port list
264             createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
265             ib.setOrder(0);
266             ib.setKey(new InstructionKey(0));
267
268             /* Alternative method to address Bug 2004 is to make a call
269              * here to appendResubmitLocalFlood(ib) so that we send the
270              * flow back to the local flood rule.
271              */
272             instructions.add(ib.build());
273
274             // Add InstructionBuilder to the Instruction(s)Builder List
275             isb.setInstruction(instructions);
276
277             // Add InstructionsBuilder to FlowBuilder
278             flowBuilder.setInstructions(isb.build());
279
280             writeFlow(flowBuilder, nodeBuilder);
281         } else {
282             boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong, localPort,
283                     existingInstructions);
284             if (flowRemove) {
285                 /* if all ports are removed, remove flow */
286                 removeFlow(flowBuilder, nodeBuilder);
287             } else {
288                 /* Install instruction with new output port list*/
289                 ib.setOrder(0);
290                 ib.setKey(new InstructionKey(0));
291                 instructions.add(ib.build());
292
293                 // Add InstructionBuilder to the Instruction(s)Builder List
294                 isb.setInstruction(instructions);
295
296                 // Add InstructionsBuilder to FlowBuilder
297                 flowBuilder.setInstructions(isb.build());
298                 writeFlow(flowBuilder, nodeBuilder);
299             }
300         }
301     }
302
303     /*
304      * (Table:2) Local VLAN Broadcast Flood
305      * Match: vlan ID and dMAC (::::FF:FF)
306      * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
307      * actions=strip_vlan, output:2,3,4,5
308      * table=110,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
309      */
310
311     @Override
312     public void programLocalVlanBcastOut(Long dpidLong, String segmentationId,
313                                          Long localPort, Long ethPort, boolean write) {
314
315         String nodeName = OPENFLOW + dpidLong;
316
317         MatchBuilder matchBuilder = new MatchBuilder();
318         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
319         FlowBuilder flowBuilder = new FlowBuilder();
320
321         // Create the OF Match using MatchBuilder
322         flowBuilder.setMatch(
323                 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
324         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
325                 new MacAddress("01:00:00:00:00:00")).build());
326
327         String flowId = "VlanBcastOut_"+segmentationId+"_"+ethPort;
328         // Add Flow Attributes
329         flowBuilder.setId(new FlowId(flowId));
330         FlowKey key = new FlowKey(new FlowId(flowId));
331         flowBuilder.setStrict(true);
332         flowBuilder.setBarrier(false);
333         flowBuilder.setTableId(getTable());
334         flowBuilder.setKey(key);
335         flowBuilder.setPriority(16384);
336         flowBuilder.setFlowName(flowId);
337         flowBuilder.setHardTimeout(0);
338         flowBuilder.setIdleTimeout(0);
339         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
340         // Instantiate the Builders for the OF Actions and Instructions
341         List<Instruction> existingInstructions = null;
342         if (flow != null) {
343             Instructions ins = flow.getInstructions();
344             if (ins != null) {
345                 existingInstructions = ins.getInstruction();
346             }
347         }
348
349         List<Instruction> instructions = Lists.newArrayList();
350         InstructionBuilder ib = new InstructionBuilder();
351         List<Action> actionList = null;
352         if (write) {
353             if (existingInstructions == null) {
354                 /* First time called there should be no instructions.
355                  * We can simply add the output:ethPort first, followed by
356                  * popVlan and then the local port. The next calls will append
357                  * the rest of the local ports.
358                  */
359                 ActionBuilder ab = new ActionBuilder();
360                 actionList = Lists.newArrayList();
361
362                 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)));
363                 ab.setOrder(0);
364                 ab.setKey(new ActionKey(0));
365                 actionList.add(ab.build());
366
367                 ab.setAction(ActionUtils.popVlanAction());
368                 ab.setOrder(1);
369                 ab.setKey(new ActionKey(1));
370                 actionList.add(ab.build());
371
372                 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
373                 ab.setOrder(2);
374                 ab.setKey(new ActionKey(2));
375                 actionList.add(ab.build());
376             } else {
377                 /* Subsequent calls require appending any new local ports for this tenant. */
378                 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
379                 Instruction in = existingInstructions.get(0);
380                 actionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
381
382                 NodeConnectorId ncid = new NodeConnectorId(nodeName + ":" + localPort);
383                 boolean addNew = true;
384
385                 /* Check if the port is already in the output list */
386                 for (Action action : actionList) {
387                     if (action.getAction() instanceof OutputActionCase) {
388                         OutputActionCase opAction = (OutputActionCase) action.getAction();
389                         if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
390                             addNew = false;
391                             break;
392                         }
393                     }
394                 }
395
396                 if (addNew) {
397                     ActionBuilder ab = new ActionBuilder();
398
399                     ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
400                     ab.setOrder(actionList.size());
401                     ab.setKey(new ActionKey(actionList.size()));
402                     actionList.add(ab.build());
403                 }
404             }
405
406             ApplyActionsBuilder aab = new ApplyActionsBuilder();
407             aab.setAction(actionList);
408             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
409             ib.setOrder(0);
410             ib.setKey(new InstructionKey(0));
411             instructions.add(ib.build());
412
413             // Add InstructionBuilder to the Instruction(s)Builder List
414             InstructionsBuilder isb = new InstructionsBuilder();
415             isb.setInstruction(instructions);
416
417             // Add InstructionsBuilder to FlowBuilder
418             flowBuilder.setInstructions(isb.build());
419             writeFlow(flowBuilder, nodeBuilder);
420         } else {
421             //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
422             //                     localPort, existingInstructions);
423             boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort, ethPort,
424                     existingInstructions);
425             if (flowRemove) {
426                 /* if all ports are removed, remove flow */
427                 removeFlow(flowBuilder, nodeBuilder);
428             } else {
429                 /* Install instruction with new output port list*/
430                 ib.setOrder(0);
431                 ib.setKey(new InstructionKey(0));
432                 instructions.add(ib.build());
433
434                 // Add InstructionBuilder to the Instruction(s)Builder List
435                 InstructionsBuilder isb = new InstructionsBuilder();
436                 isb.setInstruction(instructions);
437
438                 // Add InstructionsBuilder to FlowBuilder
439                 flowBuilder.setInstructions(isb.build());
440                 writeFlow(flowBuilder, nodeBuilder);
441             }
442         }
443     }
444
445     private boolean removeOutputPortFromInstructions(InstructionBuilder ib, Long dpidLong, Long localPort,
446                                                      Long ethPort, List<Instruction> instructions) {
447         List<Action> actionList = Lists.newArrayList();
448         boolean removeFlow = true;
449
450         if (instructions != null) {
451             ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
452             Instruction in = instructions.get(0);
453             List<Action> oldActionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
454             NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + localPort);
455             NodeConnectorId ncidEth = new NodeConnectorId(OPENFLOW + dpidLong + ":" + ethPort);
456
457             // Remove the port from the output list
458             ActionBuilder ab = new ActionBuilder();
459             int index = 2;
460             //for (ListIterator<Action> it = oldActionList.listIterator(oldActionList.size()); it.hasPrevious();) {
461             //    Action action = it.previous();
462             for (Action action : oldActionList) {
463                 if (action.getAction() instanceof OutputActionCase) {
464                     OutputActionCase opAction = (OutputActionCase) action.getAction();
465                     if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncidEth))) {
466                         actionList.add(action);
467                     } else if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid)) == false) {
468                         ab.setAction(action.getAction());
469                         ab.setOrder(index);
470                         ab.setKey(new ActionKey(index));
471                         actionList.add(ab.build());
472                         index++;
473                     }
474                 } else {
475                     actionList.add(action);
476                 }
477             }
478             ApplyActionsBuilder aab = new ApplyActionsBuilder();
479             aab.setAction(actionList);
480             ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
481         }
482
483         if (actionList != null && actionList.size() > 2) {
484             // Add InstructionBuilder to the Instruction(s)Builder List
485             InstructionsBuilder isb = new InstructionsBuilder();
486             isb.setInstruction(instructions);
487             removeFlow = false;
488         }
489
490         return removeFlow;
491     }
492
493     /*
494      * (Table:1) Local Table Miss
495      * Match: Any Remaining Flows w/a TunID
496      * Action: Drop w/ a low priority
497      * table=2,priority=8192,tun_id=0x5 actions=drop
498      */
499
500     @Override
501     public void programLocalTableMiss(Long dpidLong, String segmentationId, boolean write) {
502
503         String nodeName = OPENFLOW + dpidLong;
504
505         MatchBuilder matchBuilder = new MatchBuilder();
506         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
507         FlowBuilder flowBuilder = new FlowBuilder();
508
509         // Create Match(es) and Set them in the FlowBuilder Object
510         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
511
512         if (write) {
513             // Create the OF Actions and Instructions
514             InstructionBuilder ib = new InstructionBuilder();
515             InstructionsBuilder isb = new InstructionsBuilder();
516
517             // Instructions List Stores Individual Instructions
518             List<Instruction> instructions = Lists.newArrayList();
519
520             // Call the InstructionBuilder Methods Containing Actions
521             InstructionUtils.createDropInstructions(ib);
522             ib.setOrder(0);
523             ib.setKey(new InstructionKey(0));
524             instructions.add(ib.build());
525
526             // Add InstructionBuilder to the Instruction(s)Builder List
527             isb.setInstruction(instructions);
528
529             // Add InstructionsBuilder to FlowBuilder
530             flowBuilder.setInstructions(isb.build());
531         }
532
533         String flowId = "LocalTableMiss_"+segmentationId;
534         // Add Flow Attributes
535         flowBuilder.setId(new FlowId(flowId));
536         FlowKey key = new FlowKey(new FlowId(flowId));
537         flowBuilder.setStrict(true);
538         flowBuilder.setBarrier(false);
539         flowBuilder.setTableId(getTable());
540         flowBuilder.setKey(key);
541         flowBuilder.setPriority(8192);
542         flowBuilder.setFlowName(flowId);
543         flowBuilder.setHardTimeout(0);
544         flowBuilder.setIdleTimeout(0);
545         if (write) {
546             writeFlow(flowBuilder, nodeBuilder);
547         } else {
548             removeFlow(flowBuilder, nodeBuilder);
549         }
550     }
551
552     /*
553      * (Table:1) Local Table Miss
554      * Match: Any Remaining Flows w/a VLAN ID
555      * Action: Drop w/ a low priority
556      * table=2,priority=8192,vlan_id=0x5 actions=drop
557      */
558
559     @Override
560     public void programLocalVlanTableMiss(Long dpidLong, String segmentationId, boolean write) {
561
562         String nodeName = OPENFLOW + dpidLong;
563
564         MatchBuilder matchBuilder = new MatchBuilder();
565         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
566         FlowBuilder flowBuilder = new FlowBuilder();
567
568         // Create Match(es) and Set them in the FlowBuilder Object
569         flowBuilder.setMatch(
570                 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
571
572         if (write) {
573             // Create the OF Actions and Instructions
574             InstructionBuilder ib = new InstructionBuilder();
575             InstructionsBuilder isb = new InstructionsBuilder();
576
577             // Instructions List Stores Individual Instructions
578             List<Instruction> instructions = Lists.newArrayList();
579
580             // Call the InstructionBuilder Methods Containing Actions
581             InstructionUtils.createDropInstructions(ib);
582             ib.setOrder(0);
583             ib.setKey(new InstructionKey(0));
584             instructions.add(ib.build());
585
586             // Add InstructionBuilder to the Instruction(s)Builder List
587             isb.setInstruction(instructions);
588
589             // Add InstructionsBuilder to FlowBuilder
590             flowBuilder.setInstructions(isb.build());
591         }
592
593         String flowId = "LocalTableMiss_"+segmentationId;
594         // Add Flow Attributes
595         flowBuilder.setId(new FlowId(flowId));
596         FlowKey key = new FlowKey(new FlowId(flowId));
597         flowBuilder.setStrict(true);
598         flowBuilder.setBarrier(false);
599         flowBuilder.setTableId(getTable());
600         flowBuilder.setKey(key);
601         flowBuilder.setPriority(8192);
602         flowBuilder.setFlowName(flowId);
603         flowBuilder.setHardTimeout(0);
604         flowBuilder.setIdleTimeout(0);
605         if (write) {
606             writeFlow(flowBuilder, nodeBuilder);
607         } else {
608             removeFlow(flowBuilder, nodeBuilder);
609         }
610     }
611
612
613     /*
614      * (Table:1) Egress Tunnel Traffic
615      * Match: Destination Ethernet Addr and Local InPort
616      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
617      * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
618      * actions=output:10,goto_table:2"
619      */
620     // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
621     @Override
622     public void programTunnelOut(Long dpidLong, String segmentationId, Long OFPortOut, String attachedMac, boolean write) {
623
624         String nodeName = OPENFLOW + dpidLong;
625
626         MatchBuilder matchBuilder = new MatchBuilder();
627         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
628         FlowBuilder flowBuilder = new FlowBuilder();
629
630         // Create the OF Match using MatchBuilder
631         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
632         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
633
634         String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
635         // Add Flow Attributes
636         flowBuilder.setId(new FlowId(flowId));
637         FlowKey key = new FlowKey(new FlowId(flowId));
638         flowBuilder.setStrict(true);
639         flowBuilder.setBarrier(false);
640         flowBuilder.setTableId(getTable());
641         flowBuilder.setKey(key);
642         flowBuilder.setFlowName(flowId);
643         flowBuilder.setHardTimeout(0);
644         flowBuilder.setIdleTimeout(0);
645
646         if (write) {
647             // Instantiate the Builders for the OF Actions and Instructions
648             InstructionBuilder ib = new InstructionBuilder();
649             InstructionsBuilder isb = new InstructionsBuilder();
650
651             // Instructions List Stores Individual Instructions
652             List<Instruction> instructions = Lists.newArrayList();
653
654             // Set the Output Port/Iface
655             InstructionUtils.createOutputPortInstructions(ib, dpidLong, OFPortOut);
656             ib.setOrder(0);
657             ib.setKey(new InstructionKey(1));
658             instructions.add(ib.build());
659
660             // Add InstructionBuilder to the Instruction(s)Builder List
661             isb.setInstruction(instructions);
662
663             // Add InstructionsBuilder to FlowBuilder
664             flowBuilder.setInstructions(isb.build());
665
666             writeFlow(flowBuilder, nodeBuilder);
667         } else {
668             removeFlow(flowBuilder, nodeBuilder);
669         }
670     }
671
672     /*
673      * (Table:1) Egress VLAN Traffic
674      * Match: Destination Ethernet Addr and VLAN id
675      * Instruction: GOTO Table Table 2
676      * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
677      * actions= goto_table:2"
678      */
679     // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
680     @Override
681     public void programVlanOut(Long dpidLong, String segmentationId, Long ethPort, String attachedMac, boolean write) {
682
683         String nodeName = OPENFLOW + dpidLong;
684
685         MatchBuilder matchBuilder = new MatchBuilder();
686         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
687         FlowBuilder flowBuilder = new FlowBuilder();
688
689         // Create the OF Match using MatchBuilder
690         flowBuilder.setMatch(
691                 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
692         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
693
694         String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
695         // Add Flow Attributes
696         flowBuilder.setId(new FlowId(flowId));
697         FlowKey key = new FlowKey(new FlowId(flowId));
698         flowBuilder.setStrict(true);
699         flowBuilder.setBarrier(false);
700         flowBuilder.setTableId(getTable());
701         flowBuilder.setKey(key);
702         flowBuilder.setFlowName(flowId);
703         flowBuilder.setHardTimeout(0);
704         flowBuilder.setIdleTimeout(0);
705
706         if (write) {
707             // Instantiate the Builders for the OF Actions and Instructions
708             InstructionBuilder ib = new InstructionBuilder();
709             InstructionsBuilder isb = new InstructionsBuilder();
710
711             // Instructions List Stores Individual Instructions
712             List<Instruction> instructions = Lists.newArrayList();
713             InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
714             ib.setOrder(0);
715             ib.setKey(new InstructionKey(1));
716             instructions.add(ib.build());
717
718             // Add InstructionBuilder to the Instruction(s)Builder List
719             isb.setInstruction(instructions);
720
721             // Add InstructionsBuilder to FlowBuilder
722             flowBuilder.setInstructions(isb.build());
723
724             writeFlow(flowBuilder, nodeBuilder);
725         } else {
726             removeFlow(flowBuilder, nodeBuilder);
727         }
728     }
729
730     /*
731      * (Table:1) Egress Tunnel Traffic
732      * Match: Destination Ethernet Addr and Local InPort
733      * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
734      * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
735      * actions=output:10,output:11,goto_table:2
736      */
737     @Override
738     public void programTunnelFloodOut(Long dpidLong, String segmentationId, Long OFPortOut, boolean write) {
739
740         String nodeName = OPENFLOW + dpidLong;
741
742         MatchBuilder matchBuilder = new MatchBuilder();
743         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
744         FlowBuilder flowBuilder = new FlowBuilder();
745
746         // Create the OF Match using MatchBuilder
747         // Match TunnelID
748         MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
749         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
750         // Match DMAC
751         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
752                 new MacAddress("01:00:00:00:00:00")).build());
753
754         String flowId = "TunnelFloodOut_"+segmentationId;
755         // Add Flow Attributes
756         flowBuilder.setId(new FlowId(flowId));
757         FlowKey key = new FlowKey(new FlowId(flowId));
758         flowBuilder.setBarrier(true);
759         flowBuilder.setTableId(getTable());
760         flowBuilder.setKey(key);
761         flowBuilder.setPriority(16383);  // FIXME: change it back to 16384 once bug 3005 is fixed.
762         flowBuilder.setFlowName(flowId);
763         flowBuilder.setHardTimeout(0);
764         flowBuilder.setIdleTimeout(0);
765
766         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
767         // Instantiate the Builders for the OF Actions and Instructions
768         InstructionBuilder ib = new InstructionBuilder();
769         InstructionsBuilder isb = new InstructionsBuilder();
770         List<Instruction> instructions = Lists.newArrayList();
771         List<Instruction> existingInstructions = null;
772         if (flow != null) {
773             Instructions ins = flow.getInstructions();
774             if (ins != null) {
775                 existingInstructions = ins.getInstruction();
776             }
777         }
778
779         if (write) {
780             // Set the Output Port/Iface
781             //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
782             createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
783             ib.setOrder(0);
784             ib.setKey(new InstructionKey(0));
785             instructions.add(ib.build());
786
787             // Add InstructionBuilder to the Instruction(s)Builder List
788             isb.setInstruction(instructions);
789
790             // Add InstructionsBuilder to FlowBuilder
791             flowBuilder.setInstructions(isb.build());
792
793             writeFlow(flowBuilder, nodeBuilder);
794         } else {
795             /* remove port from action list */
796             boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
797                     OFPortOut, existingInstructions);
798             if (flowRemove) {
799                 /* if all port are removed, remove the flow too. */
800                 removeFlow(flowBuilder, nodeBuilder);
801             } else {
802                 /* Install instruction with new output port list*/
803                 ib.setOrder(0);
804                 ib.setKey(new InstructionKey(0));
805                 instructions.add(ib.build());
806
807                 // Add InstructionBuilder to the Instruction(s)Builder List
808                 isb.setInstruction(instructions);
809
810                 // Add InstructionsBuilder to FlowBuilder
811                 flowBuilder.setInstructions(isb.build());
812                 writeFlow(flowBuilder, nodeBuilder);
813             }
814         }
815     }
816
817     /*
818      * (Table:1) Egress VLAN Traffic
819      * Match: Destination Ethernet Addr and VLAN id
820      * Instruction: GOTO table 2 and Output port eth interface
821      * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
822      * actions=output:eth1,goto_table:2
823      */
824
825     @Override
826     public void programVlanFloodOut(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
827
828         String nodeName = OPENFLOW + dpidLong;
829
830         MatchBuilder matchBuilder = new MatchBuilder();
831         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
832         FlowBuilder flowBuilder = new FlowBuilder();
833
834         // Create the OF Match using MatchBuilder
835         // Match Vlan ID
836         flowBuilder.setMatch(
837                 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
838         // Match DMAC
839         flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
840                 new MacAddress("01:00:00:00:00:00")).build());
841
842         String flowId = "VlanFloodOut_"+segmentationId+"_"+ethPort;
843         // Add Flow Attributes
844         flowBuilder.setId(new FlowId(flowId));
845         FlowKey key = new FlowKey(new FlowId(flowId));
846         flowBuilder.setBarrier(true);
847         flowBuilder.setTableId(getTable());
848         flowBuilder.setKey(key);
849         flowBuilder.setPriority(16384);
850         flowBuilder.setFlowName(flowId);
851         flowBuilder.setHardTimeout(0);
852         flowBuilder.setIdleTimeout(0);
853
854         //ToDo: Is there something to be done with result of the call to getFlow?
855
856         Flow flow = this.getFlow(flowBuilder, nodeBuilder);
857         // Instantiate the Builders for the OF Actions and Instructions
858         InstructionBuilder ib = new InstructionBuilder();
859         InstructionsBuilder isb = new InstructionsBuilder();
860         List<Instruction> instructions = Lists.newArrayList();
861
862         if (write) {
863             // Set the Output Port/Iface
864             InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
865             ib.setOrder(0);
866             ib.setKey(new InstructionKey(0));
867             instructions.add(ib.build());
868
869             // Add InstructionBuilder to the Instruction(s)Builder List
870             isb.setInstruction(instructions);
871
872             // Add InstructionsBuilder to FlowBuilder
873             flowBuilder.setInstructions(isb.build());
874
875             writeFlow(flowBuilder, nodeBuilder);
876         } else {
877             removeFlow(flowBuilder, nodeBuilder);
878         }
879     }
880
881     /*
882      * (Table:1) Table Drain w/ Catch All
883      * Match: Tunnel ID
884      * Action: GOTO Local Table (10)
885      * table=2,priority=8192,tun_id=0x5 actions=drop
886      */
887     @Override
888     public void programTunnelMiss(Long dpidLong, String segmentationId, boolean write) {
889
890         String nodeName = OPENFLOW + dpidLong;
891
892         MatchBuilder matchBuilder = new MatchBuilder();
893         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
894         FlowBuilder flowBuilder = new FlowBuilder();
895
896         // Create Match(es) and Set them in the FlowBuilder Object
897         flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
898
899         if (write) {
900             // Create the OF Actions and Instructions
901             InstructionBuilder ib = new InstructionBuilder();
902             InstructionsBuilder isb = new InstructionsBuilder();
903
904             // Instructions List Stores Individual Instructions
905             List<Instruction> instructions = Lists.newArrayList();
906
907             // Call the InstructionBuilder Methods Containing Actions
908             ib = this.getMutablePipelineInstructionBuilder();
909             ib.setOrder(0);
910             ib.setKey(new InstructionKey(0));
911             instructions.add(ib.build());
912
913             // Add InstructionBuilder to the Instruction(s)Builder List
914             isb.setInstruction(instructions);
915
916             // Add InstructionsBuilder to FlowBuilder
917             flowBuilder.setInstructions(isb.build());
918         }
919
920         String flowId = "TunnelMiss_"+segmentationId;
921         // Add Flow Attributes
922         flowBuilder.setId(new FlowId(flowId));
923         FlowKey key = new FlowKey(new FlowId(flowId));
924         flowBuilder.setStrict(true);
925         flowBuilder.setBarrier(false);
926         flowBuilder.setTableId(getTable());
927         flowBuilder.setKey(key);
928         flowBuilder.setPriority(8192);
929         flowBuilder.setFlowName(flowId);
930         flowBuilder.setHardTimeout(0);
931         flowBuilder.setIdleTimeout(0);
932         if (write) {
933             writeFlow(flowBuilder, nodeBuilder);
934         } else {
935             removeFlow(flowBuilder, nodeBuilder);
936         }
937     }
938
939     /*
940      * (Table:1) Table Drain w/ Catch All
941      * Match: Vlan ID
942      * Action: Output port eth interface
943      * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
944      * table=110,priority=8192,dl_vlan=2001 actions=output:2
945      */
946
947     @Override
948     public void programVlanMiss(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
949
950         String nodeName = OPENFLOW + dpidLong;
951
952         MatchBuilder matchBuilder = new MatchBuilder();
953         NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
954         FlowBuilder flowBuilder = new FlowBuilder();
955
956         // Create Match(es) and Set them in the FlowBuilder Object
957         flowBuilder.setMatch(
958                 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
959
960         if (write) {
961             // Create the OF Actions and Instructions
962             InstructionBuilder ib = new InstructionBuilder();
963             InstructionsBuilder isb = new InstructionsBuilder();
964
965             // Instructions List Stores Individual Instructions
966             List<Instruction> instructions = Lists.newArrayList();
967
968             // Set the Output Port/Iface
969             InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
970             ib.setOrder(0);
971             ib.setKey(new InstructionKey(1));
972             instructions.add(ib.build());
973
974             // Add InstructionBuilder to the Instruction(s)Builder List
975             isb.setInstruction(instructions);
976
977             // Add InstructionsBuilder to FlowBuilder
978             flowBuilder.setInstructions(isb.build());
979         }
980
981         String flowId = "VlanMiss_"+segmentationId;
982         // Add Flow Attributes
983         flowBuilder.setId(new FlowId(flowId));
984         FlowKey key = new FlowKey(new FlowId(flowId));
985         flowBuilder.setStrict(true);
986         flowBuilder.setBarrier(false);
987         flowBuilder.setTableId(getTable());
988         flowBuilder.setKey(key);
989         flowBuilder.setPriority(8192);
990         flowBuilder.setFlowName(flowId);
991         flowBuilder.setHardTimeout(0);
992         flowBuilder.setIdleTimeout(0);
993         if (write) {
994             writeFlow(flowBuilder, nodeBuilder);
995         } else {
996             removeFlow(flowBuilder, nodeBuilder);
997         }
998     }
999
1000     /**
1001      * Create Output Port Group Instruction
1002      *
1003      * @param ib       Map InstructionBuilder without any instructions
1004      * @param dpidLong Long the datapath ID of a switch/node
1005      * @param port     Long representing a port on a switch/node
1006      * @return ib InstructionBuilder Map with instructions
1007      */
1008     protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
1009             Long dpidLong, Long port ,
1010             List<Instruction> instructions) {
1011         NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
1012         LOG.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1013
1014         List<Action> actionList = Lists.newArrayList();
1015         ActionBuilder ab = new ActionBuilder();
1016
1017         List<Action> existingActions;
1018         if (instructions != null && instructions.size() > 0) {
1019             /**
1020              * First instruction is the one containing the output ports.
1021              * So, only extract the actions from that.
1022              */
1023             Instruction in = instructions.get(0);
1024             if (in.getInstruction() instanceof ApplyActionsCase) {
1025                 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1026                 // Only include output actions
1027                 for (Action action : existingActions) {
1028                     if (action.getAction() instanceof OutputActionCase) {
1029                         actionList.add(action);
1030                     }
1031                 }
1032             }
1033         }
1034         /* Create output action for this port*/
1035         OutputActionBuilder oab = new OutputActionBuilder();
1036         oab.setOutputNodeConnector(ncid);
1037         ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
1038         boolean addNew = true;
1039
1040         /* Find the group action and get the group */
1041         for (Action action : actionList) {
1042             OutputActionCase opAction = (OutputActionCase)action.getAction();
1043             /* If output port action already in the action list of one of the buckets, skip */
1044             if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
1045                 addNew = false;
1046                 break;
1047             }
1048         }
1049         if (addNew) {
1050             ab.setOrder(actionList.size());
1051             ab.setKey(new ActionKey(actionList.size()));
1052             actionList.add(ab.build());
1053         }
1054         // Create an Apply Action
1055         ApplyActionsBuilder aab = new ApplyActionsBuilder();
1056         aab.setAction(actionList);
1057         ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1058         LOG.debug("createOutputPortInstructions() : applyAction {}", aab.build());
1059         return ib;
1060     }
1061
1062     @Override
1063     public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
1064         super.setDependencies(bundleContext.getServiceReference(L2ForwardingProvider.class.getName()), this);
1065     }
1066
1067     @Override
1068     public void setDependencies(Object impl) {
1069
1070     }
1071 }