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