blob: eb314573de888f54c7ad6e99ec86442de7a02ed7 [file] [log] [blame]
Sho SHIMIZUf7b693e2014-08-15 16:17:13 -07001package net.onrc.onos.core.newintent;
2
3import net.onrc.onos.api.flowmanager.FlowIdGenerator;
4import net.onrc.onos.api.flowmanager.SingleDstTreeFlow;
5import net.onrc.onos.api.flowmanager.Tree;
6import net.onrc.onos.api.newintent.Intent;
7import net.onrc.onos.api.newintent.IntentIdGenerator;
8import net.onrc.onos.api.newintent.MultiPointToSinglePointIntent;
9import net.onrc.onos.core.intent.ConstrainedBFSTree;
10import net.onrc.onos.core.intent.Path;
11import net.onrc.onos.core.matchaction.match.Match;
12import net.onrc.onos.core.matchaction.match.PacketMatch;
13import net.onrc.onos.core.topology.BaseTopology;
14import net.onrc.onos.core.topology.ITopologyService;
15import net.onrc.onos.core.topology.Switch;
16import net.onrc.onos.core.util.SwitchPort;
17
18import java.util.Arrays;
19import java.util.List;
20import java.util.Set;
21
22import static com.google.common.base.Preconditions.checkNotNull;
23import static net.onrc.onos.core.newintent.PointToPointIntentCompiler.convertPath;
24
25/**
26 * An intent compiler for {@link MultiPointToSinglePointIntent}.
27 */
28public class MultiPointToSinglePointIntentCompiler
29 extends AbstractFlowGeneratingIntentCompiler<MultiPointToSinglePointIntent> {
30
31 private final ITopologyService topologyService;
32
33 /**
34 * Constructs an intent compiler for {@link MultiPointToSinglePointIntent}.
35 *
36 * @param intentIdGenerator intent ID generator
37 * @param flowIdGenerator flow ID generator
38 * @param topologyService topology service
39 */
40 public MultiPointToSinglePointIntentCompiler(IntentIdGenerator intentIdGenerator,
41 FlowIdGenerator flowIdGenerator,
42 ITopologyService topologyService) {
43 super(intentIdGenerator, flowIdGenerator);
44 this.topologyService = checkNotNull(topologyService);
45 }
46
47 @Override
48 public List<Intent> compile(MultiPointToSinglePointIntent intent) {
49 Match match = intent.getMatch();
50 if (!(match instanceof PacketMatch)) {
51 throw new IntentCompilationException(
52 "intent has unsupported type of match object: " + match
53 );
54 }
55
56 SingleDstTreeFlow treeFlow = new SingleDstTreeFlow(
57 getNextFlowId(),
58 (PacketMatch) intent.getMatch(), // down-cast, but it is safe due to the guard above
59 intent.getIngressPorts(),
60 calculateTree(intent.getIngressPorts(), intent.getEgressPort()),
61 packActions(intent, intent.getEgressPort())
62 );
63 Intent compiled = new SingleDstTreeFlowIntent(getNextId(), treeFlow);
64 return Arrays.asList(compiled);
65 }
66
67 /**
68 * Calculates a tree with the specified ingress ports and egress port.
69 *
70 * {@link PathNotFoundException} is thrown when no tree found or
71 * the specified egress port is not found in the topology.
72 *
73 * @param ingressPorts ingress ports
74 * @param egressPort egress port
75 * @return tree
76 * @throws PathNotFoundException if the specified egress switch is not
77 * found or no tree is found.
78 */
79 private Tree calculateTree(Set<SwitchPort> ingressPorts, SwitchPort egressPort) {
80 BaseTopology topology = topologyService.getTopology();
81 Switch egressSwitch = topology.getSwitch(egressPort.getDpid());
82 if (egressSwitch == null) {
83 throw new PathNotFoundException("destination switch not found: " + egressPort.getDpid());
84 }
85
86 ConstrainedBFSTree bfs = new ConstrainedBFSTree(egressSwitch);
87 Tree tree = new Tree();
88
89 for (SwitchPort ingressPort: ingressPorts) {
90 Switch ingressSwitch = topology.getSwitch(ingressPort.getDpid());
91 if (ingressSwitch == null) {
92 continue;
93 }
94
95 Path path = bfs.getPath(ingressSwitch);
96 if (path.isEmpty()) {
97 continue;
98 }
99
100 tree.addAll(convertPath(path));
101 }
102
103 if (tree.isEmpty()) {
104 throw new PathNotFoundException(
105 String.format("No tree found (ingress: %s, egress: %s", ingressPorts, egressPort)
106 );
107 }
108
109 return tree;
110 }
111}