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.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.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 import com.google.common.collect.Lists;
51 public class L2ForwardingService extends AbstractServiceInstance implements L2ForwardingProvider {
52 private static final Logger logger = LoggerFactory.getLogger(L2ForwardingService.class);
53 public L2ForwardingService() {
54 super(Service.L2_FORWARDING);
57 public L2ForwardingService(Service service) {
62 * (Table:L2Forwarding) Local Unicast
63 * Match: Tunnel ID and dMAC
65 * table=2,tun_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2 goto:<next-table>
68 public void programLocalUcastOut(Long dpidLong, String segmentationId,
69 Long localPort, String attachedMac, boolean write) {
71 String nodeName = OPENFLOW + dpidLong;
73 MatchBuilder matchBuilder = new MatchBuilder();
74 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
75 FlowBuilder flowBuilder = new FlowBuilder();
77 // Create the OF Match using MatchBuilder
78 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
79 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
81 String flowId = "UcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
82 // Add Flow Attributes
83 flowBuilder.setId(new FlowId(flowId));
84 FlowKey key = new FlowKey(new FlowId(flowId));
85 flowBuilder.setStrict(true);
86 flowBuilder.setBarrier(false);
87 flowBuilder.setTableId(getTable());
88 flowBuilder.setKey(key);
89 flowBuilder.setFlowName(flowId);
90 flowBuilder.setHardTimeout(0);
91 flowBuilder.setIdleTimeout(0);
94 // Instantiate the Builders for the OF Actions and Instructions
95 InstructionBuilder ib = new InstructionBuilder();
96 InstructionsBuilder isb = new InstructionsBuilder();
98 // Instructions List Stores Individual Instructions
99 List<Instruction> instructions = Lists.newArrayList();
101 // Set the Output Port/Iface
102 InstructionUtils.createOutputPortInstructions(ib, dpidLong, localPort);
104 ib.setKey(new InstructionKey(0));
105 instructions.add(ib.build());
107 // Add InstructionBuilder to the Instruction(s)Builder List
108 isb.setInstruction(instructions);
110 // Add InstructionsBuilder to FlowBuilder
111 flowBuilder.setInstructions(isb.build());
112 writeFlow(flowBuilder, nodeBuilder);
114 removeFlow(flowBuilder, nodeBuilder);
118 * (Table:2) Local VLAN unicast
119 * Match: VLAN ID and dMAC
120 * Action: Output Port
121 * table=2,vlan_id=0x5,dl_dst=00:00:00:00:00:01 actions=output:2
122 * table=110,dl_vlan=2001,dl_dst=fa:16:3e:a3:3b:cc actions=pop_vlan,output:1
126 public void programLocalVlanUcastOut (Long dpidLong, String segmentationId, Long localPort, String attachedMac, boolean write) {
128 String nodeName = OPENFLOW + dpidLong;
130 MatchBuilder matchBuilder = new MatchBuilder();
131 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
132 FlowBuilder flowBuilder = new FlowBuilder();
134 // Create the OF Match using MatchBuilder
135 flowBuilder.setMatch(
136 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
137 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
139 String flowId = "VlanUcastOut_"+segmentationId+"_"+localPort+"_"+attachedMac;
140 // Add Flow Attributes
141 flowBuilder.setId(new FlowId(flowId));
142 FlowKey key = new FlowKey(new FlowId(flowId));
143 flowBuilder.setStrict(true);
144 flowBuilder.setBarrier(false);
145 flowBuilder.setTableId(getTable());
146 flowBuilder.setKey(key);
147 flowBuilder.setFlowName(flowId);
148 flowBuilder.setHardTimeout(0);
149 flowBuilder.setIdleTimeout(0);
152 // Instantiate the Builders for the OF Actions and Instructions
153 InstructionBuilder ib = new InstructionBuilder();
154 InstructionsBuilder isb = new InstructionsBuilder();
156 // Instructions List Stores Individual Instructions
157 List<Instruction> instructions = Lists.newArrayList();
158 List<Instruction> instructions_tmp = Lists.newArrayList();
160 /* Strip vlan and store to tmp instruction space*/
161 InstructionUtils.createPopVlanInstructions(ib);
163 ib.setKey(new InstructionKey(0));
164 instructions_tmp.add(ib.build());
166 // Set the Output Port/Iface
167 ib = new InstructionBuilder();
168 InstructionUtils.addOutputPortInstructions(ib, dpidLong, localPort, instructions_tmp);
170 ib.setKey(new InstructionKey(0));
171 instructions.add(ib.build());
173 // Add InstructionBuilder to the Instruction(s)Builder List
174 isb.setInstruction(instructions);
176 // Add InstructionsBuilder to FlowBuilder
177 flowBuilder.setInstructions(isb.build());
178 writeFlow(flowBuilder, nodeBuilder);
180 removeFlow(flowBuilder, nodeBuilder);
186 * Utility funcion used by the flooding logic to allow a flow to be resubmitted
187 * to the local port flooding rule, after being outputed to all available tunnel
188 * or VLAN egress ports.
190 private void appendResubmitLocalFlood(InstructionBuilder ib) {
192 //Update the ApplyActions instructions
193 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
194 List<Action> actionList = aac.getApplyActions().getAction();
196 int index = actionList.size();
197 ActionBuilder ab = new ActionBuilder();
198 ab.setAction(ActionUtils.nxLoadRegAction(new DstNxRegCaseBuilder().setNxReg(ClassifierService.REG_FIELD).build(),
199 BigInteger.valueOf(ClassifierService.REG_VALUE_FROM_REMOTE)));
201 ab.setKey(new ActionKey(index));
202 actionList.add(ab.build());
205 ab = new ActionBuilder();
206 ab.setAction(ActionUtils.nxResubmitAction(null, this.getTable()));
208 ab.setKey(new ActionKey(index));
209 actionList.add(ab.build());
213 * (Table:2) Local Broadcast Flood
214 * Match: Tunnel ID and dMAC (::::FF:FF)
215 * table=2,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
216 * actions=output:2,3,4,5
220 public void programLocalBcastOut(Long dpidLong, String segmentationId, Long localPort, boolean write) {
222 String nodeName = OPENFLOW + dpidLong;
224 MatchBuilder matchBuilder = new MatchBuilder();
225 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
226 FlowBuilder flowBuilder = new FlowBuilder();
228 // Create the OF Match using MatchBuilder
229 MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_REMOTE));
230 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
231 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
232 new MacAddress("01:00:00:00:00:00")).build());
234 String flowId = "BcastOut_"+segmentationId;
235 // Add Flow Attributes
236 flowBuilder.setId(new FlowId(flowId));
237 FlowKey key = new FlowKey(new FlowId(flowId));
238 flowBuilder.setStrict(true);
239 flowBuilder.setBarrier(false);
240 flowBuilder.setTableId(getTable());
241 flowBuilder.setKey(key);
242 flowBuilder.setPriority(16384);
243 flowBuilder.setFlowName(flowId);
244 flowBuilder.setHardTimeout(0);
245 flowBuilder.setIdleTimeout(0);
246 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
247 // Instantiate the Builders for the OF Actions and Instructions
248 InstructionBuilder ib = new InstructionBuilder();
249 InstructionsBuilder isb = new InstructionsBuilder();
250 List<Instruction> instructions = Lists.newArrayList();
251 List<Instruction> existingInstructions = null;
253 Instructions ins = flow.getInstructions();
255 existingInstructions = ins.getInstruction();
260 // Create output port list
261 createOutputPortInstructions(ib, dpidLong, localPort, existingInstructions);
263 ib.setKey(new InstructionKey(0));
265 /* Alternative method to address Bug 2004 is to make a call
266 * here to appendResubmitLocalFlood(ib) so that we send the
267 * flow back to the local flood rule.
269 instructions.add(ib.build());
271 // Add InstructionBuilder to the Instruction(s)Builder List
272 isb.setInstruction(instructions);
274 // Add InstructionsBuilder to FlowBuilder
275 flowBuilder.setInstructions(isb.build());
277 writeFlow(flowBuilder, nodeBuilder);
279 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong, localPort,
280 existingInstructions);
282 /* if all ports are removed, remove flow */
283 removeFlow(flowBuilder, nodeBuilder);
285 /* Install instruction with new output port list*/
287 ib.setKey(new InstructionKey(0));
288 instructions.add(ib.build());
290 // Add InstructionBuilder to the Instruction(s)Builder List
291 isb.setInstruction(instructions);
293 // Add InstructionsBuilder to FlowBuilder
294 flowBuilder.setInstructions(isb.build());
295 writeFlow(flowBuilder, nodeBuilder);
301 * (Table:2) Local VLAN Broadcast Flood
302 * Match: vlan ID and dMAC (::::FF:FF)
303 * table=2,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
304 * actions=strip_vlan, output:2,3,4,5
305 * 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
309 public void programLocalVlanBcastOut(Long dpidLong,
310 String segmentationId, Long localPort, Long ethPort, boolean write) {
312 String nodeName = OPENFLOW + dpidLong;
314 MatchBuilder matchBuilder = new MatchBuilder();
315 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
316 FlowBuilder flowBuilder = new FlowBuilder();
318 // Create the OF Match using MatchBuilder
319 flowBuilder.setMatch(
320 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
321 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
322 new MacAddress("01:00:00:00:00:00")).build());
324 String flowId = "VlanBcastOut_"+segmentationId+"_"+ethPort;
325 // Add Flow Attributes
326 flowBuilder.setId(new FlowId(flowId));
327 FlowKey key = new FlowKey(new FlowId(flowId));
328 flowBuilder.setStrict(true);
329 flowBuilder.setBarrier(false);
330 flowBuilder.setTableId(getTable());
331 flowBuilder.setKey(key);
332 flowBuilder.setPriority(16384);
333 flowBuilder.setFlowName(flowId);
334 flowBuilder.setHardTimeout(0);
335 flowBuilder.setIdleTimeout(0);
336 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
337 // Instantiate the Builders for the OF Actions and Instructions
338 List<Instruction> existingInstructions = null;
340 Instructions ins = flow.getInstructions();
342 existingInstructions = ins.getInstruction();
346 List<Instruction> instructions = Lists.newArrayList();
347 InstructionBuilder ib = new InstructionBuilder();
348 List<Action> actionList = null;
350 if (existingInstructions == null) {
351 /* First time called there should be no instructions.
352 * We can simply add the output:ethPort first, followed by
353 * popVlan and then the local port. The next calls will append
354 * the rest of the local ports.
356 ActionBuilder ab = new ActionBuilder();
357 actionList = Lists.newArrayList();
359 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + ethPort)));
361 ab.setKey(new ActionKey(0));
362 actionList.add(ab.build());
364 ab.setAction(ActionUtils.popVlanAction());
366 ab.setKey(new ActionKey(1));
367 actionList.add(ab.build());
369 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
371 ab.setKey(new ActionKey(2));
372 actionList.add(ab.build());
374 /* Subsequent calls require appending any new local ports for this tenant. */
375 ApplyActionsCase aac = (ApplyActionsCase) ib.getInstruction();
376 Instruction in = existingInstructions.get(0);
377 actionList = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
379 NodeConnectorId ncid = new NodeConnectorId(nodeName + ":" + localPort);
380 boolean addNew = true;
382 /* Check if the port is already in the output list */
383 for (Action action : actionList) {
384 if (action.getAction() instanceof OutputActionCase) {
385 OutputActionCase opAction = (OutputActionCase) action.getAction();
386 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
392 logger.info("VlanBcastOut_ addNew= {}", addNew);
394 ActionBuilder ab = new ActionBuilder();
396 ab.setAction(ActionUtils.outputAction(new NodeConnectorId(nodeName + ":" + localPort)));
397 ab.setOrder(actionList.size());
398 ab.setKey(new ActionKey(actionList.size()));
399 actionList.add(ab.build());
403 ApplyActionsBuilder aab = new ApplyActionsBuilder();
404 aab.setAction(actionList);
405 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
407 ib.setKey(new InstructionKey(0));
408 instructions.add(ib.build());
410 // Add InstructionBuilder to the Instruction(s)Builder List
411 InstructionsBuilder isb = new InstructionsBuilder();
412 isb.setInstruction(instructions);
414 // Add InstructionsBuilder to FlowBuilder
415 flowBuilder.setInstructions(isb.build());
417 writeFlow(flowBuilder, nodeBuilder);
419 //boolean flowRemove = removeOutputPortFromGroup(nodeBuilder, ib, dpidLong,
420 // localPort, existingInstructions);
421 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
422 localPort, 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);
444 * (Table:1) Local Table Miss
445 * Match: Any Remaining Flows w/a TunID
446 * Action: Drop w/ a low priority
447 * table=2,priority=8192,tun_id=0x5 actions=drop
451 public void programLocalTableMiss(Long dpidLong, String segmentationId, boolean write) {
453 String nodeName = OPENFLOW + dpidLong;
455 MatchBuilder matchBuilder = new MatchBuilder();
456 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
457 FlowBuilder flowBuilder = new FlowBuilder();
459 // Create Match(es) and Set them in the FlowBuilder Object
460 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
463 // Create the OF Actions and Instructions
464 InstructionBuilder ib = new InstructionBuilder();
465 InstructionsBuilder isb = new InstructionsBuilder();
467 // Instructions List Stores Individual Instructions
468 List<Instruction> instructions = Lists.newArrayList();
470 // Call the InstructionBuilder Methods Containing Actions
471 InstructionUtils.createDropInstructions(ib);
473 ib.setKey(new InstructionKey(0));
474 instructions.add(ib.build());
476 // Add InstructionBuilder to the Instruction(s)Builder List
477 isb.setInstruction(instructions);
479 // Add InstructionsBuilder to FlowBuilder
480 flowBuilder.setInstructions(isb.build());
483 String flowId = "LocalTableMiss_"+segmentationId;
484 // Add Flow Attributes
485 flowBuilder.setId(new FlowId(flowId));
486 FlowKey key = new FlowKey(new FlowId(flowId));
487 flowBuilder.setStrict(true);
488 flowBuilder.setBarrier(false);
489 flowBuilder.setTableId(getTable());
490 flowBuilder.setKey(key);
491 flowBuilder.setPriority(8192);
492 flowBuilder.setFlowName(flowId);
493 flowBuilder.setHardTimeout(0);
494 flowBuilder.setIdleTimeout(0);
496 writeFlow(flowBuilder, nodeBuilder);
498 removeFlow(flowBuilder, nodeBuilder);
503 * (Table:1) Local Table Miss
504 * Match: Any Remaining Flows w/a VLAN ID
505 * Action: Drop w/ a low priority
506 * table=2,priority=8192,vlan_id=0x5 actions=drop
510 public void programLocalVlanTableMiss(Long dpidLong, String segmentationId, boolean write) {
512 String nodeName = OPENFLOW + dpidLong;
514 MatchBuilder matchBuilder = new MatchBuilder();
515 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
516 FlowBuilder flowBuilder = new FlowBuilder();
518 // Create Match(es) and Set them in the FlowBuilder Object
519 flowBuilder.setMatch(
520 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
523 // Create the OF Actions and Instructions
524 InstructionBuilder ib = new InstructionBuilder();
525 InstructionsBuilder isb = new InstructionsBuilder();
527 // Instructions List Stores Individual Instructions
528 List<Instruction> instructions = Lists.newArrayList();
530 // Call the InstructionBuilder Methods Containing Actions
531 InstructionUtils.createDropInstructions(ib);
533 ib.setKey(new InstructionKey(0));
534 instructions.add(ib.build());
536 // Add InstructionBuilder to the Instruction(s)Builder List
537 isb.setInstruction(instructions);
539 // Add InstructionsBuilder to FlowBuilder
540 flowBuilder.setInstructions(isb.build());
543 String flowId = "LocalTableMiss_"+segmentationId;
544 // Add Flow Attributes
545 flowBuilder.setId(new FlowId(flowId));
546 FlowKey key = new FlowKey(new FlowId(flowId));
547 flowBuilder.setStrict(true);
548 flowBuilder.setBarrier(false);
549 flowBuilder.setTableId(getTable());
550 flowBuilder.setKey(key);
551 flowBuilder.setPriority(8192);
552 flowBuilder.setFlowName(flowId);
553 flowBuilder.setHardTimeout(0);
554 flowBuilder.setIdleTimeout(0);
556 writeFlow(flowBuilder, nodeBuilder);
558 removeFlow(flowBuilder, nodeBuilder);
564 * (Table:1) Egress Tunnel Traffic
565 * Match: Destination Ethernet Addr and Local InPort
566 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
567 * table=1,tun_id=0x5,dl_dst=00:00:00:00:00:08 \
568 * actions=output:10,goto_table:2"
570 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
572 public void programTunnelOut(Long dpidLong, String segmentationId, Long OFPortOut, String attachedMac, boolean write) {
574 String nodeName = OPENFLOW + dpidLong;
576 MatchBuilder matchBuilder = new MatchBuilder();
577 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
578 FlowBuilder flowBuilder = new FlowBuilder();
580 // Create the OF Match using MatchBuilder
581 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
582 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
584 String flowId = "TunnelOut_"+segmentationId+"_"+OFPortOut+"_"+attachedMac;
585 // Add Flow Attributes
586 flowBuilder.setId(new FlowId(flowId));
587 FlowKey key = new FlowKey(new FlowId(flowId));
588 flowBuilder.setStrict(true);
589 flowBuilder.setBarrier(false);
590 flowBuilder.setTableId(getTable());
591 flowBuilder.setKey(key);
592 flowBuilder.setFlowName(flowId);
593 flowBuilder.setHardTimeout(0);
594 flowBuilder.setIdleTimeout(0);
597 // Instantiate the Builders for the OF Actions and Instructions
598 InstructionBuilder ib = new InstructionBuilder();
599 InstructionsBuilder isb = new InstructionsBuilder();
601 // Instructions List Stores Individual Instructions
602 List<Instruction> instructions = Lists.newArrayList();
604 // Set the Output Port/Iface
605 InstructionUtils.createOutputPortInstructions(ib, dpidLong, OFPortOut);
607 ib.setKey(new InstructionKey(1));
608 instructions.add(ib.build());
610 // Add InstructionBuilder to the Instruction(s)Builder List
611 isb.setInstruction(instructions);
613 // Add InstructionsBuilder to FlowBuilder
614 flowBuilder.setInstructions(isb.build());
616 writeFlow(flowBuilder, nodeBuilder);
618 removeFlow(flowBuilder, nodeBuilder);
623 * (Table:1) Egress VLAN Traffic
624 * Match: Destination Ethernet Addr and VLAN id
625 * Instruction: GOTO Table Table 2
626 * table=1,vlan_id=0x5,dl_dst=00:00:00:00:00:08 \
627 * actions= goto_table:2"
629 // TODO : Check on the reason why the original handleTunnelOut was chaining the traffic to table 2
631 public void programVlanOut(Long dpidLong, String segmentationId, Long ethPort, String attachedMac, boolean write) {
633 String nodeName = OPENFLOW + dpidLong;
635 MatchBuilder matchBuilder = new MatchBuilder();
636 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
637 FlowBuilder flowBuilder = new FlowBuilder();
639 // Create the OF Match using MatchBuilder
640 flowBuilder.setMatch(
641 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
642 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress(attachedMac), null).build());
644 String flowId = "VlanOut_"+segmentationId+"_"+ethPort+"_"+attachedMac;
645 // Add Flow Attributes
646 flowBuilder.setId(new FlowId(flowId));
647 FlowKey key = new FlowKey(new FlowId(flowId));
648 flowBuilder.setStrict(true);
649 flowBuilder.setBarrier(false);
650 flowBuilder.setTableId(getTable());
651 flowBuilder.setKey(key);
652 flowBuilder.setFlowName(flowId);
653 flowBuilder.setHardTimeout(0);
654 flowBuilder.setIdleTimeout(0);
657 // Instantiate the Builders for the OF Actions and Instructions
658 InstructionBuilder ib = new InstructionBuilder();
659 InstructionsBuilder isb = new InstructionsBuilder();
661 // Instructions List Stores Individual Instructions
662 List<Instruction> instructions = Lists.newArrayList();
663 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
665 ib.setKey(new InstructionKey(1));
666 instructions.add(ib.build());
668 // Add InstructionBuilder to the Instruction(s)Builder List
669 isb.setInstruction(instructions);
671 // Add InstructionsBuilder to FlowBuilder
672 flowBuilder.setInstructions(isb.build());
674 writeFlow(flowBuilder, nodeBuilder);
676 removeFlow(flowBuilder, nodeBuilder);
681 * (Table:1) Egress Tunnel Traffic
682 * Match: Destination Ethernet Addr and Local InPort
683 * Instruction: Set TunnelID and GOTO Table Tunnel Table (n)
684 * table=1,priority=16384,tun_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
685 * actions=output:10,output:11,goto_table:2
688 public void programTunnelFloodOut(Long dpidLong, String segmentationId, Long OFPortOut, boolean write) {
690 String nodeName = OPENFLOW + dpidLong;
692 MatchBuilder matchBuilder = new MatchBuilder();
693 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
694 FlowBuilder flowBuilder = new FlowBuilder();
696 // Create the OF Match using MatchBuilder
698 MatchUtils.addNxRegMatch(matchBuilder, new MatchUtils.RegMatch(ClassifierService.REG_FIELD, ClassifierService.REG_VALUE_FROM_LOCAL));
699 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
701 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
702 new MacAddress("01:00:00:00:00:00")).build());
704 String flowId = "TunnelFloodOut_"+segmentationId;
705 // Add Flow Attributes
706 flowBuilder.setId(new FlowId(flowId));
707 FlowKey key = new FlowKey(new FlowId(flowId));
708 flowBuilder.setBarrier(true);
709 flowBuilder.setTableId(getTable());
710 flowBuilder.setKey(key);
711 flowBuilder.setPriority(16384);
712 flowBuilder.setFlowName(flowId);
713 flowBuilder.setHardTimeout(0);
714 flowBuilder.setIdleTimeout(0);
716 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
717 // Instantiate the Builders for the OF Actions and Instructions
718 InstructionBuilder ib = new InstructionBuilder();
719 InstructionsBuilder isb = new InstructionsBuilder();
720 List<Instruction> instructions = Lists.newArrayList();
721 List<Instruction> existingInstructions = null;
723 Instructions ins = flow.getInstructions();
725 existingInstructions = ins.getInstruction();
730 // Set the Output Port/Iface
731 //createOutputGroupInstructions(nodeBuilder, ib, dpidLong, OFPortOut, existingInstructions);
732 createOutputPortInstructions(ib, dpidLong, OFPortOut, existingInstructions);
734 ib.setKey(new InstructionKey(0));
735 instructions.add(ib.build());
737 // Add InstructionBuilder to the Instruction(s)Builder List
738 isb.setInstruction(instructions);
740 // Add InstructionsBuilder to FlowBuilder
741 flowBuilder.setInstructions(isb.build());
743 writeFlow(flowBuilder, nodeBuilder);
745 /* remove port from action list */
746 boolean flowRemove = InstructionUtils.removeOutputPortFromInstructions(ib, dpidLong,
747 OFPortOut, existingInstructions);
749 /* if all port are removed, remove the flow too. */
750 removeFlow(flowBuilder, nodeBuilder);
752 /* Install instruction with new output port list*/
754 ib.setKey(new InstructionKey(0));
755 instructions.add(ib.build());
757 // Add InstructionBuilder to the Instruction(s)Builder List
758 isb.setInstruction(instructions);
760 // Add InstructionsBuilder to FlowBuilder
761 flowBuilder.setInstructions(isb.build());
762 writeFlow(flowBuilder, nodeBuilder);
768 * (Table:1) Egress VLAN Traffic
769 * Match: Destination Ethernet Addr and VLAN id
770 * Instruction: GOTO table 2 and Output port eth interface
771 * Example: table=1,priority=16384,vlan_id=0x5,dl_dst=ff:ff:ff:ff:ff:ff \
772 * actions=output:eth1,goto_table:2
776 public void programVlanFloodOut(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
778 String nodeName = OPENFLOW + dpidLong;
780 MatchBuilder matchBuilder = new MatchBuilder();
781 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
782 FlowBuilder flowBuilder = new FlowBuilder();
784 // Create the OF Match using MatchBuilder
786 flowBuilder.setMatch(
787 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
789 flowBuilder.setMatch(MatchUtils.createDestEthMatch(matchBuilder, new MacAddress("01:00:00:00:00:00"),
790 new MacAddress("01:00:00:00:00:00")).build());
792 String flowId = "VlanFloodOut_"+segmentationId+"_"+ethPort;
793 // Add Flow Attributes
794 flowBuilder.setId(new FlowId(flowId));
795 FlowKey key = new FlowKey(new FlowId(flowId));
796 flowBuilder.setBarrier(true);
797 flowBuilder.setTableId(getTable());
798 flowBuilder.setKey(key);
799 flowBuilder.setPriority(16384);
800 flowBuilder.setFlowName(flowId);
801 flowBuilder.setHardTimeout(0);
802 flowBuilder.setIdleTimeout(0);
804 //ToDo: Is there something to be done with result of the call to getFlow?
806 Flow flow = this.getFlow(flowBuilder, nodeBuilder);
807 // Instantiate the Builders for the OF Actions and Instructions
808 InstructionBuilder ib = new InstructionBuilder();
809 InstructionsBuilder isb = new InstructionsBuilder();
810 List<Instruction> instructions = Lists.newArrayList();
813 // Set the Output Port/Iface
814 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
816 ib.setKey(new InstructionKey(0));
817 instructions.add(ib.build());
819 // Add InstructionBuilder to the Instruction(s)Builder List
820 isb.setInstruction(instructions);
822 // Add InstructionsBuilder to FlowBuilder
823 flowBuilder.setInstructions(isb.build());
825 writeFlow(flowBuilder, nodeBuilder);
827 removeFlow(flowBuilder, nodeBuilder);
832 * (Table:1) Table Drain w/ Catch All
834 * Action: GOTO Local Table (10)
835 * table=2,priority=8192,tun_id=0x5 actions=drop
838 public void programTunnelMiss(Long dpidLong, String segmentationId, boolean write) {
840 String nodeName = OPENFLOW + dpidLong;
842 MatchBuilder matchBuilder = new MatchBuilder();
843 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
844 FlowBuilder flowBuilder = new FlowBuilder();
846 // Create Match(es) and Set them in the FlowBuilder Object
847 flowBuilder.setMatch(MatchUtils.createTunnelIDMatch(matchBuilder, new BigInteger(segmentationId)).build());
850 // Create the OF Actions and Instructions
851 InstructionBuilder ib = new InstructionBuilder();
852 InstructionsBuilder isb = new InstructionsBuilder();
854 // Instructions List Stores Individual Instructions
855 List<Instruction> instructions = Lists.newArrayList();
857 // Call the InstructionBuilder Methods Containing Actions
858 ib = this.getMutablePipelineInstructionBuilder();
860 ib.setKey(new InstructionKey(0));
861 instructions.add(ib.build());
863 // Add InstructionBuilder to the Instruction(s)Builder List
864 isb.setInstruction(instructions);
866 // Add InstructionsBuilder to FlowBuilder
867 flowBuilder.setInstructions(isb.build());
870 String flowId = "TunnelMiss_"+segmentationId;
871 // Add Flow Attributes
872 flowBuilder.setId(new FlowId(flowId));
873 FlowKey key = new FlowKey(new FlowId(flowId));
874 flowBuilder.setStrict(true);
875 flowBuilder.setBarrier(false);
876 flowBuilder.setTableId(getTable());
877 flowBuilder.setKey(key);
878 flowBuilder.setPriority(8192);
879 flowBuilder.setFlowName(flowId);
880 flowBuilder.setHardTimeout(0);
881 flowBuilder.setIdleTimeout(0);
883 writeFlow(flowBuilder, nodeBuilder);
885 removeFlow(flowBuilder, nodeBuilder);
890 * (Table:1) Table Drain w/ Catch All
892 * Action: Output port eth interface
893 * table=1,priority=8192,vlan_id=0x5 actions= output port:eth1
894 * table=110,priority=8192,dl_vlan=2001 actions=output:2
898 public void programVlanMiss(Long dpidLong, String segmentationId, Long ethPort, boolean write) {
900 String nodeName = OPENFLOW + dpidLong;
902 MatchBuilder matchBuilder = new MatchBuilder();
903 NodeBuilder nodeBuilder = createNodeBuilder(nodeName);
904 FlowBuilder flowBuilder = new FlowBuilder();
906 // Create Match(es) and Set them in the FlowBuilder Object
907 flowBuilder.setMatch(
908 MatchUtils.createVlanIdMatch(matchBuilder, new VlanId(Integer.valueOf(segmentationId)), true).build());
911 // Create the OF Actions and Instructions
912 InstructionBuilder ib = new InstructionBuilder();
913 InstructionsBuilder isb = new InstructionsBuilder();
915 // Instructions List Stores Individual Instructions
916 List<Instruction> instructions = Lists.newArrayList();
918 // Set the Output Port/Iface
919 InstructionUtils.createOutputPortInstructions(ib, dpidLong, ethPort);
921 ib.setKey(new InstructionKey(1));
922 instructions.add(ib.build());
924 // Add InstructionBuilder to the Instruction(s)Builder List
925 isb.setInstruction(instructions);
927 // Add InstructionsBuilder to FlowBuilder
928 flowBuilder.setInstructions(isb.build());
931 String flowId = "VlanMiss_"+segmentationId;
932 // Add Flow Attributes
933 flowBuilder.setId(new FlowId(flowId));
934 FlowKey key = new FlowKey(new FlowId(flowId));
935 flowBuilder.setStrict(true);
936 flowBuilder.setBarrier(false);
937 flowBuilder.setTableId(getTable());
938 flowBuilder.setKey(key);
939 flowBuilder.setPriority(8192);
940 flowBuilder.setFlowName(flowId);
941 flowBuilder.setHardTimeout(0);
942 flowBuilder.setIdleTimeout(0);
944 writeFlow(flowBuilder, nodeBuilder);
946 removeFlow(flowBuilder, nodeBuilder);
951 * Create Output Port Group Instruction
953 * @param ib Map InstructionBuilder without any instructions
954 * @param dpidLong Long the datapath ID of a switch/node
955 * @param port Long representing a port on a switch/node
956 * @return ib InstructionBuilder Map with instructions
958 protected InstructionBuilder createOutputPortInstructions(InstructionBuilder ib,
959 Long dpidLong, Long port ,
960 List<Instruction> instructions) {
961 NodeConnectorId ncid = new NodeConnectorId(OPENFLOW + dpidLong + ":" + port);
962 logger.debug("createOutputPortInstructions() Node Connector ID is - Type=openflow: DPID={} port={} existingInstructions={}", dpidLong, port, instructions);
964 List<Action> actionList = Lists.newArrayList();
965 ActionBuilder ab = new ActionBuilder();
967 List<Action> existingActions;
968 if (instructions != null && instructions.size() > 0) {
970 * First instruction is the one containing the output ports.
971 * So, only extract the actions from that.
973 Instruction in = instructions.get(0);
974 if (in.getInstruction() instanceof ApplyActionsCase) {
975 existingActions = (((ApplyActionsCase) in.getInstruction()).getApplyActions().getAction());
976 // Only include output actions
977 for (Action action : existingActions)
978 if (action.getAction() instanceof OutputActionCase)
979 actionList.add(action);
982 /* Create output action for this port*/
983 OutputActionBuilder oab = new OutputActionBuilder();
984 oab.setOutputNodeConnector(ncid);
985 ab.setAction(new OutputActionCaseBuilder().setOutputAction(oab.build()).build());
986 boolean addNew = true;
988 /* Find the group action and get the group */
989 for (Action action : actionList) {
990 OutputActionCase opAction = (OutputActionCase)action.getAction();
991 /* If output port action already in the action list of one of the buckets, skip */
992 if (opAction.getOutputAction().getOutputNodeConnector().equals(new Uri(ncid))) {
998 ab.setOrder(actionList.size());
999 ab.setKey(new ActionKey(actionList.size()));
1000 actionList.add(ab.build());
1002 // Create an Apply Action
1003 ApplyActionsBuilder aab = new ApplyActionsBuilder();
1004 aab.setAction(actionList);
1005 ib.setInstruction(new ApplyActionsCaseBuilder().setApplyActions(aab.build()).build());
1006 logger.debug("createOutputPortInstructions() : applyAction {}", aab.build());