2 * Copyright (c) 2014, 2015 Red Hat, Inc. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.services;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
16 import org.opendaylight.netvirt.openstack.netvirt.api.L2ForwardingProvider;
17 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
18 import org.opendaylight.netvirt.openstack.netvirt.providers.openflow13.Service;
19 import org.opendaylight.netvirt.openstack.netvirt.providers.ConfigInterface;
20 import org.opendaylight.netvirt.utils.mdsal.openflow.ActionUtils;
21 import org.opendaylight.netvirt.utils.mdsal.openflow.FlowUtils;
22 import org.opendaylight.netvirt.utils.mdsal.openflow.InstructionUtils;
23 import org.opendaylight.netvirt.utils.mdsal.openflow.MatchUtils;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
48 import org.osgi.framework.BundleContext;
49 import org.osgi.framework.ServiceReference;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
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);
59 public L2ForwardingService(Service service) {
64 * (Table:L2Forwarding) Local Unicast
65 * Match: Tunnel ID and dMAC
67 * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 goto:<next-table>
70 public void programLocalUcastOut(Long dpidLong, String segmentationId,
71 Long localPort, String attachedMac, boolean write) {
73 String nodeName = OPENFLOW + dpidLong;
75 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
76 FlowBuilder flowBuilder = new FlowBuilder();
78 // Create the OF Match using MatchBuilder
79 MatchBuilder matchBuilder = new MatchBuilder();
80 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
81 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
82 flowBuilder.setMatch(matchBuilder.build());
84 // Add Flow Attributes
85 String flowName = "UcastOut_" + segmentationId + "_" + attachedMac;
86 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
89 // Set the Output Port/Iface
90 Instruction setOutputPortInstruction =
91 InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, localPort)
93 .setKey(new InstructionKey(0))
96 // Add InstructionsBuilder to FlowBuilder
97 InstructionUtils.setFlowBuilderInstruction(flowBuilder, setOutputPortInstruction);
98 writeFlow(flowBuilder, nodeBuilder);
100 removeFlow(flowBuilder, nodeBuilder);
105 * (Table:2) Local VLAN unicast
106 * Match: VLAN ID and dMAC
107 * Action: Output Port
108 * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
109 * table=110,dl_vlan=2001,dl_dst=fa:16:3e:a3:3b:cc actions=pop_vlan,output:1
113 public void programLocalVlanUcastOut (Long dpidLong, String segmentationId, Long localPort, String attachedMac, boolean write) {
115 String nodeName = OPENFLOW + dpidLong;
117 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
118 FlowBuilder flowBuilder = new FlowBuilder();
120 // Create the OF Match using MatchBuilder
121 MatchBuilder matchBuilder = new MatchBuilder();
122 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
123 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
124 flowBuilder.setMatch(matchBuilder.build());
126 // Add Flow Attributes
127 String flowName = "VlanUcastOut_" + segmentationId + "_" + localPort + "_" + attachedMac;
128 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
131 /* Strip vlan and store to tmp instruction space*/
132 Instruction stripVlanInstruction = InstructionUtils.createPopVlanInstructions(new InstructionBuilder())
134 .setKey(new InstructionKey(0))
137 // Set the Output Port/Iface
138 Instruction setOutputPortInstruction =
139 InstructionUtils.addOutputPortInstructions(new InstructionBuilder(), dpidLong, localPort,
140 Collections.singletonList(stripVlanInstruction))
142 .setKey(new InstructionKey(0))
145 // Add InstructionsBuilder to FlowBuilder
146 InstructionUtils.setFlowBuilderInstruction(flowBuilder, setOutputPortInstruction);
147 writeFlow(flowBuilder, nodeBuilder);
149 removeFlow(flowBuilder, nodeBuilder);
155 * (Table:2) Local Broadcast Flood
156 * Match: Tunnel ID and dMAC (::::FF:FF)
157 * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
158 * actions=output:2,3,4,5
162 public void programLocalBcastOut(Long dpidLong, String segmentationId, Long localPort, boolean write) {
164 String nodeName = OPENFLOW + dpidLong;
166 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
167 FlowBuilder flowBuilder = new FlowBuilder();
169 // Create the OF Match using MatchBuilder
170 MatchBuilder matchBuilder = new MatchBuilder();
171 MatchUtils.addNxRegMatch(matchBuilder,
172 new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
173 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
174 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
175 new MacAddress("01:00:00:00:00:00"));
176 flowBuilder.setMatch(matchBuilder.build());
178 // Add Flow Attributes
179 String flowName = "BcastOut_" + segmentationId;
180 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
183 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
185 // Retrieve the existing instructions
186 List<Instruction> existingInstructions = InstructionUtils.extractExistingInstructions(flow);
189 // Create output port list
190 Instruction outputPortInstruction =
191 createOutputPortInstructions(new InstructionBuilder(), dpidLong, localPort, existingInstructions)
193 .setKey(new InstructionKey(0))
196 /* Alternative method to address Bug 2004 is to use appendResubmitLocalFlood(ib) so that we send the
197 * flow back to the local flood rule. (See git history.) */
199 // Add InstructionsBuilder to FlowBuilder
200 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
202 writeFlow(flowBuilder, nodeBuilder);
204 InstructionBuilder ib = new InstructionBuilder();
205 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong, localPort,
206 existingInstructions);
208 /* if all ports are removed, remove flow */
209 removeFlow(flowBuilder, nodeBuilder);
211 /* Install instruction with new output port list*/
212 Instruction outputPortInstruction = ib
214 .setKey(new InstructionKey(0))
217 // Add InstructionsBuilder to FlowBuilder
218 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
220 writeFlow(flowBuilder, nodeBuilder);
226 * (Table:2) Local VLAN Broadcast Flood
227 * Match: vlan ID and dMAC (::::FF:FF)
228 * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
229 * actions=strip_vlan, output:2,3,4,5
230 * 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
234 public void programLocalVlanBcastOut(Long dpidLong, String segmentationId,
235 Long localPort, Long ethPort, boolean write) {
237 String nodeName = OPENFLOW + dpidLong;
239 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
240 FlowBuilder flowBuilder = new FlowBuilder();
242 // Create the OF Match using MatchBuilder
243 MatchBuilder matchBuilder = new MatchBuilder();
244 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
245 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
246 new MacAddress("01:00:00:00:00:00"));
247 flowBuilder.setMatch(matchBuilder.build());
249 // Add Flow Attributes
250 String flowName = "VlanBcastOut_" + segmentationId + "_" + ethPort;
251 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
253 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
255 // Retrieve the existing instructions
256 List<Instruction> existingInstructions = InstructionUtils.extractExistingInstructions(flow);
259 List<Action> actionList;
260 if (existingInstructions == null || existingInstructions.isEmpty()) {
261 /* First time called there should be no instructions.
262 * We can simply add the output:ethPort first, followed by
263 * popVlan and then the local port. The next calls will append
264 * the rest of the local ports.
266 actionList = new ArrayList<>();
270 .setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)))
272 .setKey(new ActionKey(0))
277 .setAction(ActionUtils.popVlanAction())
279 .setKey(new ActionKey(1))
284 .setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)))
286 .setKey(new ActionKey(2))
289 /* Subsequent calls require appending any new local ports for this tenant. */
290 Instruction in = existingInstructions.get(0);
291 actionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
293 NodeConnectorId ncid = new NodeConnectorId(nodeName + ":" + localPort);
294 final Uri nodeConnectorUri = new Uri(ncid);
295 boolean addNew = true;
297 /* Check if the port is already in the output list */
298 for (Action action : actionList) {
299 if (action.getAction() instanceof OutputActionCase) {
300 OutputActionCase opAction = (OutputActionCase) action.getAction();
301 if (opAction.getOutputAction().getOutputNodeConnector().equals(nodeConnectorUri)) {
312 ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)))
313 .setOrder(actionList.size())
314 .setKey(new ActionKey(actionList.size()))
319 ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build();
320 Instruction applyActionsInstruction =
321 new InstructionBuilder()
322 .setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions).build())
324 .setKey(new InstructionKey(0))
327 // Add InstructionsBuilder to FlowBuilder
328 InstructionUtils.setFlowBuilderInstruction(flowBuilder, applyActionsInstruction);
329 writeFlow(flowBuilder, nodeBuilder);
331 InstructionBuilder ib = new InstructionBuilder();
332 boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort, ethPort,
333 existingInstructions);
335 /* if all ports are removed, remove flow */
336 removeFlow(flowBuilder, nodeBuilder);
338 /* Install instruction with new output port list*/
339 Instruction outputPortInstruction = ib
341 .setKey(new InstructionKey(0))
344 // Add InstructionsBuilder to FlowBuilder
345 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
346 writeFlow(flowBuilder, nodeBuilder);
351 private boolean removeOutputPortFromInstructions(InstructionBuilder ib, Long dpidLong, Long localPort,
352 Long ethPort, List<Instruction> instructions) {
353 List<Action> actionList = new ArrayList<>();
354 boolean removeFlow = true;
356 if (instructions != null && !instructions.isEmpty()) {
357 Instruction in = instructions.get(0);
358 List<Action> oldActionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
359 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + localPort);
360 final Uri localNodeConnectorUri = new Uri(ncid);
361 NodeConnectorId ncidEth = new NodeConnectorId(OPENFLOW + dpidLong + ":" + ethPort);
362 final Uri ethNodeConnectorUri = new Uri(ncidEth);
364 // Remove the port from the output list
366 for (Action action : oldActionList) {
367 if (action.getAction() instanceof OutputActionCase) {
368 OutputActionCase opAction = (OutputActionCase) action.getAction();
369 if (opAction.getOutputAction().getOutputNodeConnector().equals(ethNodeConnectorUri)) {
370 actionList.add(action);
371 } else if (!opAction.getOutputAction().getOutputNodeConnector().equals(localNodeConnectorUri)) {
374 .setAction(action.getAction())
376 .setKey(new ActionKey(index))
381 actionList.add(action);
384 ApplyActions applyActions = new ApplyActionsBuilder().setAction(actionList).build();
385 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(applyActions).build());
388 if (actionList.size() > 2) {
389 // Add InstructionBuilder to the Instruction(s)Builder List
390 // TODO This doesn't actually do anything
391 InstructionsBuilder isb = new InstructionsBuilder();
392 isb.setInstruction(instructions);
400 * (Table:1) Local Table Miss
401 * Match: Any Remaining Flows w/a VLAN ID
402 * Action: Drop w/ a low priority
403 * table=2,priority=8192,vlan_id=0x5 actions=drop
407 public void programLocalVlanTableMiss(Long dpidLong, String segmentationId, boolean write) {
409 String nodeName = OPENFLOW + dpidLong;
411 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
412 FlowBuilder flowBuilder = new FlowBuilder();
414 // Create Match(es) and Set them in the FlowBuilder Object
415 flowBuilder.setMatch(
416 MatchUtils.createVlanIdMatch(new MatchBuilder(), new VlanId(Integer.valueOf(segmentationId)),
420 // Call the InstructionBuilder Methods Containing Actions
421 Instruction dropInstruction = InstructionUtils.createDropInstructions(new InstructionBuilder())
423 .setKey(new InstructionKey(0))
426 // Add InstructionsBuilder to FlowBuilder
427 InstructionUtils.setFlowBuilderInstruction(flowBuilder, dropInstruction);
430 // Add Flow Attributes
431 String flowName = "LocalTableMiss_" + segmentationId;
432 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
435 writeFlow(flowBuilder, nodeBuilder);
437 removeFlow(flowBuilder, nodeBuilder);
443 * (Table:1) Egress Tunnel Traffic
444 * Match: Destination Ethernet Addr and Local InPort
445 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
446 * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
447 * actions=output:10,goto_table:2"
449 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
451 public void programTunnelOut(Long dpidLong, String segmentationId, Long OFPortOut, String attachedMac, boolean write) {
453 String nodeName = OPENFLOW + dpidLong;
455 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
456 FlowBuilder flowBuilder = new FlowBuilder();
458 // Create the OF Match using MatchBuilder
459 MatchBuilder matchBuilder = new MatchBuilder();
460 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
461 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
462 flowBuilder.setMatch(matchBuilder.build());
464 // Add Flow Attributes
465 String flowName = "UcastOut_" + segmentationId + "_" + attachedMac;
466 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
469 // Set the Output Port/Iface
470 Instruction outputPortInstruction =
471 InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, OFPortOut)
473 .setKey(new InstructionKey(1))
476 // Add InstructionsBuilder to FlowBuilder
477 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
479 writeFlow(flowBuilder, nodeBuilder);
481 removeFlow(flowBuilder, nodeBuilder);
486 * (Table:1) Egress VLAN Traffic
487 * Match: Destination Ethernet Addr and VLAN id
488 * Instruction: GOTO Table Table 2
489 * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
490 * actions= goto_table:2"
492 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
494 public void programVlanOut(Long dpidLong, String segmentationId, Long ethPort, String attachedMac, boolean write) {
496 String nodeName = OPENFLOW + dpidLong;
498 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
499 FlowBuilder flowBuilder = new FlowBuilder();
501 // Create the OF Match using MatchBuilder
502 MatchBuilder matchBuilder = new MatchBuilder();
503 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true);
504 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null);
505 flowBuilder.setMatch(matchBuilder.build());
507 // Add Flow Attributes
508 String flowName = "VlanOut_" + segmentationId + "_" + ethPort + "_" + attachedMac;
509 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable());
512 // Instructions List Stores Individual Instructions
513 Instruction outputPortInstruction =
514 InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, ethPort)
516 .setKey(new InstructionKey(1))
519 // Add InstructionsBuilder to FlowBuilder
520 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
522 writeFlow(flowBuilder, nodeBuilder);
524 removeFlow(flowBuilder, nodeBuilder);
529 * (Table:1) Egress Tunnel Traffic
530 * Match: Destination Ethernet Addr and Local InPort
531 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
532 * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
533 * actions=output:10,output:11,goto_table:2
536 public void programTunnelFloodOut(Long dpidLong, String segmentationId, Long OFPortOut, boolean write) {
538 String nodeName = OPENFLOW + dpidLong;
540 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
541 FlowBuilder flowBuilder = new FlowBuilder();
543 // Create the OF Match using MatchBuilder
544 MatchBuilder matchBuilder = new MatchBuilder();
546 MatchUtils.addNxRegMatch(matchBuilder,
547 new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
548 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
550 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
551 new MacAddress("01:00:00:00:00:00"));
552 flowBuilder.setMatch(matchBuilder.build());
554 // Add Flow Attributes
555 String flowName = "TunnelFloodOut_" + segmentationId;
556 final FlowId flowId = new FlowId(flowName);
560 .setTableId(getTable())
561 .setKey(new FlowKey(flowId))
562 .setPriority(16383) // FIXME: change it back to 16384 once bug 3005 is fixed.
563 .setFlowName(flowName)
567 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
568 // Instantiate the Builders for the OF Actions and Instructions
569 List<Instruction> existingInstructions = InstructionUtils.extractExistingInstructions(flow);
572 // Set the Output Port/Iface
573 Instruction outputPortInstruction =
574 createOutputPortInstructions(new InstructionBuilder(), dpidLong, OFPortOut, existingInstructions)
576 .setKey(new InstructionKey(0))
579 // Add InstructionsBuilder to FlowBuilder
580 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
582 writeFlow(flowBuilder, nodeBuilder);
584 InstructionBuilder ib = new InstructionBuilder();
585 /* remove port from action list */
586 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
587 OFPortOut, existingInstructions);
589 /* if all port are removed, remove the flow too. */
590 removeFlow(flowBuilder, nodeBuilder);
592 /* Install instruction with new output port list*/
593 Instruction instruction = ib
595 .setKey(new InstructionKey(0))
598 // Add InstructionsBuilder to FlowBuilder
599 InstructionUtils.setFlowBuilderInstruction(flowBuilder, instruction);
600 writeFlow(flowBuilder, nodeBuilder);
606 * (Table:110) Flooding local unknown unicast Traffic
607 * Match: TunnelID and Unknown unicast and Local InPort
608 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
609 * table=110,priority=16380,tun_id=0x5,dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 \
610 * actions=output:10,output:11
613 public void programTunnelUnknownUcastFloodOut(Long dpidLong, String segmentationId, Long OFPortOut, boolean write) {
615 String nodeName = OPENFLOW + dpidLong;
617 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
618 FlowBuilder flowBuilder = new FlowBuilder();
620 // Create the OF Match using MatchBuilder
621 MatchBuilder matchBuilder = new MatchBuilder();
623 MatchUtils.addNxRegMatch(matchBuilder,
624 new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
625 MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId));
627 MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("00:00:00:00:00:00"),
628 new MacAddress("01:00:00:00:00:00"));
629 flowBuilder.setMatch(matchBuilder.build());
631 // Add Flow Attributes
632 String flowName = "TunnelUnknownUcastFloodOut_" + segmentationId;
633 final FlowId flowId = new FlowId(flowName);
637 .setTableId(getTable())
638 .setKey(new FlowKey(flowId))
640 .setFlowName(flowName)
644 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
645 // Instantiate the Builders for the OF Actions and Instructions
646 List<Instruction> existingInstructions = InstructionUtils.extractExistingInstructions(flow);
649 // Set the Output Port/Iface
650 Instruction outputPortInstruction =
651 createOutputPortInstructions(new InstructionBuilder(), dpidLong, OFPortOut, existingInstructions)
653 .setKey(new InstructionKey(0))
656 // Add InstructionsBuilder to FlowBuilder
657 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
659 writeFlow(flowBuilder, nodeBuilder);
661 InstructionBuilder ib = new InstructionBuilder();
662 /* remove port from action list */
663 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
664 OFPortOut, existingInstructions);
666 /* if all port are removed, remove the flow too. */
667 removeFlow(flowBuilder, nodeBuilder);
669 /* Install instruction with new output port list*/
670 Instruction instruction = ib
672 .setKey(new InstructionKey(0))
675 // Add InstructionsBuilder to FlowBuilder
676 InstructionUtils.setFlowBuilderInstruction(flowBuilder, instruction);
677 writeFlow(flowBuilder, nodeBuilder);
683 * (Table:1) Table Drain w/ Catch All
685 * Action: Output port eth interface
686 * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
687 * table=110,priority=8192,dl_vlan=2001 actions=output:2
691 public void programVlanMiss(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
693 String nodeName = OPENFLOW + dpidLong;
695 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
696 FlowBuilder flowBuilder = new FlowBuilder();
698 // Create Match(es) and Set them in the FlowBuilder Object
699 flowBuilder.setMatch(
700 MatchUtils.createVlanIdMatch(new MatchBuilder(), new VlanId(Integer.valueOf(segmentationId)),
704 // Set the Output Port/Iface
705 Instruction outputPortInstruction =
706 InstructionUtils.createOutputPortInstructions(new InstructionBuilder(), dpidLong, ethPort)
708 .setKey(new InstructionKey(1))
711 // Add InstructionsBuilder to FlowBuilder
712 InstructionUtils.setFlowBuilderInstruction(flowBuilder, outputPortInstruction);
715 // Add Flow Attributes
716 String flowName = "VlanMiss_" + segmentationId;
717 FlowUtils.initFlowBuilder(flowBuilder, flowName, getTable())
720 writeFlow(flowBuilder, nodeBuilder);
722 removeFlow(flowBuilder, nodeBuilder);
727 * Create Output Port Group Instruction
729 * @param ib Map InstructionBuilder without any instructions
730 * @param dpidLong Long the datapath ID of a switch/node
731 * @param port Long representing a port on a switch/node
732 * @param instructions List of instructions
733 * @return ib InstructionBuilder Map with instructions
735 protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
736 Long dpidLong, Long port ,
737 List<Instruction> instructions) {
738 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
739 LOG.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
741 List<Action> actionList = new ArrayList<>();
742 ActionBuilder ab = new ActionBuilder();
744 List<Action> existingActions;
745 if (instructions != null && instructions.size() > 0) {
747 * First instruction is the one containing the output ports.
748 * So, only extract the actions from that.
750 Instruction in = instructions.get(0);
751 if (in.getInstruction() instanceof ApplyActionsCase) {
752 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
753 // Only include output actions
754 for (Action action : existingActions) {
755 if (action.getAction() instanceof OutputActionCase) {
756 actionList.add(action);
761 /* Create output action for this port*/
762 OutputActionBuilder oab = new OutputActionBuilder();
763 oab.setOutputNodeConnector(ncid);
764 ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
765 boolean addNew = true;
767 /* Find the group action and get the group */
768 for (Action action : actionList) {
769 OutputActionCase opAction = (OutputActionCase)action.getAction();
770 /* If output port action already in the action list of one of the buckets, skip */
771 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
777 ab.setOrder(actionList.size());
778 ab.setKey(new ActionKey(actionList.size()));
779 actionList.add(ab.build());
781 // Create an Apply Action
782 ApplyActionsBuilder aab = new ApplyActionsBuilder();
783 aab.setAction(actionList);
784 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
785 LOG.debug("createOutputPortInstructions() : applyAction {}", aab.build());
790 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
791 super.setDependencies(bundleContext.getServiceReference(L2ForwardingProvider.class.getName()), this);
795 public void setDependencies(Object impl) {