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.ovsdb.openstack.netvirt.providers.openflow13.services;
11 import java.math.BigInteger;
12 import java.util.List;
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;
51 import com.google.common.collect.Lists;
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 MatchBuilder matchBuilder = new MatchBuilder();
76 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
77 FlowBuilder flowBuilder = new FlowBuilder();
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());
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);
96 // Instantiate the Builders for the OF Actions and Instructions
97 InstructionBuilder ib = new InstructionBuilder();
98 InstructionsBuilder isb = new InstructionsBuilder();
100 // Instructions List Stores Individual Instructions
101 List<Instruction> instructions = Lists.newArrayList();
103 // Set the Output Port/Iface
104 InstructionUtils.createOutputPortInstructions(ib, dpidLong, localPort);
106 ib.setKey(new InstructionKey(0));
107 instructions.add(ib.build());
109 // Add InstructionBuilder to the Instruction(s)Builder List
110 isb.setInstruction(instructions);
112 // Add InstructionsBuilder to FlowBuilder
113 flowBuilder.setInstructions(isb.build());
114 writeFlow(flowBuilder, nodeBuilder);
116 removeFlow(flowBuilder, nodeBuilder);
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
128 public void programLocalVlanUcastOut (Long dpidLong, String segmentationId, Long localPort, String attachedMac, boolean write) {
130 String nodeName = OPENFLOW + dpidLong;
132 MatchBuilder matchBuilder = new MatchBuilder();
133 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
134 FlowBuilder flowBuilder = new FlowBuilder();
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());
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);
154 // Instantiate the Builders for the OF Actions and Instructions
155 InstructionBuilder ib = new InstructionBuilder();
156 InstructionsBuilder isb = new InstructionsBuilder();
158 // Instructions List Stores Individual Instructions
159 List<Instruction> instructions = Lists.newArrayList();
160 List<Instruction> instructions_tmp = Lists.newArrayList();
162 /* Strip vlan and store to tmp instruction space*/
163 InstructionUtils.createPopVlanInstructions(ib);
165 ib.setKey(new InstructionKey(0));
166 instructions_tmp.add(ib.build());
168 // Set the Output Port/Iface
169 ib = new InstructionBuilder();
170 InstructionUtils.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
172 ib.setKey(new InstructionKey(0));
173 instructions.add(ib.build());
175 // Add InstructionBuilder to the Instruction(s)Builder List
176 isb.setInstruction(instructions);
178 // Add InstructionsBuilder to FlowBuilder
179 flowBuilder.setInstructions(isb.build());
180 writeFlow(flowBuilder, nodeBuilder);
182 removeFlow(flowBuilder, nodeBuilder);
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.
192 private void appendResubmitLocalFlood(InstructionBuilder ib) {
194 //Update the ApplyActions instructions
195 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
196 List<Action> actionList = aac.getApplyActions().getAction();
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)));
203 ab.setKey(new ActionKey(index));
204 actionList.add(ab.build());
207 ab = new ActionBuilder();
208 ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
210 ab.setKey(new ActionKey(index));
211 actionList.add(ab.build());
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
222 public void programLocalBcastOut(Long dpidLong, String segmentationId, Long localPort, boolean write) {
224 String nodeName = OPENFLOW + dpidLong;
226 MatchBuilder matchBuilder = new MatchBuilder();
227 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
228 FlowBuilder flowBuilder = new FlowBuilder();
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());
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;
255 Instructions ins = flow.getInstructions();
257 existingInstructions = ins.getInstruction();
262 // Create output port list
263 createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
265 ib.setKey(new InstructionKey(0));
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.
271 instructions.add(ib.build());
273 // Add InstructionBuilder to the Instruction(s)Builder List
274 isb.setInstruction(instructions);
276 // Add InstructionsBuilder to FlowBuilder
277 flowBuilder.setInstructions(isb.build());
279 writeFlow(flowBuilder, nodeBuilder);
281 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong, localPort,
282 existingInstructions);
284 /* if all ports are removed, remove flow */
285 removeFlow(flowBuilder, nodeBuilder);
287 /* Install instruction with new output port list*/
289 ib.setKey(new InstructionKey(0));
290 instructions.add(ib.build());
292 // Add InstructionBuilder to the Instruction(s)Builder List
293 isb.setInstruction(instructions);
295 // Add InstructionsBuilder to FlowBuilder
296 flowBuilder.setInstructions(isb.build());
297 writeFlow(flowBuilder, nodeBuilder);
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
311 public void programLocalVlanBcastOut(Long dpidLong, String segmentationId,
312 Long localPort, Long ethPort, boolean write) {
314 String nodeName = OPENFLOW + dpidLong;
316 MatchBuilder matchBuilder = new MatchBuilder();
317 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
318 FlowBuilder flowBuilder = new FlowBuilder();
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());
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;
342 Instructions ins = flow.getInstructions();
344 existingInstructions = ins.getInstruction();
348 List<Instruction> instructions = Lists.newArrayList();
349 InstructionBuilder ib = new InstructionBuilder();
350 List<Action> actionList;
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.
358 ActionBuilder ab = new ActionBuilder();
359 actionList = Lists.newArrayList();
361 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)));
363 ab.setKey(new ActionKey(0));
364 actionList.add(ab.build());
366 ab.setAction(ActionUtils.popVlanAction());
368 ab.setKey(new ActionKey(1));
369 actionList.add(ab.build());
371 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
373 ab.setKey(new ActionKey(2));
374 actionList.add(ab.build());
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());
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 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);
454 // Remove the port from the output list
455 ActionBuilder ab = new ActionBuilder();
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());
467 ab.setKey(new ActionKey(index));
468 actionList.add(ab.build());
472 actionList.add(action);
475 ApplyActionsBuilder aab = new ApplyActionsBuilder();
476 aab.setAction(actionList);
477 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
480 if (actionList.size() > 2) {
481 // Add InstructionBuilder to the Instruction(s)Builder List
482 InstructionsBuilder isb = new InstructionsBuilder();
483 isb.setInstruction(instructions);
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
498 public void programLocalTableMiss(Long dpidLong, String segmentationId, boolean write) {
500 String nodeName = OPENFLOW + dpidLong;
502 MatchBuilder matchBuilder = new MatchBuilder();
503 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
504 FlowBuilder flowBuilder = new FlowBuilder();
506 // Create Match(es) and Set them in the FlowBuilder Object
507 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
510 // Create the OF Actions and Instructions
511 InstructionBuilder ib = new InstructionBuilder();
512 InstructionsBuilder isb = new InstructionsBuilder();
514 // Instructions List Stores Individual Instructions
515 List<Instruction> instructions = Lists.newArrayList();
517 // Call the InstructionBuilder Methods Containing Actions
518 InstructionUtils.createDropInstructions(ib);
520 ib.setKey(new InstructionKey(0));
521 instructions.add(ib.build());
523 // Add InstructionBuilder to the Instruction(s)Builder List
524 isb.setInstruction(instructions);
526 // Add InstructionsBuilder to FlowBuilder
527 flowBuilder.setInstructions(isb.build());
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);
543 writeFlow(flowBuilder, nodeBuilder);
545 removeFlow(flowBuilder, nodeBuilder);
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
557 public void programLocalVlanTableMiss(Long dpidLong, String segmentationId, boolean write) {
559 String nodeName = OPENFLOW + dpidLong;
561 MatchBuilder matchBuilder = new MatchBuilder();
562 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
563 FlowBuilder flowBuilder = new FlowBuilder();
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());
570 // Create the OF Actions and Instructions
571 InstructionBuilder ib = new InstructionBuilder();
572 InstructionsBuilder isb = new InstructionsBuilder();
574 // Instructions List Stores Individual Instructions
575 List<Instruction> instructions = Lists.newArrayList();
577 // Call the InstructionBuilder Methods Containing Actions
578 InstructionUtils.createDropInstructions(ib);
580 ib.setKey(new InstructionKey(0));
581 instructions.add(ib.build());
583 // Add InstructionBuilder to the Instruction(s)Builder List
584 isb.setInstruction(instructions);
586 // Add InstructionsBuilder to FlowBuilder
587 flowBuilder.setInstructions(isb.build());
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);
603 writeFlow(flowBuilder, nodeBuilder);
605 removeFlow(flowBuilder, nodeBuilder);
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"
617 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
619 public void programTunnelOut(Long dpidLong, String segmentationId, Long OFPortOut, String attachedMac, boolean write) {
621 String nodeName = OPENFLOW + dpidLong;
623 MatchBuilder matchBuilder = new MatchBuilder();
624 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
625 FlowBuilder flowBuilder = new FlowBuilder();
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());
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);
644 // Instantiate the Builders for the OF Actions and Instructions
645 InstructionBuilder ib = new InstructionBuilder();
646 InstructionsBuilder isb = new InstructionsBuilder();
648 // Instructions List Stores Individual Instructions
649 List<Instruction> instructions = Lists.newArrayList();
651 // Set the Output Port/Iface
652 InstructionUtils.createOutputPortInstructions(ib, dpidLong, OFPortOut);
654 ib.setKey(new InstructionKey(1));
655 instructions.add(ib.build());
657 // Add InstructionBuilder to the Instruction(s)Builder List
658 isb.setInstruction(instructions);
660 // Add InstructionsBuilder to FlowBuilder
661 flowBuilder.setInstructions(isb.build());
663 writeFlow(flowBuilder, nodeBuilder);
665 removeFlow(flowBuilder, nodeBuilder);
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"
676 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
678 public void programVlanOut(Long dpidLong, String segmentationId, Long ethPort, String attachedMac, boolean write) {
680 String nodeName = OPENFLOW + dpidLong;
682 MatchBuilder matchBuilder = new MatchBuilder();
683 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
684 FlowBuilder flowBuilder = new FlowBuilder();
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());
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);
704 // Instantiate the Builders for the OF Actions and Instructions
705 InstructionBuilder ib = new InstructionBuilder();
706 InstructionsBuilder isb = new InstructionsBuilder();
708 // Instructions List Stores Individual Instructions
709 List<Instruction> instructions = Lists.newArrayList();
710 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
712 ib.setKey(new InstructionKey(1));
713 instructions.add(ib.build());
715 // Add InstructionBuilder to the Instruction(s)Builder List
716 isb.setInstruction(instructions);
718 // Add InstructionsBuilder to FlowBuilder
719 flowBuilder.setInstructions(isb.build());
721 writeFlow(flowBuilder, nodeBuilder);
723 removeFlow(flowBuilder, nodeBuilder);
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
735 public void programTunnelFloodOut(Long dpidLong, String segmentationId, Long OFPortOut, boolean write) {
737 String nodeName = OPENFLOW + dpidLong;
739 MatchBuilder matchBuilder = new MatchBuilder();
740 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
741 FlowBuilder flowBuilder = new FlowBuilder();
743 // Create the OF Match using MatchBuilder
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());
748 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
749 new MacAddress("01:00:00:00:00:00")).build());
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);
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;
770 Instructions ins = flow.getInstructions();
772 existingInstructions = ins.getInstruction();
777 // Set the Output Port/Iface
778 //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
779 createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
781 ib.setKey(new InstructionKey(0));
782 instructions.add(ib.build());
784 // Add InstructionBuilder to the Instruction(s)Builder List
785 isb.setInstruction(instructions);
787 // Add InstructionsBuilder to FlowBuilder
788 flowBuilder.setInstructions(isb.build());
790 writeFlow(flowBuilder, nodeBuilder);
792 /* remove port from action list */
793 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
794 OFPortOut, existingInstructions);
796 /* if all port are removed, remove the flow too. */
797 removeFlow(flowBuilder, nodeBuilder);
799 /* Install instruction with new output port list*/
801 ib.setKey(new InstructionKey(0));
802 instructions.add(ib.build());
804 // Add InstructionBuilder to the Instruction(s)Builder List
805 isb.setInstruction(instructions);
807 // Add InstructionsBuilder to FlowBuilder
808 flowBuilder.setInstructions(isb.build());
809 writeFlow(flowBuilder, nodeBuilder);
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
823 public void programVlanFloodOut(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
825 String nodeName = OPENFLOW + dpidLong;
827 MatchBuilder matchBuilder = new MatchBuilder();
828 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
829 FlowBuilder flowBuilder = new FlowBuilder();
831 // Create the OF Match using MatchBuilder
833 flowBuilder.setMatch(
834 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
836 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
837 new MacAddress("01:00:00:00:00:00")).build());
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);
851 //ToDo: Is there something to be done with result of the call to getFlow?
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();
860 // Set the Output Port/Iface
861 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
863 ib.setKey(new InstructionKey(0));
864 instructions.add(ib.build());
866 // Add InstructionBuilder to the Instruction(s)Builder List
867 isb.setInstruction(instructions);
869 // Add InstructionsBuilder to FlowBuilder
870 flowBuilder.setInstructions(isb.build());
872 writeFlow(flowBuilder, nodeBuilder);
874 removeFlow(flowBuilder, nodeBuilder);
879 * (Table:1) Table Drain w/ Catch All
881 * Action: GOTO Local Table (10)
882 * table=2,priority=8192,tun_id=0x5 actions=drop
885 public void programTunnelMiss(Long dpidLong, String segmentationId, boolean write) {
887 String nodeName = OPENFLOW + dpidLong;
889 MatchBuilder matchBuilder = new MatchBuilder();
890 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
891 FlowBuilder flowBuilder = new FlowBuilder();
893 // Create Match(es) and Set them in the FlowBuilder Object
894 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
897 // Create the OF Actions and Instructions
898 InstructionsBuilder isb = new InstructionsBuilder();
900 // Instructions List Stores Individual Instructions
901 List<Instruction> instructions = Lists.newArrayList();
903 // Call the InstructionBuilder Methods Containing Actions
904 InstructionBuilder ib = this.getMutablePipelineInstructionBuilder();
906 ib.setKey(new InstructionKey(0));
907 instructions.add(ib.build());
909 // Add InstructionBuilder to the Instruction(s)Builder List
910 isb.setInstruction(instructions);
912 // Add InstructionsBuilder to FlowBuilder
913 flowBuilder.setInstructions(isb.build());
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);
929 writeFlow(flowBuilder, nodeBuilder);
931 removeFlow(flowBuilder, nodeBuilder);
936 * (Table:1) Table Drain w/ Catch All
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
944 public void programVlanMiss(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
946 String nodeName = OPENFLOW + dpidLong;
948 MatchBuilder matchBuilder = new MatchBuilder();
949 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
950 FlowBuilder flowBuilder = new FlowBuilder();
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());
957 // Create the OF Actions and Instructions
958 InstructionBuilder ib = new InstructionBuilder();
959 InstructionsBuilder isb = new InstructionsBuilder();
961 // Instructions List Stores Individual Instructions
962 List<Instruction> instructions = Lists.newArrayList();
964 // Set the Output Port/Iface
965 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
967 ib.setKey(new InstructionKey(1));
968 instructions.add(ib.build());
970 // Add InstructionBuilder to the Instruction(s)Builder List
971 isb.setInstruction(instructions);
973 // Add InstructionsBuilder to FlowBuilder
974 flowBuilder.setInstructions(isb.build());
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);
990 writeFlow(flowBuilder, nodeBuilder);
992 removeFlow(flowBuilder, nodeBuilder);
997 * Create Output Port Group Instruction
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
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);
1010 List<Action> actionList = Lists.newArrayList();
1011 ActionBuilder ab = new ActionBuilder();
1013 List<Action> existingActions;
1014 if (instructions != null && instructions.size() > 0) {
1016 * First instruction is the one containing the output ports.
1017 * So, only extract the actions from that.
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);
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 LOG.debug("createOutputPortInstructions() : applyAction {}", aab.build());
1059 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
1060 super.setDependencies(bundleContext.getServiceReference(L2ForwardingProvider.class.getName()), this);
1064 public void setDependencies(Object impl) {