2 * Copyright (C) 2014 Red Hat, Inc.
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
8 * Authors : Madhu Venugopal
10 package org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.services;
12 import java.math.BigInteger;
13 import java.util.List;
15 //import java.util.ListIterator;
16 import org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
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.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 import com.google.common.collect.Lists;
52 public class L2ForwardingService extends AbstractServiceInstance implements L2ForwardingProvider {
53 private static final Logger logger = LoggerFactory.getLogger(L2ForwardingService.class);
54 public L2ForwardingService() {
55 super(Service.L2_FORWARDING);
58 public L2ForwardingService(Service service) {
63 * (Table:L2Forwarding) Local Unicast
64 * Match: Tunnel ID and dMAC
66 * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 goto:<next-table>
69 public void programLocalUcastOut(Long dpidLong, String segmentationId,
70 Long localPort, String attachedMac, boolean write) {
72 String nodeName = OPENFLOW + dpidLong;
74 MatchBuilder matchBuilder = new MatchBuilder();
75 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
76 FlowBuilder flowBuilder = new FlowBuilder();
78 // Create the OF Match using MatchBuilder
79 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
80 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
82 String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
83 // Add Flow Attributes
84 flowBuilder.setId(new FlowId(flowId));
85 FlowKey key = new FlowKey(new FlowId(flowId));
86 flowBuilder.setStrict(true);
87 flowBuilder.setBarrier(false);
88 flowBuilder.setTableId(getTable());
89 flowBuilder.setKey(key);
90 flowBuilder.setFlowName(flowId);
91 flowBuilder.setHardTimeout(0);
92 flowBuilder.setIdleTimeout(0);
95 // Instantiate the Builders for the OF Actions and Instructions
96 InstructionBuilder ib = new InstructionBuilder();
97 InstructionsBuilder isb = new InstructionsBuilder();
99 // Instructions List Stores Individual Instructions
100 List<Instruction> instructions = Lists.newArrayList();
102 // Set the Output Port/Iface
103 InstructionUtils.createOutputPortInstructions(ib, dpidLong, localPort);
105 ib.setKey(new InstructionKey(0));
106 instructions.add(ib.build());
108 // Add InstructionBuilder to the Instruction(s)Builder List
109 isb.setInstruction(instructions);
111 // Add InstructionsBuilder to FlowBuilder
112 flowBuilder.setInstructions(isb.build());
113 writeFlow(flowBuilder, nodeBuilder);
115 removeFlow(flowBuilder, nodeBuilder);
119 * (Table:2) Local VLAN unicast
120 * Match: VLAN ID and dMAC
121 * Action: Output Port
122 * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
123 * table=110,dl_vlan=2001,dl_dst=fa:16:3e:a3:3b:cc actions=pop_vlan,output:1
127 public void programLocalVlanUcastOut (Long dpidLong, String segmentationId, Long localPort, String attachedMac, boolean write) {
129 String nodeName = OPENFLOW + dpidLong;
131 MatchBuilder matchBuilder = new MatchBuilder();
132 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
133 FlowBuilder flowBuilder = new FlowBuilder();
135 // Create the OF Match using MatchBuilder
136 flowBuilder.setMatch(
137 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
138 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
140 String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
141 // Add Flow Attributes
142 flowBuilder.setId(new FlowId(flowId));
143 FlowKey key = new FlowKey(new FlowId(flowId));
144 flowBuilder.setStrict(true);
145 flowBuilder.setBarrier(false);
146 flowBuilder.setTableId(getTable());
147 flowBuilder.setKey(key);
148 flowBuilder.setFlowName(flowId);
149 flowBuilder.setHardTimeout(0);
150 flowBuilder.setIdleTimeout(0);
153 // Instantiate the Builders for the OF Actions and Instructions
154 InstructionBuilder ib = new InstructionBuilder();
155 InstructionsBuilder isb = new InstructionsBuilder();
157 // Instructions List Stores Individual Instructions
158 List<Instruction> instructions = Lists.newArrayList();
159 List<Instruction> instructions_tmp = Lists.newArrayList();
161 /* Strip vlan and store to tmp instruction space*/
162 InstructionUtils.createPopVlanInstructions(ib);
164 ib.setKey(new InstructionKey(0));
165 instructions_tmp.add(ib.build());
167 // Set the Output Port/Iface
168 ib = new InstructionBuilder();
169 InstructionUtils.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
171 ib.setKey(new InstructionKey(0));
172 instructions.add(ib.build());
174 // Add InstructionBuilder to the Instruction(s)Builder List
175 isb.setInstruction(instructions);
177 // Add InstructionsBuilder to FlowBuilder
178 flowBuilder.setInstructions(isb.build());
179 writeFlow(flowBuilder, nodeBuilder);
181 removeFlow(flowBuilder, nodeBuilder);
187 * Utility function used by the flooding logic to allow a flow to be resubmitted
188 * to the local port flooding rule, after being outputed to all available tunnel
189 * or VLAN egress ports.
191 private void appendResubmitLocalFlood(InstructionBuilder ib) {
193 //Update the ApplyActions instructions
194 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
195 List<Action> actionList = aac.getApplyActions().getAction();
197 int index = actionList.size();
198 ActionBuilder ab = new ActionBuilder();
199 ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(ClassifierService.REG_FIELD).build(),
200 BigInteger.valueOf(ClassifierService.REG_VALUE_FROM_REMOTE)));
202 ab.setKey(new ActionKey(index));
203 actionList.add(ab.build());
206 ab = new ActionBuilder();
207 ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
209 ab.setKey(new ActionKey(index));
210 actionList.add(ab.build());
214 * (Table:2) Local Broadcast Flood
215 * Match: Tunnel ID and dMAC (::::FF:FF)
216 * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
217 * actions=output:2,3,4,5
221 public void programLocalBcastOut(Long dpidLong, String segmentationId, Long localPort, boolean write) {
223 String nodeName = OPENFLOW + dpidLong;
225 MatchBuilder matchBuilder = new MatchBuilder();
226 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
227 FlowBuilder flowBuilder = new FlowBuilder();
229 // Create the OF Match using MatchBuilder
230 MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
231 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
232 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
233 new MacAddress("01:00:00:00:00:00")).build());
235 String flowId = "BcastOut_"+segmentationId;
236 // Add Flow Attributes
237 flowBuilder.setId(new FlowId(flowId));
238 FlowKey key = new FlowKey(new FlowId(flowId));
239 flowBuilder.setStrict(true);
240 flowBuilder.setBarrier(false);
241 flowBuilder.setTableId(getTable());
242 flowBuilder.setKey(key);
243 flowBuilder.setPriority(16384);
244 flowBuilder.setFlowName(flowId);
245 flowBuilder.setHardTimeout(0);
246 flowBuilder.setIdleTimeout(0);
247 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
248 // Instantiate the Builders for the OF Actions and Instructions
249 InstructionBuilder ib = new InstructionBuilder();
250 InstructionsBuilder isb = new InstructionsBuilder();
251 List<Instruction> instructions = Lists.newArrayList();
252 List<Instruction> existingInstructions = null;
254 Instructions ins = flow.getInstructions();
256 existingInstructions = ins.getInstruction();
261 // Create output port list
262 createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
264 ib.setKey(new InstructionKey(0));
266 /* Alternative method to address Bug 2004 is to make a call
267 * here to appendResubmitLocalFlood(ib) so that we send the
268 * flow back to the local flood rule.
270 instructions.add(ib.build());
272 // Add InstructionBuilder to the Instruction(s)Builder List
273 isb.setInstruction(instructions);
275 // Add InstructionsBuilder to FlowBuilder
276 flowBuilder.setInstructions(isb.build());
278 writeFlow(flowBuilder, nodeBuilder);
280 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong, localPort,
281 existingInstructions);
283 /* if all ports are removed, remove flow */
284 removeFlow(flowBuilder, nodeBuilder);
286 /* Install instruction with new output port list*/
288 ib.setKey(new InstructionKey(0));
289 instructions.add(ib.build());
291 // Add InstructionBuilder to the Instruction(s)Builder List
292 isb.setInstruction(instructions);
294 // Add InstructionsBuilder to FlowBuilder
295 flowBuilder.setInstructions(isb.build());
296 writeFlow(flowBuilder, nodeBuilder);
302 * (Table:2) Local VLAN Broadcast Flood
303 * Match: vlan ID and dMAC (::::FF:FF)
304 * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
305 * actions=strip_vlan, output:2,3,4,5
306 * 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
310 public void programLocalVlanBcastOut(Long dpidLong, String segmentationId,
311 Long localPort, Long ethPort, boolean write) {
313 String nodeName = OPENFLOW + dpidLong;
315 MatchBuilder matchBuilder = new MatchBuilder();
316 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
317 FlowBuilder flowBuilder = new FlowBuilder();
319 // Create the OF Match using MatchBuilder
320 flowBuilder.setMatch(
321 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
322 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
323 new MacAddress("01:00:00:00:00:00")).build());
325 String flowId = "VlanBcastOut_"+segmentationId+"_"+ethPort;
326 // Add Flow Attributes
327 flowBuilder.setId(new FlowId(flowId));
328 FlowKey key = new FlowKey(new FlowId(flowId));
329 flowBuilder.setStrict(true);
330 flowBuilder.setBarrier(false);
331 flowBuilder.setTableId(getTable());
332 flowBuilder.setKey(key);
333 flowBuilder.setPriority(16384);
334 flowBuilder.setFlowName(flowId);
335 flowBuilder.setHardTimeout(0);
336 flowBuilder.setIdleTimeout(0);
337 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
338 // Instantiate the Builders for the OF Actions and Instructions
339 List<Instruction> existingInstructions = null;
341 Instructions ins = flow.getInstructions();
343 existingInstructions = ins.getInstruction();
347 List<Instruction> instructions = Lists.newArrayList();
348 InstructionBuilder ib = new InstructionBuilder();
349 List<Action> actionList = null;
351 if (existingInstructions == null) {
352 /* First time called there should be no instructions.
353 * We can simply add the output:ethPort first, followed by
354 * popVlan and then the local port. The next calls will append
355 * the rest of the local ports.
357 ActionBuilder ab = new ActionBuilder();
358 actionList = Lists.newArrayList();
360 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)));
362 ab.setKey(new ActionKey(0));
363 actionList.add(ab.build());
365 ab.setAction(ActionUtils.popVlanAction());
367 ab.setKey(new ActionKey(1));
368 actionList.add(ab.build());
370 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
372 ab.setKey(new ActionKey(2));
373 actionList.add(ab.build());
375 /* Subsequent calls require appending any new local ports for this tenant. */
376 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
377 Instruction in = existingInstructions.get(0);
378 actionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
380 NodeConnectorId ncid = new NodeConnectorId(nodeName + ":" + localPort);
381 boolean addNew = true;
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))) {
395 ActionBuilder ab = new ActionBuilder();
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());
404 ApplyActionsBuilder aab = new ApplyActionsBuilder();
405 aab.setAction(actionList);
406 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
408 ib.setKey(new InstructionKey(0));
409 instructions.add(ib.build());
411 // Add InstructionBuilder to the Instruction(s)Builder List
412 InstructionsBuilder isb = new InstructionsBuilder();
413 isb.setInstruction(instructions);
415 // Add InstructionsBuilder to FlowBuilder
416 flowBuilder.setInstructions(isb.build());
417 writeFlow(flowBuilder, nodeBuilder);
419 //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
420 // localPort, existingInstructions);
421 boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort, ethPort,
422 existingInstructions);
424 /* if all ports are removed, remove flow */
425 removeFlow(flowBuilder, nodeBuilder);
427 /* Install instruction with new output port list*/
429 ib.setKey(new InstructionKey(0));
430 instructions.add(ib.build());
432 // Add InstructionBuilder to the Instruction(s)Builder List
433 InstructionsBuilder isb = new InstructionsBuilder();
434 isb.setInstruction(instructions);
436 // Add InstructionsBuilder to FlowBuilder
437 flowBuilder.setInstructions(isb.build());
438 writeFlow(flowBuilder, nodeBuilder);
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;
448 if (instructions != null) {
449 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
450 Instruction in = instructions.get(0);
451 List<Action> oldActionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
452 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + localPort);
453 NodeConnectorId ncidEth = new NodeConnectorId(OPENFLOW + dpidLong + ":" + ethPort);
455 // Remove the port from the output list
456 ActionBuilder ab = new ActionBuilder();
458 //for (ListIterator<Action> it = oldActionList.listIterator(oldActionList.size()); it.hasPrevious();) {
459 // Action action = it.previous();
460 for (Action action : oldActionList) {
461 if (action.getAction() instanceof OutputActionCase) {
462 OutputActionCase opAction = (OutputActionCase) action.getAction();
463 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncidEth))) {
464 actionList.add(action);
465 } else if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid)) == false) {
466 ab.setAction(action.getAction());
468 ab.setKey(new ActionKey(index));
469 actionList.add(ab.build());
473 actionList.add(action);
476 ApplyActionsBuilder aab = new ApplyActionsBuilder();
477 aab.setAction(actionList);
478 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
481 if (actionList != null && actionList.size() > 2) {
482 // Add InstructionBuilder to the Instruction(s)Builder List
483 InstructionsBuilder isb = new InstructionsBuilder();
484 isb.setInstruction(instructions);
492 * (Table:1) Local Table Miss
493 * Match: Any Remaining Flows w/a TunID
494 * Action: Drop w/ a low priority
495 * table=2,priority=8192,tun_id=0x5 actions=drop
499 public void programLocalTableMiss(Long dpidLong, String segmentationId, boolean write) {
501 String nodeName = OPENFLOW + dpidLong;
503 MatchBuilder matchBuilder = new MatchBuilder();
504 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
505 FlowBuilder flowBuilder = new FlowBuilder();
507 // Create Match(es) and Set them in the FlowBuilder Object
508 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
511 // Create the OF Actions and Instructions
512 InstructionBuilder ib = new InstructionBuilder();
513 InstructionsBuilder isb = new InstructionsBuilder();
515 // Instructions List Stores Individual Instructions
516 List<Instruction> instructions = Lists.newArrayList();
518 // Call the InstructionBuilder Methods Containing Actions
519 InstructionUtils.createDropInstructions(ib);
521 ib.setKey(new InstructionKey(0));
522 instructions.add(ib.build());
524 // Add InstructionBuilder to the Instruction(s)Builder List
525 isb.setInstruction(instructions);
527 // Add InstructionsBuilder to FlowBuilder
528 flowBuilder.setInstructions(isb.build());
531 String flowId = "LocalTableMiss_"+segmentationId;
532 // Add Flow Attributes
533 flowBuilder.setId(new FlowId(flowId));
534 FlowKey key = new FlowKey(new FlowId(flowId));
535 flowBuilder.setStrict(true);
536 flowBuilder.setBarrier(false);
537 flowBuilder.setTableId(getTable());
538 flowBuilder.setKey(key);
539 flowBuilder.setPriority(8192);
540 flowBuilder.setFlowName(flowId);
541 flowBuilder.setHardTimeout(0);
542 flowBuilder.setIdleTimeout(0);
544 writeFlow(flowBuilder, nodeBuilder);
546 removeFlow(flowBuilder, nodeBuilder);
551 * (Table:1) Local Table Miss
552 * Match: Any Remaining Flows w/a VLAN ID
553 * Action: Drop w/ a low priority
554 * table=2,priority=8192,vlan_id=0x5 actions=drop
558 public void programLocalVlanTableMiss(Long dpidLong, String segmentationId, boolean write) {
560 String nodeName = OPENFLOW + dpidLong;
562 MatchBuilder matchBuilder = new MatchBuilder();
563 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
564 FlowBuilder flowBuilder = new FlowBuilder();
566 // Create Match(es) and Set them in the FlowBuilder Object
567 flowBuilder.setMatch(
568 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
571 // Create the OF Actions and Instructions
572 InstructionBuilder ib = new InstructionBuilder();
573 InstructionsBuilder isb = new InstructionsBuilder();
575 // Instructions List Stores Individual Instructions
576 List<Instruction> instructions = Lists.newArrayList();
578 // Call the InstructionBuilder Methods Containing Actions
579 InstructionUtils.createDropInstructions(ib);
581 ib.setKey(new InstructionKey(0));
582 instructions.add(ib.build());
584 // Add InstructionBuilder to the Instruction(s)Builder List
585 isb.setInstruction(instructions);
587 // Add InstructionsBuilder to FlowBuilder
588 flowBuilder.setInstructions(isb.build());
591 String flowId = "LocalTableMiss_"+segmentationId;
592 // Add Flow Attributes
593 flowBuilder.setId(new FlowId(flowId));
594 FlowKey key = new FlowKey(new FlowId(flowId));
595 flowBuilder.setStrict(true);
596 flowBuilder.setBarrier(false);
597 flowBuilder.setTableId(getTable());
598 flowBuilder.setKey(key);
599 flowBuilder.setPriority(8192);
600 flowBuilder.setFlowName(flowId);
601 flowBuilder.setHardTimeout(0);
602 flowBuilder.setIdleTimeout(0);
604 writeFlow(flowBuilder, nodeBuilder);
606 removeFlow(flowBuilder, nodeBuilder);
612 * (Table:1) Egress Tunnel Traffic
613 * Match: Destination Ethernet Addr and Local InPort
614 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
615 * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
616 * actions=output:10,goto_table:2"
618 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
620 public void programTunnelOut(Long dpidLong, String segmentationId, Long OFPortOut, String attachedMac, boolean write) {
622 String nodeName = OPENFLOW + dpidLong;
624 MatchBuilder matchBuilder = new MatchBuilder();
625 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
626 FlowBuilder flowBuilder = new FlowBuilder();
628 // Create the OF Match using MatchBuilder
629 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
630 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
632 String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
633 // Add Flow Attributes
634 flowBuilder.setId(new FlowId(flowId));
635 FlowKey key = new FlowKey(new FlowId(flowId));
636 flowBuilder.setStrict(true);
637 flowBuilder.setBarrier(false);
638 flowBuilder.setTableId(getTable());
639 flowBuilder.setKey(key);
640 flowBuilder.setFlowName(flowId);
641 flowBuilder.setHardTimeout(0);
642 flowBuilder.setIdleTimeout(0);
645 // Instantiate the Builders for the OF Actions and Instructions
646 InstructionBuilder ib = new InstructionBuilder();
647 InstructionsBuilder isb = new InstructionsBuilder();
649 // Instructions List Stores Individual Instructions
650 List<Instruction> instructions = Lists.newArrayList();
652 // Set the Output Port/Iface
653 InstructionUtils.createOutputPortInstructions(ib, dpidLong, OFPortOut);
655 ib.setKey(new InstructionKey(1));
656 instructions.add(ib.build());
658 // Add InstructionBuilder to the Instruction(s)Builder List
659 isb.setInstruction(instructions);
661 // Add InstructionsBuilder to FlowBuilder
662 flowBuilder.setInstructions(isb.build());
664 writeFlow(flowBuilder, nodeBuilder);
666 removeFlow(flowBuilder, nodeBuilder);
671 * (Table:1) Egress VLAN Traffic
672 * Match: Destination Ethernet Addr and VLAN id
673 * Instruction: GOTO Table Table 2
674 * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
675 * actions= goto_table:2"
677 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
679 public void programVlanOut(Long dpidLong, String segmentationId, Long ethPort, String attachedMac, boolean write) {
681 String nodeName = OPENFLOW + dpidLong;
683 MatchBuilder matchBuilder = new MatchBuilder();
684 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
685 FlowBuilder flowBuilder = new FlowBuilder();
687 // Create the OF Match using MatchBuilder
688 flowBuilder.setMatch(
689 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
690 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
692 String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
693 // Add Flow Attributes
694 flowBuilder.setId(new FlowId(flowId));
695 FlowKey key = new FlowKey(new FlowId(flowId));
696 flowBuilder.setStrict(true);
697 flowBuilder.setBarrier(false);
698 flowBuilder.setTableId(getTable());
699 flowBuilder.setKey(key);
700 flowBuilder.setFlowName(flowId);
701 flowBuilder.setHardTimeout(0);
702 flowBuilder.setIdleTimeout(0);
705 // Instantiate the Builders for the OF Actions and Instructions
706 InstructionBuilder ib = new InstructionBuilder();
707 InstructionsBuilder isb = new InstructionsBuilder();
709 // Instructions List Stores Individual Instructions
710 List<Instruction> instructions = Lists.newArrayList();
711 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
713 ib.setKey(new InstructionKey(1));
714 instructions.add(ib.build());
716 // Add InstructionBuilder to the Instruction(s)Builder List
717 isb.setInstruction(instructions);
719 // Add InstructionsBuilder to FlowBuilder
720 flowBuilder.setInstructions(isb.build());
722 writeFlow(flowBuilder, nodeBuilder);
724 removeFlow(flowBuilder, nodeBuilder);
729 * (Table:1) Egress Tunnel Traffic
730 * Match: Destination Ethernet Addr and Local InPort
731 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
732 * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
733 * actions=output:10,output:11,goto_table:2
736 public void programTunnelFloodOut(Long dpidLong, String segmentationId, Long OFPortOut, boolean write) {
738 String nodeName = OPENFLOW + dpidLong;
740 MatchBuilder matchBuilder = new MatchBuilder();
741 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
742 FlowBuilder flowBuilder = new FlowBuilder();
744 // Create the OF Match using MatchBuilder
746 MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
747 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
749 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
750 new MacAddress("01:00:00:00:00:00")).build());
752 String flowId = "TunnelFloodOut_"+segmentationId;
753 // Add Flow Attributes
754 flowBuilder.setId(new FlowId(flowId));
755 FlowKey key = new FlowKey(new FlowId(flowId));
756 flowBuilder.setBarrier(true);
757 flowBuilder.setTableId(getTable());
758 flowBuilder.setKey(key);
759 flowBuilder.setPriority(16384);
760 flowBuilder.setFlowName(flowId);
761 flowBuilder.setHardTimeout(0);
762 flowBuilder.setIdleTimeout(0);
764 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
765 // Instantiate the Builders for the OF Actions and Instructions
766 InstructionBuilder ib = new InstructionBuilder();
767 InstructionsBuilder isb = new InstructionsBuilder();
768 List<Instruction> instructions = Lists.newArrayList();
769 List<Instruction> existingInstructions = null;
771 Instructions ins = flow.getInstructions();
773 existingInstructions = ins.getInstruction();
778 // Set the Output Port/Iface
779 //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
780 createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
782 ib.setKey(new InstructionKey(0));
783 instructions.add(ib.build());
785 // Add InstructionBuilder to the Instruction(s)Builder List
786 isb.setInstruction(instructions);
788 // Add InstructionsBuilder to FlowBuilder
789 flowBuilder.setInstructions(isb.build());
791 writeFlow(flowBuilder, nodeBuilder);
793 /* remove port from action list */
794 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
795 OFPortOut, existingInstructions);
797 /* if all port are removed, remove the flow too. */
798 removeFlow(flowBuilder, nodeBuilder);
800 /* Install instruction with new output port list*/
802 ib.setKey(new InstructionKey(0));
803 instructions.add(ib.build());
805 // Add InstructionBuilder to the Instruction(s)Builder List
806 isb.setInstruction(instructions);
808 // Add InstructionsBuilder to FlowBuilder
809 flowBuilder.setInstructions(isb.build());
810 writeFlow(flowBuilder, nodeBuilder);
816 * (Table:1) Egress VLAN Traffic
817 * Match: Destination Ethernet Addr and VLAN id
818 * Instruction: GOTO table 2 and Output port eth interface
819 * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
820 * actions=output:eth1,goto_table:2
824 public void programVlanFloodOut(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
826 String nodeName = OPENFLOW + dpidLong;
828 MatchBuilder matchBuilder = new MatchBuilder();
829 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
830 FlowBuilder flowBuilder = new FlowBuilder();
832 // Create the OF Match using MatchBuilder
834 flowBuilder.setMatch(
835 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
837 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
838 new MacAddress("01:00:00:00:00:00")).build());
840 String flowId = "VlanFloodOut_"+segmentationId+"_"+ethPort;
841 // Add Flow Attributes
842 flowBuilder.setId(new FlowId(flowId));
843 FlowKey key = new FlowKey(new FlowId(flowId));
844 flowBuilder.setBarrier(true);
845 flowBuilder.setTableId(getTable());
846 flowBuilder.setKey(key);
847 flowBuilder.setPriority(16384);
848 flowBuilder.setFlowName(flowId);
849 flowBuilder.setHardTimeout(0);
850 flowBuilder.setIdleTimeout(0);
852 //ToDo: Is there something to be done with result of the call to getFlow?
854 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
855 // Instantiate the Builders for the OF Actions and Instructions
856 InstructionBuilder ib = new InstructionBuilder();
857 InstructionsBuilder isb = new InstructionsBuilder();
858 List<Instruction> instructions = Lists.newArrayList();
861 // Set the Output Port/Iface
862 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
864 ib.setKey(new InstructionKey(0));
865 instructions.add(ib.build());
867 // Add InstructionBuilder to the Instruction(s)Builder List
868 isb.setInstruction(instructions);
870 // Add InstructionsBuilder to FlowBuilder
871 flowBuilder.setInstructions(isb.build());
873 writeFlow(flowBuilder, nodeBuilder);
875 removeFlow(flowBuilder, nodeBuilder);
880 * (Table:1) Table Drain w/ Catch All
882 * Action: GOTO Local Table (10)
883 * table=2,priority=8192,tun_id=0x5 actions=drop
886 public void programTunnelMiss(Long dpidLong, String segmentationId, boolean write) {
888 String nodeName = OPENFLOW + dpidLong;
890 MatchBuilder matchBuilder = new MatchBuilder();
891 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
892 FlowBuilder flowBuilder = new FlowBuilder();
894 // Create Match(es) and Set them in the FlowBuilder Object
895 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
898 // Create the OF Actions and Instructions
899 InstructionBuilder ib = new InstructionBuilder();
900 InstructionsBuilder isb = new InstructionsBuilder();
902 // Instructions List Stores Individual Instructions
903 List<Instruction> instructions = Lists.newArrayList();
905 // Call the InstructionBuilder Methods Containing Actions
906 ib = this.getMutablePipelineInstructionBuilder();
908 ib.setKey(new InstructionKey(0));
909 instructions.add(ib.build());
911 // Add InstructionBuilder to the Instruction(s)Builder List
912 isb.setInstruction(instructions);
914 // Add InstructionsBuilder to FlowBuilder
915 flowBuilder.setInstructions(isb.build());
918 String flowId = "TunnelMiss_"+segmentationId;
919 // Add Flow Attributes
920 flowBuilder.setId(new FlowId(flowId));
921 FlowKey key = new FlowKey(new FlowId(flowId));
922 flowBuilder.setStrict(true);
923 flowBuilder.setBarrier(false);
924 flowBuilder.setTableId(getTable());
925 flowBuilder.setKey(key);
926 flowBuilder.setPriority(8192);
927 flowBuilder.setFlowName(flowId);
928 flowBuilder.setHardTimeout(0);
929 flowBuilder.setIdleTimeout(0);
931 writeFlow(flowBuilder, nodeBuilder);
933 removeFlow(flowBuilder, nodeBuilder);
938 * (Table:1) Table Drain w/ Catch All
940 * Action: Output port eth interface
941 * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
942 * table=110,priority=8192,dl_vlan=2001 actions=output:2
946 public void programVlanMiss(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
948 String nodeName = OPENFLOW + dpidLong;
950 MatchBuilder matchBuilder = new MatchBuilder();
951 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
952 FlowBuilder flowBuilder = new FlowBuilder();
954 // Create Match(es) and Set them in the FlowBuilder Object
955 flowBuilder.setMatch(
956 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
959 // Create the OF Actions and Instructions
960 InstructionBuilder ib = new InstructionBuilder();
961 InstructionsBuilder isb = new InstructionsBuilder();
963 // Instructions List Stores Individual Instructions
964 List<Instruction> instructions = Lists.newArrayList();
966 // Set the Output Port/Iface
967 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
969 ib.setKey(new InstructionKey(1));
970 instructions.add(ib.build());
972 // Add InstructionBuilder to the Instruction(s)Builder List
973 isb.setInstruction(instructions);
975 // Add InstructionsBuilder to FlowBuilder
976 flowBuilder.setInstructions(isb.build());
979 String flowId = "VlanMiss_"+segmentationId;
980 // Add Flow Attributes
981 flowBuilder.setId(new FlowId(flowId));
982 FlowKey key = new FlowKey(new FlowId(flowId));
983 flowBuilder.setStrict(true);
984 flowBuilder.setBarrier(false);
985 flowBuilder.setTableId(getTable());
986 flowBuilder.setKey(key);
987 flowBuilder.setPriority(8192);
988 flowBuilder.setFlowName(flowId);
989 flowBuilder.setHardTimeout(0);
990 flowBuilder.setIdleTimeout(0);
992 writeFlow(flowBuilder, nodeBuilder);
994 removeFlow(flowBuilder, nodeBuilder);
999 * Create Output Port Group Instruction
1001 * @param ib Map InstructionBuilder without any instructions
1002 * @param dpidLong Long the datapath ID of a switch/node
1003 * @param port Long representing a port on a switch/node
1004 * @return ib InstructionBuilder Map with instructions
1006 protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
1007 Long dpidLong, Long port ,
1008 List<Instruction> instructions) {
1009 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
1010 logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1012 List<Action> actionList = Lists.newArrayList();
1013 ActionBuilder ab = new ActionBuilder();
1015 List<Action> existingActions;
1016 if (instructions != null && instructions.size() > 0) {
1018 * First instruction is the one containing the output ports.
1019 * So, only extract the actions from that.
1021 Instruction in = instructions.get(0);
1022 if (in.getInstruction() instanceof ApplyActionsCase) {
1023 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1024 // Only include output actions
1025 for (Action action : existingActions)
1026 if (action.getAction() instanceof OutputActionCase)
1027 actionList.add(action);
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;
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))) {
1046 ab.setOrder(actionList.size());
1047 ab.setKey(new ActionKey(actionList.size()));
1048 actionList.add(ab.build());
1050 // Create an Apply Action
1051 ApplyActionsBuilder aab = new ApplyActionsBuilder();
1052 aab.setAction(actionList);
1053 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1054 logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());