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 org.opendaylight.ovsdb.openstack.netvirt.api.L2ForwardingProvider;
16 import org.opendaylight.ovsdb.openstack.netvirt.providers.ConfigInterface;
17 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.AbstractServiceInstance;
18 import org.opendaylight.ovsdb.openstack.netvirt.providers.openflow13.Service;
19 import org.opendaylight.ovsdb.utils.mdsal.openflow.ActionUtils;
20 import org.opendaylight.ovsdb.utils.mdsal.openflow.InstructionUtils;
21 import org.opendaylight.ovsdb.utils.mdsal.openflow.MatchUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCaseBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.dst.choice.grouping.dst.choice.DstNxRegCaseBuilder;
47 import org.osgi.framework.BundleContext;
48 import org.osgi.framework.ServiceReference;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 import com.google.common.collect.Lists;
54 public class L2ForwardingService extends AbstractServiceInstance implements ConfigInterface, L2ForwardingProvider {
55 private static final Logger LOG = LoggerFactory.getLogger(L2ForwardingService.class);
56 public L2ForwardingService() {
57 super(Service.L2_FORWARDING);
60 public L2ForwardingService(Service service) {
65 * (Table:L2Forwarding) Local Unicast
66 * Match: Tunnel ID and dMAC
68 * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 goto:<next-table>
71 public void programLocalUcastOut(Long dpidLong, String segmentationId,
72 Long localPort, String attachedMac, boolean write) {
74 String nodeName = OPENFLOW + dpidLong;
76 MatchBuilder matchBuilder = new MatchBuilder();
77 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
78 FlowBuilder flowBuilder = new FlowBuilder();
80 // Create the OF Match using MatchBuilder
81 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
82 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
84 String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
85 // Add Flow Attributes
86 flowBuilder.setId(new FlowId(flowId));
87 FlowKey key = new FlowKey(new FlowId(flowId));
88 flowBuilder.setStrict(true);
89 flowBuilder.setBarrier(false);
90 flowBuilder.setTableId(getTable());
91 flowBuilder.setKey(key);
92 flowBuilder.setFlowName(flowId);
93 flowBuilder.setHardTimeout(0);
94 flowBuilder.setIdleTimeout(0);
97 // Instantiate the Builders for the OF Actions and Instructions
98 InstructionBuilder ib = new InstructionBuilder();
99 InstructionsBuilder isb = new InstructionsBuilder();
101 // Instructions List Stores Individual Instructions
102 List<Instruction> instructions = Lists.newArrayList();
104 // Set the Output Port/Iface
105 InstructionUtils.createOutputPortInstructions(ib, dpidLong, localPort);
107 ib.setKey(new InstructionKey(0));
108 instructions.add(ib.build());
110 // Add InstructionBuilder to the Instruction(s)Builder List
111 isb.setInstruction(instructions);
113 // Add InstructionsBuilder to FlowBuilder
114 flowBuilder.setInstructions(isb.build());
115 writeFlow(flowBuilder, nodeBuilder);
117 removeFlow(flowBuilder, nodeBuilder);
121 * (Table:2) Local VLAN unicast
122 * Match: VLAN ID and dMAC
123 * Action: Output Port
124 * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
125 * table=110,dl_vlan=2001,dl_dst=fa:16:3e:a3:3b:cc actions=pop_vlan,output:1
129 public void programLocalVlanUcastOut (Long dpidLong, String segmentationId, Long localPort, String attachedMac, boolean write) {
131 String nodeName = OPENFLOW + dpidLong;
133 MatchBuilder matchBuilder = new MatchBuilder();
134 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
135 FlowBuilder flowBuilder = new FlowBuilder();
137 // Create the OF Match using MatchBuilder
138 flowBuilder.setMatch(
139 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
140 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
142 String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
143 // Add Flow Attributes
144 flowBuilder.setId(new FlowId(flowId));
145 FlowKey key = new FlowKey(new FlowId(flowId));
146 flowBuilder.setStrict(true);
147 flowBuilder.setBarrier(false);
148 flowBuilder.setTableId(getTable());
149 flowBuilder.setKey(key);
150 flowBuilder.setFlowName(flowId);
151 flowBuilder.setHardTimeout(0);
152 flowBuilder.setIdleTimeout(0);
155 // Instantiate the Builders for the OF Actions and Instructions
156 InstructionBuilder ib = new InstructionBuilder();
157 InstructionsBuilder isb = new InstructionsBuilder();
159 // Instructions List Stores Individual Instructions
160 List<Instruction> instructions = Lists.newArrayList();
161 List<Instruction> instructions_tmp = Lists.newArrayList();
163 /* Strip vlan and store to tmp instruction space*/
164 InstructionUtils.createPopVlanInstructions(ib);
166 ib.setKey(new InstructionKey(0));
167 instructions_tmp.add(ib.build());
169 // Set the Output Port/Iface
170 ib = new InstructionBuilder();
171 InstructionUtils.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
173 ib.setKey(new InstructionKey(0));
174 instructions.add(ib.build());
176 // Add InstructionBuilder to the Instruction(s)Builder List
177 isb.setInstruction(instructions);
179 // Add InstructionsBuilder to FlowBuilder
180 flowBuilder.setInstructions(isb.build());
181 writeFlow(flowBuilder, nodeBuilder);
183 removeFlow(flowBuilder, nodeBuilder);
189 * Utility function used by the flooding logic to allow a flow to be resubmitted
190 * to the local port flooding rule, after being outputed to all available tunnel
191 * or VLAN egress ports.
193 private void appendResubmitLocalFlood(InstructionBuilder ib) {
195 //Update the ApplyActions instructions
196 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
197 List<Action> actionList = aac.getApplyActions().getAction();
199 int index = actionList.size();
200 ActionBuilder ab = new ActionBuilder();
201 ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(ClassifierService.REG_FIELD).build(),
202 BigInteger.valueOf(ClassifierService.REG_VALUE_FROM_REMOTE)));
204 ab.setKey(new ActionKey(index));
205 actionList.add(ab.build());
208 ab = new ActionBuilder();
209 ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
211 ab.setKey(new ActionKey(index));
212 actionList.add(ab.build());
216 * (Table:2) Local Broadcast Flood
217 * Match: Tunnel ID and dMAC (::::FF:FF)
218 * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
219 * actions=output:2,3,4,5
223 public void programLocalBcastOut(Long dpidLong, String segmentationId, Long localPort, boolean write) {
225 String nodeName = OPENFLOW + dpidLong;
227 MatchBuilder matchBuilder = new MatchBuilder();
228 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
229 FlowBuilder flowBuilder = new FlowBuilder();
231 // Create the OF Match using MatchBuilder
232 MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
233 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
234 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
235 new MacAddress("01:00:00:00:00:00")).build());
237 String flowId = "BcastOut_"+segmentationId;
238 // Add Flow Attributes
239 flowBuilder.setId(new FlowId(flowId));
240 FlowKey key = new FlowKey(new FlowId(flowId));
241 flowBuilder.setStrict(true);
242 flowBuilder.setBarrier(false);
243 flowBuilder.setTableId(getTable());
244 flowBuilder.setKey(key);
245 flowBuilder.setPriority(16384);
246 flowBuilder.setFlowName(flowId);
247 flowBuilder.setHardTimeout(0);
248 flowBuilder.setIdleTimeout(0);
249 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
250 // Instantiate the Builders for the OF Actions and Instructions
251 InstructionBuilder ib = new InstructionBuilder();
252 InstructionsBuilder isb = new InstructionsBuilder();
253 List<Instruction> instructions = Lists.newArrayList();
254 List<Instruction> existingInstructions = null;
256 Instructions ins = flow.getInstructions();
258 existingInstructions = ins.getInstruction();
263 // Create output port list
264 createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
266 ib.setKey(new InstructionKey(0));
268 /* Alternative method to address Bug 2004 is to make a call
269 * here to appendResubmitLocalFlood(ib) so that we send the
270 * flow back to the local flood rule.
272 instructions.add(ib.build());
274 // Add InstructionBuilder to the Instruction(s)Builder List
275 isb.setInstruction(instructions);
277 // Add InstructionsBuilder to FlowBuilder
278 flowBuilder.setInstructions(isb.build());
280 writeFlow(flowBuilder, nodeBuilder);
282 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong, localPort,
283 existingInstructions);
285 /* if all ports are removed, remove flow */
286 removeFlow(flowBuilder, nodeBuilder);
288 /* Install instruction with new output port list*/
290 ib.setKey(new InstructionKey(0));
291 instructions.add(ib.build());
293 // Add InstructionBuilder to the Instruction(s)Builder List
294 isb.setInstruction(instructions);
296 // Add InstructionsBuilder to FlowBuilder
297 flowBuilder.setInstructions(isb.build());
298 writeFlow(flowBuilder, nodeBuilder);
304 * (Table:2) Local VLAN Broadcast Flood
305 * Match: vlan ID and dMAC (::::FF:FF)
306 * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
307 * actions=strip_vlan, output:2,3,4,5
308 * table=110,dl_vlan=2001,dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=output:2,pop_vlan,output:1,output:3,output:4
312 public void programLocalVlanBcastOut(Long dpidLong, String segmentationId,
313 Long localPort, Long ethPort, boolean write) {
315 String nodeName = OPENFLOW + dpidLong;
317 MatchBuilder matchBuilder = new MatchBuilder();
318 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
319 FlowBuilder flowBuilder = new FlowBuilder();
321 // Create the OF Match using MatchBuilder
322 flowBuilder.setMatch(
323 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
324 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
325 new MacAddress("01:00:00:00:00:00")).build());
327 String flowId = "VlanBcastOut_"+segmentationId+"_"+ethPort;
328 // Add Flow Attributes
329 flowBuilder.setId(new FlowId(flowId));
330 FlowKey key = new FlowKey(new FlowId(flowId));
331 flowBuilder.setStrict(true);
332 flowBuilder.setBarrier(false);
333 flowBuilder.setTableId(getTable());
334 flowBuilder.setKey(key);
335 flowBuilder.setPriority(16384);
336 flowBuilder.setFlowName(flowId);
337 flowBuilder.setHardTimeout(0);
338 flowBuilder.setIdleTimeout(0);
339 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
340 // Instantiate the Builders for the OF Actions and Instructions
341 List<Instruction> existingInstructions = null;
343 Instructions ins = flow.getInstructions();
345 existingInstructions = ins.getInstruction();
349 List<Instruction> instructions = Lists.newArrayList();
350 InstructionBuilder ib = new InstructionBuilder();
351 List<Action> actionList = null;
353 if (existingInstructions == null) {
354 /* First time called there should be no instructions.
355 * We can simply add the output:ethPort first, followed by
356 * popVlan and then the local port. The next calls will append
357 * the rest of the local ports.
359 ActionBuilder ab = new ActionBuilder();
360 actionList = Lists.newArrayList();
362 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)));
364 ab.setKey(new ActionKey(0));
365 actionList.add(ab.build());
367 ab.setAction(ActionUtils.popVlanAction());
369 ab.setKey(new ActionKey(1));
370 actionList.add(ab.build());
372 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
374 ab.setKey(new ActionKey(2));
375 actionList.add(ab.build());
377 /* Subsequent calls require appending any new local ports for this tenant. */
378 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
379 Instruction in = existingInstructions.get(0);
380 actionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
382 NodeConnectorId ncid = new NodeConnectorId(nodeName + ":" + localPort);
383 boolean addNew = true;
385 /* Check if the port is already in the output list */
386 for (Action action : actionList) {
387 if (action.getAction() instanceof OutputActionCase) {
388 OutputActionCase opAction = (OutputActionCase) action.getAction();
389 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
397 ActionBuilder ab = new ActionBuilder();
399 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
400 ab.setOrder(actionList.size());
401 ab.setKey(new ActionKey(actionList.size()));
402 actionList.add(ab.build());
406 ApplyActionsBuilder aab = new ApplyActionsBuilder();
407 aab.setAction(actionList);
408 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
410 ib.setKey(new InstructionKey(0));
411 instructions.add(ib.build());
413 // Add InstructionBuilder to the Instruction(s)Builder List
414 InstructionsBuilder isb = new InstructionsBuilder();
415 isb.setInstruction(instructions);
417 // Add InstructionsBuilder to FlowBuilder
418 flowBuilder.setInstructions(isb.build());
419 writeFlow(flowBuilder, nodeBuilder);
421 //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
422 // localPort, existingInstructions);
423 boolean flowRemove = removeOutputPortFromInstructions(ib, dpidLong, localPort, ethPort,
424 existingInstructions);
426 /* if all ports are removed, remove flow */
427 removeFlow(flowBuilder, nodeBuilder);
429 /* Install instruction with new output port list*/
431 ib.setKey(new InstructionKey(0));
432 instructions.add(ib.build());
434 // Add InstructionBuilder to the Instruction(s)Builder List
435 InstructionsBuilder isb = new InstructionsBuilder();
436 isb.setInstruction(instructions);
438 // Add InstructionsBuilder to FlowBuilder
439 flowBuilder.setInstructions(isb.build());
440 writeFlow(flowBuilder, nodeBuilder);
445 private boolean removeOutputPortFromInstructions(InstructionBuilder ib, Long dpidLong, Long localPort,
446 Long ethPort, List<Instruction> instructions) {
447 List<Action> actionList = Lists.newArrayList();
448 boolean removeFlow = true;
450 if (instructions != null) {
451 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
452 Instruction in = instructions.get(0);
453 List<Action> oldActionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
454 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + localPort);
455 NodeConnectorId ncidEth = new NodeConnectorId(OPENFLOW + dpidLong + ":" + ethPort);
457 // Remove the port from the output list
458 ActionBuilder ab = new ActionBuilder();
460 //for (ListIterator<Action> it = oldActionList.listIterator(oldActionList.size()); it.hasPrevious();) {
461 // Action action = it.previous();
462 for (Action action : oldActionList) {
463 if (action.getAction() instanceof OutputActionCase) {
464 OutputActionCase opAction = (OutputActionCase) action.getAction();
465 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncidEth))) {
466 actionList.add(action);
467 } else if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid)) == false) {
468 ab.setAction(action.getAction());
470 ab.setKey(new ActionKey(index));
471 actionList.add(ab.build());
475 actionList.add(action);
478 ApplyActionsBuilder aab = new ApplyActionsBuilder();
479 aab.setAction(actionList);
480 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
483 if (actionList != null && actionList.size() > 2) {
484 // Add InstructionBuilder to the Instruction(s)Builder List
485 InstructionsBuilder isb = new InstructionsBuilder();
486 isb.setInstruction(instructions);
494 * (Table:1) Local Table Miss
495 * Match: Any Remaining Flows w/a TunID
496 * Action: Drop w/ a low priority
497 * table=2,priority=8192,tun_id=0x5 actions=drop
501 public void programLocalTableMiss(Long dpidLong, String segmentationId, boolean write) {
503 String nodeName = OPENFLOW + dpidLong;
505 MatchBuilder matchBuilder = new MatchBuilder();
506 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
507 FlowBuilder flowBuilder = new FlowBuilder();
509 // Create Match(es) and Set them in the FlowBuilder Object
510 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
513 // Create the OF Actions and Instructions
514 InstructionBuilder ib = new InstructionBuilder();
515 InstructionsBuilder isb = new InstructionsBuilder();
517 // Instructions List Stores Individual Instructions
518 List<Instruction> instructions = Lists.newArrayList();
520 // Call the InstructionBuilder Methods Containing Actions
521 InstructionUtils.createDropInstructions(ib);
523 ib.setKey(new InstructionKey(0));
524 instructions.add(ib.build());
526 // Add InstructionBuilder to the Instruction(s)Builder List
527 isb.setInstruction(instructions);
529 // Add InstructionsBuilder to FlowBuilder
530 flowBuilder.setInstructions(isb.build());
533 String flowId = "LocalTableMiss_"+segmentationId;
534 // Add Flow Attributes
535 flowBuilder.setId(new FlowId(flowId));
536 FlowKey key = new FlowKey(new FlowId(flowId));
537 flowBuilder.setStrict(true);
538 flowBuilder.setBarrier(false);
539 flowBuilder.setTableId(getTable());
540 flowBuilder.setKey(key);
541 flowBuilder.setPriority(8192);
542 flowBuilder.setFlowName(flowId);
543 flowBuilder.setHardTimeout(0);
544 flowBuilder.setIdleTimeout(0);
546 writeFlow(flowBuilder, nodeBuilder);
548 removeFlow(flowBuilder, nodeBuilder);
553 * (Table:1) Local Table Miss
554 * Match: Any Remaining Flows w/a VLAN ID
555 * Action: Drop w/ a low priority
556 * table=2,priority=8192,vlan_id=0x5 actions=drop
560 public void programLocalVlanTableMiss(Long dpidLong, String segmentationId, boolean write) {
562 String nodeName = OPENFLOW + dpidLong;
564 MatchBuilder matchBuilder = new MatchBuilder();
565 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
566 FlowBuilder flowBuilder = new FlowBuilder();
568 // Create Match(es) and Set them in the FlowBuilder Object
569 flowBuilder.setMatch(
570 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
573 // Create the OF Actions and Instructions
574 InstructionBuilder ib = new InstructionBuilder();
575 InstructionsBuilder isb = new InstructionsBuilder();
577 // Instructions List Stores Individual Instructions
578 List<Instruction> instructions = Lists.newArrayList();
580 // Call the InstructionBuilder Methods Containing Actions
581 InstructionUtils.createDropInstructions(ib);
583 ib.setKey(new InstructionKey(0));
584 instructions.add(ib.build());
586 // Add InstructionBuilder to the Instruction(s)Builder List
587 isb.setInstruction(instructions);
589 // Add InstructionsBuilder to FlowBuilder
590 flowBuilder.setInstructions(isb.build());
593 String flowId = "LocalTableMiss_"+segmentationId;
594 // Add Flow Attributes
595 flowBuilder.setId(new FlowId(flowId));
596 FlowKey key = new FlowKey(new FlowId(flowId));
597 flowBuilder.setStrict(true);
598 flowBuilder.setBarrier(false);
599 flowBuilder.setTableId(getTable());
600 flowBuilder.setKey(key);
601 flowBuilder.setPriority(8192);
602 flowBuilder.setFlowName(flowId);
603 flowBuilder.setHardTimeout(0);
604 flowBuilder.setIdleTimeout(0);
606 writeFlow(flowBuilder, nodeBuilder);
608 removeFlow(flowBuilder, nodeBuilder);
614 * (Table:1) Egress Tunnel Traffic
615 * Match: Destination Ethernet Addr and Local InPort
616 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
617 * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
618 * actions=output:10,goto_table:2"
620 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
622 public void programTunnelOut(Long dpidLong, String segmentationId, Long OFPortOut, String attachedMac, boolean write) {
624 String nodeName = OPENFLOW + dpidLong;
626 MatchBuilder matchBuilder = new MatchBuilder();
627 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
628 FlowBuilder flowBuilder = new FlowBuilder();
630 // Create the OF Match using MatchBuilder
631 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
632 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
634 String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
635 // Add Flow Attributes
636 flowBuilder.setId(new FlowId(flowId));
637 FlowKey key = new FlowKey(new FlowId(flowId));
638 flowBuilder.setStrict(true);
639 flowBuilder.setBarrier(false);
640 flowBuilder.setTableId(getTable());
641 flowBuilder.setKey(key);
642 flowBuilder.setFlowName(flowId);
643 flowBuilder.setHardTimeout(0);
644 flowBuilder.setIdleTimeout(0);
647 // Instantiate the Builders for the OF Actions and Instructions
648 InstructionBuilder ib = new InstructionBuilder();
649 InstructionsBuilder isb = new InstructionsBuilder();
651 // Instructions List Stores Individual Instructions
652 List<Instruction> instructions = Lists.newArrayList();
654 // Set the Output Port/Iface
655 InstructionUtils.createOutputPortInstructions(ib, dpidLong, OFPortOut);
657 ib.setKey(new InstructionKey(1));
658 instructions.add(ib.build());
660 // Add InstructionBuilder to the Instruction(s)Builder List
661 isb.setInstruction(instructions);
663 // Add InstructionsBuilder to FlowBuilder
664 flowBuilder.setInstructions(isb.build());
666 writeFlow(flowBuilder, nodeBuilder);
668 removeFlow(flowBuilder, nodeBuilder);
673 * (Table:1) Egress VLAN Traffic
674 * Match: Destination Ethernet Addr and VLAN id
675 * Instruction: GOTO Table Table 2
676 * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
677 * actions= goto_table:2"
679 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
681 public void programVlanOut(Long dpidLong, String segmentationId, Long ethPort, String attachedMac, boolean write) {
683 String nodeName = OPENFLOW + dpidLong;
685 MatchBuilder matchBuilder = new MatchBuilder();
686 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
687 FlowBuilder flowBuilder = new FlowBuilder();
689 // Create the OF Match using MatchBuilder
690 flowBuilder.setMatch(
691 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
692 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
694 String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
695 // Add Flow Attributes
696 flowBuilder.setId(new FlowId(flowId));
697 FlowKey key = new FlowKey(new FlowId(flowId));
698 flowBuilder.setStrict(true);
699 flowBuilder.setBarrier(false);
700 flowBuilder.setTableId(getTable());
701 flowBuilder.setKey(key);
702 flowBuilder.setFlowName(flowId);
703 flowBuilder.setHardTimeout(0);
704 flowBuilder.setIdleTimeout(0);
707 // Instantiate the Builders for the OF Actions and Instructions
708 InstructionBuilder ib = new InstructionBuilder();
709 InstructionsBuilder isb = new InstructionsBuilder();
711 // Instructions List Stores Individual Instructions
712 List<Instruction> instructions = Lists.newArrayList();
713 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
715 ib.setKey(new InstructionKey(1));
716 instructions.add(ib.build());
718 // Add InstructionBuilder to the Instruction(s)Builder List
719 isb.setInstruction(instructions);
721 // Add InstructionsBuilder to FlowBuilder
722 flowBuilder.setInstructions(isb.build());
724 writeFlow(flowBuilder, nodeBuilder);
726 removeFlow(flowBuilder, nodeBuilder);
731 * (Table:1) Egress Tunnel Traffic
732 * Match: Destination Ethernet Addr and Local InPort
733 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
734 * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
735 * actions=output:10,output:11,goto_table:2
738 public void programTunnelFloodOut(Long dpidLong, String segmentationId, Long OFPortOut, boolean write) {
740 String nodeName = OPENFLOW + dpidLong;
742 MatchBuilder matchBuilder = new MatchBuilder();
743 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
744 FlowBuilder flowBuilder = new FlowBuilder();
746 // Create the OF Match using MatchBuilder
748 MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
749 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
751 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
752 new MacAddress("01:00:00:00:00:00")).build());
754 String flowId = "TunnelFloodOut_"+segmentationId;
755 // Add Flow Attributes
756 flowBuilder.setId(new FlowId(flowId));
757 FlowKey key = new FlowKey(new FlowId(flowId));
758 flowBuilder.setBarrier(true);
759 flowBuilder.setTableId(getTable());
760 flowBuilder.setKey(key);
761 flowBuilder.setPriority(16383); // FIXME: change it back to 16384 once bug 3005 is fixed.
762 flowBuilder.setFlowName(flowId);
763 flowBuilder.setHardTimeout(0);
764 flowBuilder.setIdleTimeout(0);
766 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
767 // Instantiate the Builders for the OF Actions and Instructions
768 InstructionBuilder ib = new InstructionBuilder();
769 InstructionsBuilder isb = new InstructionsBuilder();
770 List<Instruction> instructions = Lists.newArrayList();
771 List<Instruction> existingInstructions = null;
773 Instructions ins = flow.getInstructions();
775 existingInstructions = ins.getInstruction();
780 // Set the Output Port/Iface
781 //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
782 createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
784 ib.setKey(new InstructionKey(0));
785 instructions.add(ib.build());
787 // Add InstructionBuilder to the Instruction(s)Builder List
788 isb.setInstruction(instructions);
790 // Add InstructionsBuilder to FlowBuilder
791 flowBuilder.setInstructions(isb.build());
793 writeFlow(flowBuilder, nodeBuilder);
795 /* remove port from action list */
796 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
797 OFPortOut, existingInstructions);
799 /* if all port are removed, remove the flow too. */
800 removeFlow(flowBuilder, nodeBuilder);
802 /* Install instruction with new output port list*/
804 ib.setKey(new InstructionKey(0));
805 instructions.add(ib.build());
807 // Add InstructionBuilder to the Instruction(s)Builder List
808 isb.setInstruction(instructions);
810 // Add InstructionsBuilder to FlowBuilder
811 flowBuilder.setInstructions(isb.build());
812 writeFlow(flowBuilder, nodeBuilder);
818 * (Table:1) Egress VLAN Traffic
819 * Match: Destination Ethernet Addr and VLAN id
820 * Instruction: GOTO table 2 and Output port eth interface
821 * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
822 * actions=output:eth1,goto_table:2
826 public void programVlanFloodOut(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
828 String nodeName = OPENFLOW + dpidLong;
830 MatchBuilder matchBuilder = new MatchBuilder();
831 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
832 FlowBuilder flowBuilder = new FlowBuilder();
834 // Create the OF Match using MatchBuilder
836 flowBuilder.setMatch(
837 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
839 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
840 new MacAddress("01:00:00:00:00:00")).build());
842 String flowId = "VlanFloodOut_"+segmentationId+"_"+ethPort;
843 // Add Flow Attributes
844 flowBuilder.setId(new FlowId(flowId));
845 FlowKey key = new FlowKey(new FlowId(flowId));
846 flowBuilder.setBarrier(true);
847 flowBuilder.setTableId(getTable());
848 flowBuilder.setKey(key);
849 flowBuilder.setPriority(16384);
850 flowBuilder.setFlowName(flowId);
851 flowBuilder.setHardTimeout(0);
852 flowBuilder.setIdleTimeout(0);
854 //ToDo: Is there something to be done with result of the call to getFlow?
856 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
857 // Instantiate the Builders for the OF Actions and Instructions
858 InstructionBuilder ib = new InstructionBuilder();
859 InstructionsBuilder isb = new InstructionsBuilder();
860 List<Instruction> instructions = Lists.newArrayList();
863 // Set the Output Port/Iface
864 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
866 ib.setKey(new InstructionKey(0));
867 instructions.add(ib.build());
869 // Add InstructionBuilder to the Instruction(s)Builder List
870 isb.setInstruction(instructions);
872 // Add InstructionsBuilder to FlowBuilder
873 flowBuilder.setInstructions(isb.build());
875 writeFlow(flowBuilder, nodeBuilder);
877 removeFlow(flowBuilder, nodeBuilder);
882 * (Table:1) Table Drain w/ Catch All
884 * Action: GOTO Local Table (10)
885 * table=2,priority=8192,tun_id=0x5 actions=drop
888 public void programTunnelMiss(Long dpidLong, String segmentationId, boolean write) {
890 String nodeName = OPENFLOW + dpidLong;
892 MatchBuilder matchBuilder = new MatchBuilder();
893 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
894 FlowBuilder flowBuilder = new FlowBuilder();
896 // Create Match(es) and Set them in the FlowBuilder Object
897 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
900 // Create the OF Actions and Instructions
901 InstructionBuilder ib = new InstructionBuilder();
902 InstructionsBuilder isb = new InstructionsBuilder();
904 // Instructions List Stores Individual Instructions
905 List<Instruction> instructions = Lists.newArrayList();
907 // Call the InstructionBuilder Methods Containing Actions
908 ib = this.getMutablePipelineInstructionBuilder();
910 ib.setKey(new InstructionKey(0));
911 instructions.add(ib.build());
913 // Add InstructionBuilder to the Instruction(s)Builder List
914 isb.setInstruction(instructions);
916 // Add InstructionsBuilder to FlowBuilder
917 flowBuilder.setInstructions(isb.build());
920 String flowId = "TunnelMiss_"+segmentationId;
921 // Add Flow Attributes
922 flowBuilder.setId(new FlowId(flowId));
923 FlowKey key = new FlowKey(new FlowId(flowId));
924 flowBuilder.setStrict(true);
925 flowBuilder.setBarrier(false);
926 flowBuilder.setTableId(getTable());
927 flowBuilder.setKey(key);
928 flowBuilder.setPriority(8192);
929 flowBuilder.setFlowName(flowId);
930 flowBuilder.setHardTimeout(0);
931 flowBuilder.setIdleTimeout(0);
933 writeFlow(flowBuilder, nodeBuilder);
935 removeFlow(flowBuilder, nodeBuilder);
940 * (Table:1) Table Drain w/ Catch All
942 * Action: Output port eth interface
943 * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
944 * table=110,priority=8192,dl_vlan=2001 actions=output:2
948 public void programVlanMiss(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
950 String nodeName = OPENFLOW + dpidLong;
952 MatchBuilder matchBuilder = new MatchBuilder();
953 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
954 FlowBuilder flowBuilder = new FlowBuilder();
956 // Create Match(es) and Set them in the FlowBuilder Object
957 flowBuilder.setMatch(
958 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
961 // Create the OF Actions and Instructions
962 InstructionBuilder ib = new InstructionBuilder();
963 InstructionsBuilder isb = new InstructionsBuilder();
965 // Instructions List Stores Individual Instructions
966 List<Instruction> instructions = Lists.newArrayList();
968 // Set the Output Port/Iface
969 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
971 ib.setKey(new InstructionKey(1));
972 instructions.add(ib.build());
974 // Add InstructionBuilder to the Instruction(s)Builder List
975 isb.setInstruction(instructions);
977 // Add InstructionsBuilder to FlowBuilder
978 flowBuilder.setInstructions(isb.build());
981 String flowId = "VlanMiss_"+segmentationId;
982 // Add Flow Attributes
983 flowBuilder.setId(new FlowId(flowId));
984 FlowKey key = new FlowKey(new FlowId(flowId));
985 flowBuilder.setStrict(true);
986 flowBuilder.setBarrier(false);
987 flowBuilder.setTableId(getTable());
988 flowBuilder.setKey(key);
989 flowBuilder.setPriority(8192);
990 flowBuilder.setFlowName(flowId);
991 flowBuilder.setHardTimeout(0);
992 flowBuilder.setIdleTimeout(0);
994 writeFlow(flowBuilder, nodeBuilder);
996 removeFlow(flowBuilder, nodeBuilder);
1001 * Create Output Port Group Instruction
1003 * @param ib Map InstructionBuilder without any instructions
1004 * @param dpidLong Long the datapath ID of a switch/node
1005 * @param port Long representing a port on a switch/node
1006 * @return ib InstructionBuilder Map with instructions
1008 protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
1009 Long dpidLong, Long port ,
1010 List<Instruction> instructions) {
1011 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
1012 LOG.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
1014 List<Action> actionList = Lists.newArrayList();
1015 ActionBuilder ab = new ActionBuilder();
1017 List<Action> existingActions;
1018 if (instructions != null && instructions.size() > 0) {
1020 * First instruction is the one containing the output ports.
1021 * So, only extract the actions from that.
1023 Instruction in = instructions.get(0);
1024 if (in.getInstruction() instanceof ApplyActionsCase) {
1025 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
1026 // Only include output actions
1027 for (Action action : existingActions) {
1028 if (action.getAction() instanceof OutputActionCase) {
1029 actionList.add(action);
1034 /* Create output action for this port*/
1035 OutputActionBuilder oab = new OutputActionBuilder();
1036 oab.setOutputNodeConnector(ncid);
1037 ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
1038 boolean addNew = true;
1040 /* Find the group action and get the group */
1041 for (Action action : actionList) {
1042 OutputActionCase opAction = (OutputActionCase)action.getAction();
1043 /* If output port action already in the action list of one of the buckets, skip */
1044 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
1050 ab.setOrder(actionList.size());
1051 ab.setKey(new ActionKey(actionList.size()));
1052 actionList.add(ab.build());
1054 // Create an Apply Action
1055 ApplyActionsBuilder aab = new ApplyActionsBuilder();
1056 aab.setAction(actionList);
1057 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1058 LOG.debug("createOutputPortInstructions() : applyAction {}", aab.build());
1063 public void setDependencies(BundleContext bundleContext, ServiceReference serviceReference) {
1064 super.setDependencies(bundleContext.getServiceReference(L2ForwardingProvider.class.getName()), this);
1068 public void setDependencies(Object impl) {