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