Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
28 changed files
with
1757 additions
and
25 deletions
apps/optical/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
4 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
5 | + <modelVersion>4.0.0</modelVersion> | ||
6 | + | ||
7 | + <parent> | ||
8 | + <groupId>org.onlab.onos</groupId> | ||
9 | + <artifactId>onos-apps</artifactId> | ||
10 | + <version>1.0.0-SNAPSHOT</version> | ||
11 | + <relativePath>../pom.xml</relativePath> | ||
12 | + </parent> | ||
13 | + | ||
14 | + <artifactId>onos-app-optical</artifactId> | ||
15 | + <packaging>bundle</packaging> | ||
16 | + | ||
17 | + <description>ONOS application for packet/optical deployments</description> | ||
18 | + | ||
19 | + <dependencies> | ||
20 | + | ||
21 | + <dependency> | ||
22 | + <groupId>org.onlab.onos</groupId> | ||
23 | + <artifactId>onos-cli</artifactId> | ||
24 | + <version>${project.version}</version> | ||
25 | + </dependency> | ||
26 | + <dependency> | ||
27 | + <groupId>org.apache.karaf.shell</groupId> | ||
28 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
29 | + </dependency> | ||
30 | + | ||
31 | + <dependency> | ||
32 | + <groupId>org.codehaus.jackson</groupId> | ||
33 | + <artifactId>jackson-core-asl</artifactId> | ||
34 | + </dependency> | ||
35 | + <dependency> | ||
36 | + <groupId>org.codehaus.jackson</groupId> | ||
37 | + <artifactId>jackson-mapper-asl</artifactId> | ||
38 | + </dependency> | ||
39 | + <dependency> | ||
40 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
41 | + <artifactId>jackson-annotations</artifactId> | ||
42 | + <scope>provided</scope> | ||
43 | + </dependency> | ||
44 | + | ||
45 | + </dependencies> | ||
46 | + | ||
47 | +</project> |
This diff is collapsed. Click to expand it.
1 | +package org.onlab.onos.optical.cfg; | ||
2 | + | ||
3 | +import java.util.Map; | ||
4 | +import org.codehaus.jackson.JsonNode; | ||
5 | +import org.onlab.util.HexString; | ||
6 | + | ||
7 | +/** | ||
8 | + * Public class corresponding to JSON described data model. | ||
9 | + */ | ||
10 | +public class OpticalLinkDescription { | ||
11 | + protected String type; | ||
12 | + protected Boolean allowed; | ||
13 | + protected long dpid1; | ||
14 | + protected long dpid2; | ||
15 | + protected String nodeDpid1; | ||
16 | + protected String nodeDpid2; | ||
17 | + protected Map<String, JsonNode> params; | ||
18 | + protected Map<String, String> publishAttributes; | ||
19 | + | ||
20 | + public String getType() { | ||
21 | + return type; | ||
22 | + } | ||
23 | + | ||
24 | + public void setType(String type) { | ||
25 | + this.type = type; | ||
26 | + } | ||
27 | + | ||
28 | + public Boolean isAllowed() { | ||
29 | + return allowed; | ||
30 | + } | ||
31 | + | ||
32 | + public void setAllowed(Boolean allowed) { | ||
33 | + this.allowed = allowed; | ||
34 | + } | ||
35 | + | ||
36 | + public String getNodeDpid1() { | ||
37 | + return nodeDpid1; | ||
38 | + } | ||
39 | + | ||
40 | + public void setNodeDpid1(String nodeDpid1) { | ||
41 | + this.nodeDpid1 = nodeDpid1; | ||
42 | + this.dpid1 = HexString.toLong(nodeDpid1); | ||
43 | + } | ||
44 | + | ||
45 | + public String getNodeDpid2() { | ||
46 | + return nodeDpid2; | ||
47 | + } | ||
48 | + | ||
49 | + public void setNodeDpid2(String nodeDpid2) { | ||
50 | + this.nodeDpid2 = nodeDpid2; | ||
51 | + this.dpid2 = HexString.toLong(nodeDpid2); | ||
52 | + } | ||
53 | + | ||
54 | + public long getDpid1() { | ||
55 | + return dpid1; | ||
56 | + } | ||
57 | + | ||
58 | + public void setDpid1(long dpid1) { | ||
59 | + this.dpid1 = dpid1; | ||
60 | + this.nodeDpid1 = HexString.toHexString(dpid1); | ||
61 | + } | ||
62 | + | ||
63 | + public long getDpid2() { | ||
64 | + return dpid2; | ||
65 | + } | ||
66 | + | ||
67 | + public void setDpid2(long dpid2) { | ||
68 | + this.dpid2 = dpid2; | ||
69 | + this.nodeDpid2 = HexString.toHexString(dpid2); | ||
70 | + } | ||
71 | + | ||
72 | + public Map<String, JsonNode> getParams() { | ||
73 | + return params; | ||
74 | + } | ||
75 | + | ||
76 | + public void setParams(Map<String, JsonNode> params) { | ||
77 | + this.params = params; | ||
78 | + } | ||
79 | + | ||
80 | + public Map<String, String> getPublishAttributes() { | ||
81 | + return publishAttributes; | ||
82 | + } | ||
83 | + | ||
84 | + public void setPublishAttributes(Map<String, String> publishAttributes) { | ||
85 | + this.publishAttributes = publishAttributes; | ||
86 | + } | ||
87 | + | ||
88 | +} | ||
89 | + |
1 | +package org.onlab.onos.optical.cfg; | ||
2 | + | ||
3 | +import java.util.ArrayList; | ||
4 | +import java.util.List; | ||
5 | + | ||
6 | +import org.slf4j.Logger; | ||
7 | +import org.slf4j.LoggerFactory; | ||
8 | + | ||
9 | +/** | ||
10 | + * Public class corresponding to JSON described data model. | ||
11 | + */ | ||
12 | +public class OpticalNetworkConfig { | ||
13 | + protected static final Logger log = LoggerFactory.getLogger(OpticalNetworkConfig.class); | ||
14 | + | ||
15 | + private List<OpticalSwitchDescription> opticalSwitches; | ||
16 | + private List<OpticalLinkDescription> opticalLinks; | ||
17 | + | ||
18 | + public OpticalNetworkConfig() { | ||
19 | + opticalSwitches = new ArrayList<OpticalSwitchDescription>(); | ||
20 | + opticalLinks = new ArrayList<OpticalLinkDescription>(); | ||
21 | + } | ||
22 | + | ||
23 | + public List<OpticalSwitchDescription> getOpticalSwitches() { | ||
24 | + return opticalSwitches; | ||
25 | + } | ||
26 | + | ||
27 | + public void setOpticalSwitches(List<OpticalSwitchDescription> switches) { | ||
28 | + this.opticalSwitches = switches; | ||
29 | + } | ||
30 | + | ||
31 | + public List<OpticalLinkDescription> getOpticalLinks() { | ||
32 | + return opticalLinks; | ||
33 | + } | ||
34 | + | ||
35 | + public void setOpticalLinks(List<OpticalLinkDescription> links) { | ||
36 | + this.opticalLinks = links; | ||
37 | + } | ||
38 | + | ||
39 | +} | ||
40 | + |
1 | +package org.onlab.onos.optical.cfg; | ||
2 | + | ||
3 | +import java.util.Map; | ||
4 | +import org.codehaus.jackson.JsonNode; | ||
5 | +import org.codehaus.jackson.annotate.JsonProperty; | ||
6 | +import org.onlab.util.HexString; | ||
7 | + | ||
8 | +/** | ||
9 | + * Public class corresponding to JSON described data model. | ||
10 | + */ | ||
11 | +public class OpticalSwitchDescription { | ||
12 | + protected String name; | ||
13 | + protected long dpid; | ||
14 | + protected String nodeDpid; | ||
15 | + protected String type; | ||
16 | + protected double latitude; | ||
17 | + protected double longitude; | ||
18 | + protected boolean allowed; | ||
19 | + protected Map<String, JsonNode> params; | ||
20 | + protected Map<String, String> publishAttributes; | ||
21 | + | ||
22 | + public String getName() { | ||
23 | + return name; | ||
24 | + } | ||
25 | + @JsonProperty("name") | ||
26 | + public void setName(String name) { | ||
27 | + this.name = name; | ||
28 | + } | ||
29 | + | ||
30 | + public long getDpid() { | ||
31 | + return dpid; | ||
32 | + } | ||
33 | + @JsonProperty("dpid") | ||
34 | + public void setDpid(long dpid) { | ||
35 | + this.dpid = dpid; | ||
36 | + this.nodeDpid = HexString.toHexString(dpid); | ||
37 | + } | ||
38 | + | ||
39 | + public String getNodeDpid() { | ||
40 | + return nodeDpid; | ||
41 | + } | ||
42 | + | ||
43 | + public String getHexDpid() { | ||
44 | + return nodeDpid; | ||
45 | + } | ||
46 | + | ||
47 | + public void setNodeDpid(String nodeDpid) { | ||
48 | + this.nodeDpid = nodeDpid; | ||
49 | + this.dpid = HexString.toLong(nodeDpid); | ||
50 | + } | ||
51 | + | ||
52 | + public String getType() { | ||
53 | + return type; | ||
54 | + } | ||
55 | + | ||
56 | + public void setType(String type) { | ||
57 | + this.type = type; | ||
58 | + } | ||
59 | + | ||
60 | + public double getLatitude() { | ||
61 | + return latitude; | ||
62 | + } | ||
63 | + | ||
64 | + public void setLatitude(double latitude) { | ||
65 | + this.latitude = latitude; | ||
66 | + } | ||
67 | + | ||
68 | + public double getLongitude() { | ||
69 | + return longitude; | ||
70 | + } | ||
71 | + | ||
72 | + public void setLongitude(double longitude) { | ||
73 | + this.longitude = longitude; | ||
74 | + } | ||
75 | + | ||
76 | + public boolean isAllowed() { | ||
77 | + return allowed; | ||
78 | + } | ||
79 | + | ||
80 | + public void setAllowed(boolean allowed) { | ||
81 | + this.allowed = allowed; | ||
82 | + } | ||
83 | + | ||
84 | + public Map<String, JsonNode> getParams() { | ||
85 | + return params; | ||
86 | + } | ||
87 | + | ||
88 | + public void setParams(Map<String, JsonNode> params) { | ||
89 | + this.params = params; | ||
90 | + } | ||
91 | + | ||
92 | + public Map<String, String> getPublishAttributes() { | ||
93 | + return publishAttributes; | ||
94 | + } | ||
95 | + | ||
96 | + public void setPublishAttributes(Map<String, String> publishAttributes) { | ||
97 | + this.publishAttributes = publishAttributes; | ||
98 | + } | ||
99 | + | ||
100 | +} |
1 | +package org.onlab.onos.optical.cfg; | ||
2 | + | ||
3 | +/** | ||
4 | + * Packet-optical link Java data object. | ||
5 | + */ | ||
6 | +class PktOptLink { | ||
7 | + private String srcNodeName; | ||
8 | + private String snkNodeName; | ||
9 | + private String srcNodeId; | ||
10 | + private String snkNodeId; | ||
11 | + private int srcPort; | ||
12 | + private int snkPort; | ||
13 | + private double bandwidth; | ||
14 | + private double cost; | ||
15 | + private long adminWeight; | ||
16 | + | ||
17 | + public PktOptLink(String srcName, String snkName) { | ||
18 | + this.srcNodeName = srcName; | ||
19 | + this.snkNodeName = snkName; | ||
20 | + } | ||
21 | + | ||
22 | + public PktOptLink() { | ||
23 | + // TODO Auto-generated constructor stub | ||
24 | + } | ||
25 | + | ||
26 | + public void setSrcNodeName(String name) { | ||
27 | + this.srcNodeName = name; | ||
28 | + } | ||
29 | + | ||
30 | + public String getSrcNodeName() { | ||
31 | + return this.srcNodeName; | ||
32 | + } | ||
33 | + | ||
34 | + public void setSnkNodeName(String name) { | ||
35 | + this.snkNodeName = name; | ||
36 | + } | ||
37 | + | ||
38 | + public String getSnkNodeName() { | ||
39 | + return this.snkNodeName; | ||
40 | + } | ||
41 | + | ||
42 | + public void setSrcNodeId(String nodeId) { | ||
43 | + this.srcNodeId = nodeId; | ||
44 | + } | ||
45 | + | ||
46 | + public String getSrcNodeId() { | ||
47 | + return this.srcNodeId; | ||
48 | + } | ||
49 | + | ||
50 | + public void setSnkNodeId(String nodeId) { | ||
51 | + this.snkNodeId = nodeId; | ||
52 | + } | ||
53 | + | ||
54 | + public String getSnkNodeId() { | ||
55 | + return this.snkNodeId; | ||
56 | + } | ||
57 | + | ||
58 | + public void setSrcPort(int port) { | ||
59 | + this.srcPort = port; | ||
60 | + } | ||
61 | + | ||
62 | + public int getSrcPort() { | ||
63 | + return this.srcPort; | ||
64 | + } | ||
65 | + | ||
66 | + public void setSnkPort(int port) { | ||
67 | + this.snkPort = port; | ||
68 | + } | ||
69 | + | ||
70 | + public int getSnkPort() { | ||
71 | + return this.snkPort; | ||
72 | + } | ||
73 | + | ||
74 | + public void setBandwdith(double x) { | ||
75 | + this.bandwidth = x; | ||
76 | + } | ||
77 | + | ||
78 | + public double getBandwidth() { | ||
79 | + return this.bandwidth; | ||
80 | + } | ||
81 | + | ||
82 | + public void setCost(double x) { | ||
83 | + this.cost = x; | ||
84 | + } | ||
85 | + | ||
86 | + public double getCost() { | ||
87 | + return this.cost; | ||
88 | + } | ||
89 | + | ||
90 | + public void setAdminWeight(long x) { | ||
91 | + this.adminWeight = x; | ||
92 | + } | ||
93 | + | ||
94 | + public long getAdminWeight() { | ||
95 | + return this.adminWeight; | ||
96 | + } | ||
97 | + | ||
98 | + @Override | ||
99 | + public String toString() { | ||
100 | + return new StringBuilder(" srcNodeName: ").append(this.srcNodeName) | ||
101 | + .append(" snkNodeName: ").append(this.snkNodeName) | ||
102 | + .append(" srcNodeId: ").append(this.srcNodeId) | ||
103 | + .append(" snkNodeId: ").append(this.snkNodeId) | ||
104 | + .append(" srcPort: ").append(this.srcPort) | ||
105 | + .append(" snkPort: ").append(this.snkPort) | ||
106 | + .append(" bandwidth: ").append(this.bandwidth) | ||
107 | + .append(" cost: ").append(this.cost) | ||
108 | + .append(" adminWeight: ").append(this.adminWeight).toString(); | ||
109 | + } | ||
110 | +} |
1 | +package org.onlab.onos.optical.cfg; | ||
2 | + | ||
3 | +/** | ||
4 | + * ROADM java data object converted from a JSON file. | ||
5 | + */ | ||
6 | +class Roadm { | ||
7 | + private String name; | ||
8 | + private String nodeID; | ||
9 | + private double longtitude; | ||
10 | + private double latitude; | ||
11 | + private int regenNum; | ||
12 | + | ||
13 | + //TODO use the following attributes when needed for configurations | ||
14 | + private int tPort10G; | ||
15 | + private int tPort40G; | ||
16 | + private int tPort100G; | ||
17 | + private int wPort; | ||
18 | + | ||
19 | + public Roadm() { | ||
20 | + } | ||
21 | + | ||
22 | + public Roadm(String name) { | ||
23 | + this.name = name; | ||
24 | + } | ||
25 | + | ||
26 | + public void setName(String name) { | ||
27 | + this.name = name; | ||
28 | + } | ||
29 | + | ||
30 | + public String getName() { | ||
31 | + return this.name; | ||
32 | + } | ||
33 | + | ||
34 | + public void setNodeId(String nameId) { | ||
35 | + this.nodeID = nameId; | ||
36 | + } | ||
37 | + | ||
38 | + public String getNodeId() { | ||
39 | + return this.nodeID; | ||
40 | + } | ||
41 | + | ||
42 | + public void setLongtitude(double x) { | ||
43 | + this.longtitude = x; | ||
44 | + } | ||
45 | + | ||
46 | + public double getLongtitude() { | ||
47 | + return this.longtitude; | ||
48 | + } | ||
49 | + | ||
50 | + public void setLatitude(double y) { | ||
51 | + this.latitude = y; | ||
52 | + } | ||
53 | + | ||
54 | + public double getLatitude() { | ||
55 | + return this.latitude; | ||
56 | + } | ||
57 | + | ||
58 | + public void setRegenNum(int num) { | ||
59 | + this.regenNum = num; | ||
60 | + } | ||
61 | + public int getRegenNum() { | ||
62 | + return this.regenNum; | ||
63 | + } | ||
64 | + | ||
65 | + public void setTport10GNum(int num) { | ||
66 | + this.tPort10G = num; | ||
67 | + } | ||
68 | + public int getTport10GNum() { | ||
69 | + return this.tPort10G; | ||
70 | + } | ||
71 | + | ||
72 | + public void setTport40GNum(int num) { | ||
73 | + this.tPort40G = num; | ||
74 | + } | ||
75 | + public int getTport40GNum() { | ||
76 | + return this.tPort40G; | ||
77 | + } | ||
78 | + | ||
79 | + public void setTport100GNum(int num) { | ||
80 | + this.tPort100G = num; | ||
81 | + } | ||
82 | + public int getTport100GNum() { | ||
83 | + return this.tPort100G; | ||
84 | + } | ||
85 | + | ||
86 | + public void setWportNum(int num) { | ||
87 | + this.wPort = num; | ||
88 | + } | ||
89 | + public int getWportNum() { | ||
90 | + return this.wPort; | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + public String toString() { | ||
95 | + return new StringBuilder(" ROADM Name: ").append(this.name) | ||
96 | + .append(" nodeID: ").append(this.nodeID) | ||
97 | + .append(" longtitude: ").append(this.longtitude) | ||
98 | + .append(" latitude: ").append(this.latitude) | ||
99 | + .append(" regenNum: ").append(this.regenNum) | ||
100 | + .append(" 10GTportNum: ").append(this.tPort10G) | ||
101 | + .append(" 40GTportNum: ").append(this.tPort40G) | ||
102 | + .append(" 100GTportNum: ").append(this.tPort100G) | ||
103 | + .append(" WportNum: ").append(this.wPort).toString(); | ||
104 | + } | ||
105 | +} | ||
106 | + |
1 | +package org.onlab.onos.optical.cfg; | ||
2 | + | ||
3 | +/** | ||
4 | + * WDM Link Java data object converted from a JSON file. | ||
5 | + */ | ||
6 | +class WdmLink { | ||
7 | + private String srcNodeName; | ||
8 | + private String snkNodeName; | ||
9 | + private String srcNodeId; | ||
10 | + private String snkNodeId; | ||
11 | + private int srcPort; | ||
12 | + private int snkPort; | ||
13 | + private double distance; | ||
14 | + private double cost; | ||
15 | + private int wavelengthNumber; | ||
16 | + private long adminWeight; | ||
17 | + | ||
18 | + public WdmLink(String name1, String name2) { | ||
19 | + this.srcNodeName = name1; | ||
20 | + this.snkNodeName = name2; | ||
21 | + } | ||
22 | + | ||
23 | + public WdmLink() { | ||
24 | + // TODO Auto-generated constructor stub | ||
25 | + } | ||
26 | + | ||
27 | + public void setSrcNodeName(String name) { | ||
28 | + this.srcNodeName = name; | ||
29 | + } | ||
30 | + | ||
31 | + public String getSrcNodeName() { | ||
32 | + return this.srcNodeName; | ||
33 | + } | ||
34 | + | ||
35 | + public void setSnkNodeName(String name) { | ||
36 | + this.snkNodeName = name; | ||
37 | + } | ||
38 | + | ||
39 | + public String getSnkNodeName() { | ||
40 | + return this.snkNodeName; | ||
41 | + } | ||
42 | + | ||
43 | + public void setSrcNodeId(String nodeId) { | ||
44 | + this.srcNodeId = nodeId; | ||
45 | + } | ||
46 | + | ||
47 | + public String getSrcNodeId() { | ||
48 | + return this.srcNodeId; | ||
49 | + } | ||
50 | + | ||
51 | + public void setSnkNodeId(String nodeId) { | ||
52 | + this.snkNodeId = nodeId; | ||
53 | + } | ||
54 | + | ||
55 | + public String getSnkNodeId() { | ||
56 | + return this.snkNodeId; | ||
57 | + } | ||
58 | + | ||
59 | + public void setSrcPort(int port) { | ||
60 | + this.srcPort = port; | ||
61 | + } | ||
62 | + | ||
63 | + public int getSrcPort() { | ||
64 | + return this.srcPort; | ||
65 | + } | ||
66 | + | ||
67 | + public void setSnkPort(int port) { | ||
68 | + this.snkPort = port; | ||
69 | + } | ||
70 | + | ||
71 | + public int getSnkPort() { | ||
72 | + return this.snkPort; | ||
73 | + } | ||
74 | + | ||
75 | + public void setDistance(double x) { | ||
76 | + this.distance = x; | ||
77 | + } | ||
78 | + | ||
79 | + public double getDistance() { | ||
80 | + return this.distance; | ||
81 | + } | ||
82 | + | ||
83 | + public void setCost(double x) { | ||
84 | + this.cost = x; | ||
85 | + } | ||
86 | + | ||
87 | + public double getCost() { | ||
88 | + return this.cost; | ||
89 | + } | ||
90 | + | ||
91 | + public void setWavelengthNumber(int x) { | ||
92 | + this.wavelengthNumber = x; | ||
93 | + } | ||
94 | + | ||
95 | + public int getWavelengthNumber() { | ||
96 | + return this.wavelengthNumber; | ||
97 | + } | ||
98 | + | ||
99 | + public void setAdminWeight(long x) { | ||
100 | + this.adminWeight = x; | ||
101 | + } | ||
102 | + | ||
103 | + public long getAdminWeight() { | ||
104 | + return this.adminWeight; | ||
105 | + } | ||
106 | + | ||
107 | + @Override | ||
108 | + public String toString() { | ||
109 | + return new StringBuilder(" srcNodeName: ").append(this.srcNodeName) | ||
110 | + .append(" snkNodeName: ").append(this.snkNodeName) | ||
111 | + .append(" srcNodeId: ").append(this.srcNodeId) | ||
112 | + .append(" snkNodeId: ").append(this.snkNodeId) | ||
113 | + .append(" srcPort: ").append(this.srcPort) | ||
114 | + .append(" snkPort: ").append(this.snkPort) | ||
115 | + .append(" distance: ").append(this.distance) | ||
116 | + .append(" cost: ").append(this.cost) | ||
117 | + .append(" wavelengthNumber: ").append(this.wavelengthNumber) | ||
118 | + .append(" adminWeight: ").append(this.adminWeight).toString(); | ||
119 | + } | ||
120 | +} | ||
121 | + |
1 | +{ | ||
2 | + "opticalSwitches": [ | ||
3 | + { | ||
4 | + "allowed": true, | ||
5 | + "latitude": 37.6, | ||
6 | + "longitude": 122.3, | ||
7 | + "name": "SFO-W10", | ||
8 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:01", | ||
9 | + "params": { | ||
10 | + "numRegen": 0 | ||
11 | + }, | ||
12 | + "type": "Roadm" | ||
13 | + }, | ||
14 | + | ||
15 | + { | ||
16 | + "allowed": true, | ||
17 | + "latitude": 37.3, | ||
18 | + "longitude": 121.9, | ||
19 | + "name": "SJC-W10", | ||
20 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:02", | ||
21 | + "params": { | ||
22 | + "numRegen": 0 | ||
23 | + }, | ||
24 | + "type": "Roadm" | ||
25 | + }, | ||
26 | + | ||
27 | + { | ||
28 | + "allowed": true, | ||
29 | + "latitude": 33.9, | ||
30 | + "longitude": 118.4 | ||
31 | + "name": "LAX-W10", | ||
32 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:03", | ||
33 | + "params": { | ||
34 | + "numRegen": 0 | ||
35 | + }, | ||
36 | + "type": "Roadm" | ||
37 | + }, | ||
38 | + | ||
39 | + { | ||
40 | + "allowed": true, | ||
41 | + "latitude": 32.8, | ||
42 | + "longitude": 117.1, | ||
43 | + "name": "SDG-W10", | ||
44 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:04", | ||
45 | + "params": { | ||
46 | + "numRegen": 3 | ||
47 | + }, | ||
48 | + "type": "Roadm" | ||
49 | + }, | ||
50 | + | ||
51 | + { | ||
52 | + "allowed": true, | ||
53 | + "latitude": 44.8, | ||
54 | + "longitude": 93.1, | ||
55 | + "name": "MSP-M10", | ||
56 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:05", | ||
57 | + "params": { | ||
58 | + "numRegen": 3 | ||
59 | + }, | ||
60 | + "type": "Roadm" | ||
61 | + }, | ||
62 | + | ||
63 | + { | ||
64 | + "allowed": true, | ||
65 | + "latitude": 32.8, | ||
66 | + "longitude": 97.1, | ||
67 | + "name": "DFW-M10", | ||
68 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:06", | ||
69 | + "params": { | ||
70 | + "numRegen": 3 | ||
71 | + }, | ||
72 | + "type": "Roadm" | ||
73 | + }, | ||
74 | + | ||
75 | + { | ||
76 | + "allowed": true, | ||
77 | + "latitude": 41.8, | ||
78 | + "longitude": 120.1, | ||
79 | + "name": "CHG-N10", | ||
80 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:07", | ||
81 | + "params": { | ||
82 | + "numRegen": 3 | ||
83 | + }, | ||
84 | + "type": "Roadm" | ||
85 | + }, | ||
86 | + | ||
87 | + { | ||
88 | + "allowed": true, | ||
89 | + "latitude": 38.8, | ||
90 | + "longitude": 77.1, | ||
91 | + "name": "IAD-M10", | ||
92 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:08", | ||
93 | + "params": { | ||
94 | + "numRegen": 3 | ||
95 | + }, | ||
96 | + "type": "Roadm" | ||
97 | + }, | ||
98 | + | ||
99 | + { | ||
100 | + "allowed": true, | ||
101 | + "latitude": 40.8, | ||
102 | + "longitude": 73.1, | ||
103 | + "name": "JFK-E10", | ||
104 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:09", | ||
105 | + "params": { | ||
106 | + "numRegen": 0 | ||
107 | + }, | ||
108 | + "type": "Roadm" | ||
109 | + | ||
110 | + }, | ||
111 | + | ||
112 | + { | ||
113 | + "allowed": true, | ||
114 | + "latitude": 33.8, | ||
115 | + "longitude": 84.1, | ||
116 | + "name": "ATL-S10", | ||
117 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:0A", | ||
118 | + "params": { | ||
119 | + "numRegen": 0 | ||
120 | + }, | ||
121 | + "type": "Roadm" | ||
122 | + } | ||
123 | + | ||
124 | + ], | ||
125 | + | ||
126 | + "opticalLinks": [ | ||
127 | + { | ||
128 | + "allowed": true, | ||
129 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:01", | ||
130 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:02", | ||
131 | + "params": { | ||
132 | + "distKms": 1000, | ||
133 | + "nodeName1": "SFO-W10", | ||
134 | + "nodeName2": "SJC-W10", | ||
135 | + "numWaves": 80, | ||
136 | + "port1": 10, | ||
137 | + "port2": 10 | ||
138 | + }, | ||
139 | + "type": "wdmLink" | ||
140 | + }, | ||
141 | + | ||
142 | + { | ||
143 | + "allowed": true, | ||
144 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:02", | ||
145 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:03", | ||
146 | + "params": { | ||
147 | + "distKms": 1000, | ||
148 | + "nodeName1": "SJC-W10", | ||
149 | + "nodeName2": "LAX-W10", | ||
150 | + "numWaves": 80, | ||
151 | + "port1": 20, | ||
152 | + "port2": 10 | ||
153 | + }, | ||
154 | + "type": "wdmLink" | ||
155 | + }, | ||
156 | + | ||
157 | + { | ||
158 | + "allowed": true, | ||
159 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:03", | ||
160 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:04", | ||
161 | + "params": { | ||
162 | + "distKms": 1000, | ||
163 | + "nodeName1": "LAX-W10", | ||
164 | + "nodeName2": "SDG-W10", | ||
165 | + "numWaves": 80, | ||
166 | + "port1": 30, | ||
167 | + "port2": 10 | ||
168 | + }, | ||
169 | + "type": "wdmLink" | ||
170 | + }, | ||
171 | + | ||
172 | + { | ||
173 | + "allowed": true, | ||
174 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:02", | ||
175 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:05", | ||
176 | + "params": { | ||
177 | + "distKms": 4000, | ||
178 | + "nodeName1": "SJC-W10", | ||
179 | + "nodeName2": "MSP-M10", | ||
180 | + "numWaves": 80, | ||
181 | + "port1": 20, | ||
182 | + "port2": 10 | ||
183 | + }, | ||
184 | + "type": "wdmLink" | ||
185 | + }, | ||
186 | + | ||
187 | + { | ||
188 | + | ||
189 | + "allowed": true, | ||
190 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:03", | ||
191 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06", | ||
192 | + "params": { | ||
193 | + "distKms": 5000, | ||
194 | + "nodeName1": "LAX-W10", | ||
195 | + "nodeName2": "DFW-M10", | ||
196 | + "numWaves": 80, | ||
197 | + "port1": 20, | ||
198 | + "port2": 10 | ||
199 | + }, | ||
200 | + "type": "wdmLink" | ||
201 | + }, | ||
202 | + | ||
203 | + { | ||
204 | + "allowed": true, | ||
205 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:05", | ||
206 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:06", | ||
207 | + "params": { | ||
208 | + "distKms": 3000, | ||
209 | + "nodeName1": "MSP-M10", | ||
210 | + "nodeName2": "DFW-M10", | ||
211 | + "numWaves": 80, | ||
212 | + "port1": 30, | ||
213 | + "port2": 20 | ||
214 | + }, | ||
215 | + "type": "wdmLink" | ||
216 | + }, | ||
217 | + | ||
218 | + { | ||
219 | + "allowed": true, | ||
220 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:05", | ||
221 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:07", | ||
222 | + "params": { | ||
223 | + "distKms": 3000, | ||
224 | + "nodeName1": "MSP-M10", | ||
225 | + "nodeName2": "CHG-N10", | ||
226 | + "numWaves": 80, | ||
227 | + "port1": 20, | ||
228 | + "port2": 21 | ||
229 | + }, | ||
230 | + "type": "wdmLink" | ||
231 | + }, | ||
232 | + | ||
233 | + { | ||
234 | + | ||
235 | + "allowed": true, | ||
236 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:06", | ||
237 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:08", | ||
238 | + "params": { | ||
239 | + "distKms": 4000, | ||
240 | + "nodeName1": "DFW-M10", | ||
241 | + "nodeName2": "IAD-M10", | ||
242 | + "numWaves": 80, | ||
243 | + "port1": 30, | ||
244 | + "port2": 10 | ||
245 | + }, | ||
246 | + "type": "wdmLink" | ||
247 | + }, | ||
248 | + | ||
249 | + { | ||
250 | + | ||
251 | + "allowed": true, | ||
252 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:07", | ||
253 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:08", | ||
254 | + "params": { | ||
255 | + "distKms": 4000, | ||
256 | + "nodeName1": "CHG-M10", | ||
257 | + "nodeName2": "IAD-M10", | ||
258 | + "numWaves": 80, | ||
259 | + "port1": 30, | ||
260 | + "port2": 20 | ||
261 | + }, | ||
262 | + "type": "wdmLink" | ||
263 | + }, | ||
264 | + | ||
265 | + { | ||
266 | + "allowed": true, | ||
267 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:07", | ||
268 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:09", | ||
269 | + "params": { | ||
270 | + "distKms": 5000, | ||
271 | + "nodeName1": "CHG-M10", | ||
272 | + "nodeName2": "JFK-E10", | ||
273 | + "numWaves": 80, | ||
274 | + "port1": 20, | ||
275 | + "port2": 10 | ||
276 | + }, | ||
277 | + "type": "wdmLink" | ||
278 | + }, | ||
279 | + | ||
280 | + { | ||
281 | + "allowed": true, | ||
282 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:08", | ||
283 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A", | ||
284 | + "params": { | ||
285 | + "distKms": 3000, | ||
286 | + "nodeName1": "IAD-M10", | ||
287 | + "nodeName2": "ATL-S10", | ||
288 | + "numWaves": 80, | ||
289 | + "port1": 30, | ||
290 | + "port2": 10 | ||
291 | + }, | ||
292 | + "type": "wdmLink" | ||
293 | + }, | ||
294 | + | ||
295 | + { | ||
296 | + | ||
297 | + "allowed": true, | ||
298 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:09", | ||
299 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A", | ||
300 | + "params": { | ||
301 | + "distKms": 4000, | ||
302 | + "nodeName1": "JFK-E10", | ||
303 | + "nodeName2": "ATL-S10", | ||
304 | + "numWaves": 80, | ||
305 | + "port1": 20, | ||
306 | + "port2": 20 | ||
307 | + }, | ||
308 | + "type": "wdmLink" | ||
309 | + }, | ||
310 | + | ||
311 | + | ||
312 | + { | ||
313 | + "allowed": true, | ||
314 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:01", | ||
315 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:01", | ||
316 | + "params": { | ||
317 | + "nodeName1": "SFO-R10", | ||
318 | + "nodeName2": "SFO-W10", | ||
319 | + "port1": 10, | ||
320 | + "port2": 1 | ||
321 | + }, | ||
322 | + "type": "pktOptLink" | ||
323 | + }, | ||
324 | + | ||
325 | + { | ||
326 | + "allowed": true, | ||
327 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:03", | ||
328 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:03", | ||
329 | + "params": { | ||
330 | + "nodeName1": "LAX-R10", | ||
331 | + "nodeName2": "LAX-W10", | ||
332 | + "port1": 10, | ||
333 | + "port2": 1 | ||
334 | + }, | ||
335 | + "type": "pktOptLink" | ||
336 | + }, | ||
337 | + | ||
338 | + { | ||
339 | + "allowed": true, | ||
340 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:04", | ||
341 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:04", | ||
342 | + "params": { | ||
343 | + "nodeName1": "SDG-R10", | ||
344 | + "nodeName2": "SDG-W10", | ||
345 | + "port1": 10, | ||
346 | + "port2": 1 | ||
347 | + }, | ||
348 | + "type": "pktOptLink" | ||
349 | + }, | ||
350 | + | ||
351 | + { | ||
352 | + "allowed": true, | ||
353 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:07", | ||
354 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:07", | ||
355 | + "params": { | ||
356 | + "nodeName1": "CHG-R10", | ||
357 | + "nodeName2": "CHG-W10", | ||
358 | + "port1": 10, | ||
359 | + "port2": 1 | ||
360 | + }, | ||
361 | + "type": "pktOptLink" | ||
362 | + }, | ||
363 | + | ||
364 | + { | ||
365 | + "allowed": true, | ||
366 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:09", | ||
367 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:09", | ||
368 | + "params": { | ||
369 | + "nodeName1": "JFK-R10", | ||
370 | + "nodeName2": "JFK-W10", | ||
371 | + "port1": 10, | ||
372 | + "port2": 1 | ||
373 | + }, | ||
374 | + "type": "pktOptLink" | ||
375 | + }, | ||
376 | + | ||
377 | + { | ||
378 | + "allowed": true, | ||
379 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:0A", | ||
380 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A", | ||
381 | + "params": { | ||
382 | + "nodeName1": "ATL-R10", | ||
383 | + "nodeName2": "ATL-W10", | ||
384 | + "port1": 10, | ||
385 | + "port2": 1 | ||
386 | + }, | ||
387 | + "type": "pktOptLink" | ||
388 | + }, | ||
389 | + | ||
390 | + ] | ||
391 | +} |
1 | +{ | ||
2 | + "opticalSwitches": [ | ||
3 | + { | ||
4 | + "allowed": true, | ||
5 | + "latitude": 37.6, | ||
6 | + "longitude": 122.3, | ||
7 | + "name": "ROADM1", | ||
8 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:01", | ||
9 | + "params": { | ||
10 | + "numRegen": 0 | ||
11 | + }, | ||
12 | + "type": "Roadm" | ||
13 | + }, | ||
14 | + | ||
15 | + { | ||
16 | + "allowed": true, | ||
17 | + "latitude": 37.3, | ||
18 | + "longitude": 121.9, | ||
19 | + "name": "ROADM2", | ||
20 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:02", | ||
21 | + "params": { | ||
22 | + "numRegen": 0 | ||
23 | + }, | ||
24 | + "type": "Roadm" | ||
25 | + }, | ||
26 | + | ||
27 | + { | ||
28 | + "allowed": true, | ||
29 | + "latitude": 33.9, | ||
30 | + "longitude": 118.4, | ||
31 | + "name": "ROADM3", | ||
32 | + "nodeDpid": "00:00:ff:ff:ff:ff:ff:03", | ||
33 | + "params": { | ||
34 | + "numRegen": 2 | ||
35 | + }, | ||
36 | + "type": "Roadm" | ||
37 | + } | ||
38 | + ], | ||
39 | + | ||
40 | + "opticalLinks": [ | ||
41 | + { | ||
42 | + "allowed": true, | ||
43 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:01", | ||
44 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:03", | ||
45 | + "params": { | ||
46 | + "distKms": 1000, | ||
47 | + "nodeName1": "ROADM1", | ||
48 | + "nodeName2": "ROADM3", | ||
49 | + "numWaves": 80, | ||
50 | + "port1": 10, | ||
51 | + "port2": 30 | ||
52 | + }, | ||
53 | + "type": "wdmLink" | ||
54 | + }, | ||
55 | + | ||
56 | + { | ||
57 | + "allowed": true, | ||
58 | + "nodeDpid1": "00:00:ff:ff:ff:ff:ff:03", | ||
59 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:02", | ||
60 | + "params": { | ||
61 | + "distKms": 2000, | ||
62 | + "nodeName1": "ROADM3", | ||
63 | + "nodeName2": "ROADM2", | ||
64 | + "numWaves": 80, | ||
65 | + "port1": 31, | ||
66 | + "port2": 20 | ||
67 | + }, | ||
68 | + "type": "wdmLink" | ||
69 | + }, | ||
70 | + | ||
71 | + | ||
72 | + { | ||
73 | + "allowed": true, | ||
74 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:01", | ||
75 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:01", | ||
76 | + "params": { | ||
77 | + "nodeName1": "ROUTER1", | ||
78 | + "nodeName2": "ROADM1", | ||
79 | + "bandWidth": 100000, | ||
80 | + "port1": 10, | ||
81 | + "port2": 11 | ||
82 | + }, | ||
83 | + "type": "pktOptLink" | ||
84 | + }, | ||
85 | + | ||
86 | + { | ||
87 | + "allowed": true, | ||
88 | + "nodeDpid1": "00:00:ff:ff:ff:ff:00:02", | ||
89 | + "nodeDpid2": "00:00:ff:ff:ff:ff:ff:02", | ||
90 | + "params": { | ||
91 | + "nodeName1": "ROUTER2", | ||
92 | + "nodeName2": "ROADM2", | ||
93 | + "bandWidth": 100000, | ||
94 | + "port1": 10, | ||
95 | + "port2": 21 | ||
96 | + }, | ||
97 | + "type": "pktOptLink" | ||
98 | + } | ||
99 | + | ||
100 | + ] | ||
101 | +} |
... | @@ -26,6 +26,7 @@ | ... | @@ -26,6 +26,7 @@ |
26 | <module>config</module> | 26 | <module>config</module> |
27 | <module>sdnip</module> | 27 | <module>sdnip</module> |
28 | <module>calendar</module> | 28 | <module>calendar</module> |
29 | + <module>optical</module> | ||
29 | </modules> | 30 | </modules> |
30 | 31 | ||
31 | <properties> | 32 | <properties> | ... | ... |
... | @@ -37,6 +37,15 @@ public interface ClusterCommunicationService { | ... | @@ -37,6 +37,15 @@ public interface ClusterCommunicationService { |
37 | boolean multicast(ClusterMessage message, Set<NodeId> nodeIds) throws IOException; | 37 | boolean multicast(ClusterMessage message, Set<NodeId> nodeIds) throws IOException; |
38 | 38 | ||
39 | /** | 39 | /** |
40 | + * Sends a message synchronously. | ||
41 | + * @param message message to send | ||
42 | + * @param toNodeId recipient node identifier | ||
43 | + * @return ClusterMessageResponse which is reply future. | ||
44 | + * @throws IOException | ||
45 | + */ | ||
46 | + ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException; | ||
47 | + | ||
48 | + /** | ||
40 | * Adds a new subscriber for the specified message subject. | 49 | * Adds a new subscriber for the specified message subject. |
41 | * | 50 | * |
42 | * @param subject message subject | 51 | * @param subject message subject | ... | ... |
core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessageResponse.java
0 → 100644
1 | +package org.onlab.onos.store.cluster.messaging; | ||
2 | + | ||
3 | +import java.util.concurrent.TimeUnit; | ||
4 | +import java.util.concurrent.TimeoutException; | ||
5 | + | ||
6 | +import org.onlab.onos.cluster.NodeId; | ||
7 | + | ||
8 | +public interface ClusterMessageResponse { | ||
9 | + public NodeId sender(); | ||
10 | + public byte[] get(long timeout, TimeUnit timeunit) throws TimeoutException; | ||
11 | + public byte[] get(long timeout) throws InterruptedException; | ||
12 | +} |
... | @@ -43,7 +43,7 @@ public class PointToPointIntentCompiler | ... | @@ -43,7 +43,7 @@ public class PointToPointIntentCompiler |
43 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 43 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
44 | protected HostService hostService; | 44 | protected HostService hostService; |
45 | 45 | ||
46 | - private IdGenerator<IntentId> intentIdGenerator; | 46 | + protected IdGenerator<IntentId> intentIdGenerator; |
47 | 47 | ||
48 | @Activate | 48 | @Activate |
49 | public void activate() { | 49 | public void activate() { | ... | ... |
... | @@ -167,6 +167,7 @@ public class ProxyArpManager implements ProxyArpService { | ... | @@ -167,6 +167,7 @@ public class ProxyArpManager implements ProxyArpService { |
167 | return; | 167 | return; |
168 | } | 168 | } |
169 | 169 | ||
170 | + // TODO find the correct IP address | ||
170 | Ethernet arpReply = buildArpReply(dst.ipAddresses().iterator().next(), | 171 | Ethernet arpReply = buildArpReply(dst.ipAddresses().iterator().next(), |
171 | dst.mac(), eth); | 172 | dst.mac(), eth); |
172 | // TODO: check send status with host service. | 173 | // TODO: check send status with host service. | ... | ... |
1 | +package org.onlab.onos.net.intent; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | +import org.onlab.onos.net.ConnectPoint; | ||
5 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
6 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
7 | + | ||
8 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
9 | +import static org.hamcrest.Matchers.equalTo; | ||
10 | +import static org.hamcrest.Matchers.is; | ||
11 | +import static org.hamcrest.Matchers.not; | ||
12 | +import static org.onlab.onos.net.NetTestTools.connectPoint; | ||
13 | + | ||
14 | +/** | ||
15 | + * Unit tests for the HostToHostIntent class. | ||
16 | + */ | ||
17 | +public class TestPointToPointIntent { | ||
18 | + | ||
19 | + private TrafficSelector selector = new IntentTestsMocks.MockSelector(); | ||
20 | + private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment(); | ||
21 | + | ||
22 | + private ConnectPoint point1 = connectPoint("dev1", 1); | ||
23 | + private ConnectPoint point2 = connectPoint("dev2", 1); | ||
24 | + | ||
25 | + private PointToPointIntent makePointToPoint(long id, | ||
26 | + ConnectPoint ingress, | ||
27 | + ConnectPoint egress) { | ||
28 | + return new PointToPointIntent(new IntentId(id), | ||
29 | + selector, | ||
30 | + treatment, | ||
31 | + ingress, | ||
32 | + egress); | ||
33 | + } | ||
34 | + | ||
35 | + /** | ||
36 | + * Tests the equals() method where two PointToPointIntents have references | ||
37 | + * to the same ingress and egress points. These should compare equal. | ||
38 | + */ | ||
39 | + @Test | ||
40 | + public void testSameEquals() { | ||
41 | + PointToPointIntent i1 = makePointToPoint(12, point1, point2); | ||
42 | + PointToPointIntent i2 = makePointToPoint(12, point1, point2); | ||
43 | + | ||
44 | + assertThat(i1, is(equalTo(i2))); | ||
45 | + } | ||
46 | + | ||
47 | + /** | ||
48 | + * Tests the equals() method where two HostToHostIntents have references | ||
49 | + * to different Hosts. These should compare not equal. | ||
50 | + */ | ||
51 | + @Test | ||
52 | + public void testLinksDifferentEquals() { | ||
53 | + | ||
54 | + PointToPointIntent i1 = makePointToPoint(12, point1, point2); | ||
55 | + PointToPointIntent i2 = makePointToPoint(12, point2, point1); | ||
56 | + | ||
57 | + assertThat(i1, is(not(equalTo(i2)))); | ||
58 | + } | ||
59 | + | ||
60 | + /** | ||
61 | + * Tests the equals() method where two HostToHostIntents have different | ||
62 | + * ids. These should compare not equal. | ||
63 | + */ | ||
64 | + @Test | ||
65 | + public void testBaseDifferentEquals() { | ||
66 | + PointToPointIntent i1 = makePointToPoint(12, point1, point2); | ||
67 | + PointToPointIntent i2 = makePointToPoint(11, point1, point2); | ||
68 | + | ||
69 | + | ||
70 | + assertThat(i1, is(not(equalTo(i2)))); | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * Tests that the hashCode() values for two equivalent HostToHostIntent | ||
75 | + * objects are the same. | ||
76 | + */ | ||
77 | + @Test | ||
78 | + public void testHashCodeEquals() { | ||
79 | + PointToPointIntent i1 = makePointToPoint(12, point1, point2); | ||
80 | + PointToPointIntent i2 = makePointToPoint(12, point1, point2); | ||
81 | + | ||
82 | + assertThat(i1.hashCode(), is(equalTo(i2.hashCode()))); | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * Tests that the hashCode() values for two distinct LinkCollectionIntent | ||
87 | + * objects are different. | ||
88 | + */ | ||
89 | + @Test | ||
90 | + public void testHashCodeDifferent() { | ||
91 | + PointToPointIntent i1 = makePointToPoint(12, point1, point2); | ||
92 | + PointToPointIntent i2 = makePointToPoint(22, point1, point2); | ||
93 | + | ||
94 | + assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode())))); | ||
95 | + } | ||
96 | +} |
core/net/src/test/java/org/onlab/onos/net/intent/impl/TestPointToPointIntentCompiler.java
0 → 100644
1 | +package org.onlab.onos.net.intent.impl; | ||
2 | + | ||
3 | +import java.util.List; | ||
4 | + | ||
5 | +import org.hamcrest.Matchers; | ||
6 | +import org.junit.Test; | ||
7 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
8 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
9 | +import org.onlab.onos.net.intent.Intent; | ||
10 | +import org.onlab.onos.net.intent.IntentId; | ||
11 | +import org.onlab.onos.net.intent.IntentTestsMocks; | ||
12 | +import org.onlab.onos.net.intent.PathIntent; | ||
13 | +import org.onlab.onos.net.intent.PointToPointIntent; | ||
14 | + | ||
15 | +import static org.hamcrest.CoreMatchers.notNullValue; | ||
16 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
17 | +import static org.hamcrest.Matchers.hasSize; | ||
18 | +import static org.hamcrest.Matchers.is; | ||
19 | +import static org.onlab.onos.net.NetTestTools.connectPoint; | ||
20 | +import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath; | ||
21 | + | ||
22 | +/** | ||
23 | + * Unit tests for the HostToHost intent compiler. | ||
24 | + */ | ||
25 | +public class TestPointToPointIntentCompiler { | ||
26 | + | ||
27 | + private TrafficSelector selector = new IntentTestsMocks.MockSelector(); | ||
28 | + private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment(); | ||
29 | + | ||
30 | + /** | ||
31 | + * Creates a PointToPoint intent based on ingress and egress device Ids. | ||
32 | + * | ||
33 | + * @param ingressIdString string for id of ingress device | ||
34 | + * @param egressIdString string for id of egress device | ||
35 | + * @return PointToPointIntent for the two devices | ||
36 | + */ | ||
37 | + private PointToPointIntent makeIntent(String ingressIdString, | ||
38 | + String egressIdString) { | ||
39 | + return new PointToPointIntent(new IntentId(12), | ||
40 | + selector, | ||
41 | + treatment, | ||
42 | + connectPoint(ingressIdString, 1), | ||
43 | + connectPoint(egressIdString, 1)); | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * Creates a compiler for HostToHost intents. | ||
48 | + * | ||
49 | + * @param hops string array describing the path hops to use when compiling | ||
50 | + * @return HostToHost intent compiler | ||
51 | + */ | ||
52 | + private PointToPointIntentCompiler makeCompiler(String[] hops) { | ||
53 | + PointToPointIntentCompiler compiler = | ||
54 | + new PointToPointIntentCompiler(); | ||
55 | + compiler.pathService = new IntentTestsMocks.MockPathService(hops); | ||
56 | + IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator(); | ||
57 | + compiler.intentIdGenerator = | ||
58 | + new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator); | ||
59 | + return compiler; | ||
60 | + } | ||
61 | + | ||
62 | + | ||
63 | + /** | ||
64 | + * Tests a pair of devices in an 8 hop path, forward direction. | ||
65 | + */ | ||
66 | + @Test | ||
67 | + public void testForwardPathCompilation() { | ||
68 | + | ||
69 | + PointToPointIntent intent = makeIntent("d1", "d8"); | ||
70 | + assertThat(intent, is(notNullValue())); | ||
71 | + | ||
72 | + String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"}; | ||
73 | + PointToPointIntentCompiler compiler = makeCompiler(hops); | ||
74 | + assertThat(compiler, is(notNullValue())); | ||
75 | + | ||
76 | + List<Intent> result = compiler.compile(intent); | ||
77 | + assertThat(result, is(Matchers.notNullValue())); | ||
78 | + assertThat(result, hasSize(1)); | ||
79 | + Intent forwardResultIntent = result.get(0); | ||
80 | + assertThat(forwardResultIntent instanceof PathIntent, is(true)); | ||
81 | + | ||
82 | + if (forwardResultIntent instanceof PathIntent) { | ||
83 | + PathIntent forwardPathIntent = (PathIntent) forwardResultIntent; | ||
84 | + // 7 links for the hops, plus one default lnk on ingress and egress | ||
85 | + assertThat(forwardPathIntent.path().links(), hasSize(hops.length + 1)); | ||
86 | + assertThat(forwardPathIntent.path().links(), linksHasPath("d1", "d2")); | ||
87 | + assertThat(forwardPathIntent.path().links(), linksHasPath("d2", "d3")); | ||
88 | + assertThat(forwardPathIntent.path().links(), linksHasPath("d3", "d4")); | ||
89 | + assertThat(forwardPathIntent.path().links(), linksHasPath("d4", "d5")); | ||
90 | + assertThat(forwardPathIntent.path().links(), linksHasPath("d5", "d6")); | ||
91 | + assertThat(forwardPathIntent.path().links(), linksHasPath("d6", "d7")); | ||
92 | + assertThat(forwardPathIntent.path().links(), linksHasPath("d7", "d8")); | ||
93 | + } | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * Tests a pair of devices in an 8 hop path, forward direction. | ||
98 | + */ | ||
99 | + @Test | ||
100 | + public void testReversePathCompilation() { | ||
101 | + | ||
102 | + PointToPointIntent intent = makeIntent("d8", "d1"); | ||
103 | + assertThat(intent, is(notNullValue())); | ||
104 | + | ||
105 | + String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"}; | ||
106 | + PointToPointIntentCompiler compiler = makeCompiler(hops); | ||
107 | + assertThat(compiler, is(notNullValue())); | ||
108 | + | ||
109 | + List<Intent> result = compiler.compile(intent); | ||
110 | + assertThat(result, is(Matchers.notNullValue())); | ||
111 | + assertThat(result, hasSize(1)); | ||
112 | + Intent reverseResultIntent = result.get(0); | ||
113 | + assertThat(reverseResultIntent instanceof PathIntent, is(true)); | ||
114 | + | ||
115 | + if (reverseResultIntent instanceof PathIntent) { | ||
116 | + PathIntent reversePathIntent = (PathIntent) reverseResultIntent; | ||
117 | + assertThat(reversePathIntent.path().links(), hasSize(hops.length + 1)); | ||
118 | + assertThat(reversePathIntent.path().links(), linksHasPath("d2", "d1")); | ||
119 | + assertThat(reversePathIntent.path().links(), linksHasPath("d3", "d2")); | ||
120 | + assertThat(reversePathIntent.path().links(), linksHasPath("d4", "d3")); | ||
121 | + assertThat(reversePathIntent.path().links(), linksHasPath("d5", "d4")); | ||
122 | + assertThat(reversePathIntent.path().links(), linksHasPath("d6", "d5")); | ||
123 | + assertThat(reversePathIntent.path().links(), linksHasPath("d7", "d6")); | ||
124 | + assertThat(reversePathIntent.path().links(), linksHasPath("d8", "d7")); | ||
125 | + } | ||
126 | + } | ||
127 | +} |
... | @@ -4,6 +4,9 @@ import static com.google.common.base.Preconditions.checkArgument; | ... | @@ -4,6 +4,9 @@ import static com.google.common.base.Preconditions.checkArgument; |
4 | 4 | ||
5 | import java.io.IOException; | 5 | import java.io.IOException; |
6 | import java.util.Set; | 6 | import java.util.Set; |
7 | +import java.util.concurrent.TimeUnit; | ||
8 | +import java.util.concurrent.TimeoutException; | ||
9 | + | ||
7 | import org.apache.felix.scr.annotations.Activate; | 10 | import org.apache.felix.scr.annotations.Activate; |
8 | import org.apache.felix.scr.annotations.Component; | 11 | import org.apache.felix.scr.annotations.Component; |
9 | import org.apache.felix.scr.annotations.Deactivate; | 12 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -17,6 +20,7 @@ import org.onlab.onos.store.cluster.impl.ClusterMembershipEvent; | ... | @@ -17,6 +20,7 @@ import org.onlab.onos.store.cluster.impl.ClusterMembershipEvent; |
17 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | 20 | import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; |
18 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; | 21 | import org.onlab.onos.store.cluster.messaging.ClusterMessage; |
19 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; | 22 | import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; |
23 | +import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse; | ||
20 | import org.onlab.onos.store.cluster.messaging.MessageSubject; | 24 | import org.onlab.onos.store.cluster.messaging.MessageSubject; |
21 | import org.onlab.onos.store.serializers.ClusterMessageSerializer; | 25 | import org.onlab.onos.store.serializers.ClusterMessageSerializer; |
22 | import org.onlab.onos.store.serializers.KryoPoolUtil; | 26 | import org.onlab.onos.store.serializers.KryoPoolUtil; |
... | @@ -28,6 +32,7 @@ import org.onlab.netty.Message; | ... | @@ -28,6 +32,7 @@ import org.onlab.netty.Message; |
28 | import org.onlab.netty.MessageHandler; | 32 | import org.onlab.netty.MessageHandler; |
29 | import org.onlab.netty.MessagingService; | 33 | import org.onlab.netty.MessagingService; |
30 | import org.onlab.netty.NettyMessagingService; | 34 | import org.onlab.netty.NettyMessagingService; |
35 | +import org.onlab.netty.Response; | ||
31 | import org.slf4j.Logger; | 36 | import org.slf4j.Logger; |
32 | import org.slf4j.LoggerFactory; | 37 | import org.slf4j.LoggerFactory; |
33 | 38 | ||
... | @@ -120,6 +125,22 @@ public class ClusterCommunicationManager | ... | @@ -120,6 +125,22 @@ public class ClusterCommunicationManager |
120 | } | 125 | } |
121 | 126 | ||
122 | @Override | 127 | @Override |
128 | + public ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException { | ||
129 | + ControllerNode node = clusterService.getNode(toNodeId); | ||
130 | + checkArgument(node != null, "Unknown nodeId: %s", toNodeId); | ||
131 | + Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort()); | ||
132 | + try { | ||
133 | + Response responseFuture = | ||
134 | + messagingService.sendAndReceive(nodeEp, message.subject().value(), SERIALIZER.encode(message)); | ||
135 | + return new InternalClusterMessageResponse(toNodeId, responseFuture); | ||
136 | + | ||
137 | + } catch (IOException e) { | ||
138 | + log.error("Failed interaction with remote nodeId: " + toNodeId, e); | ||
139 | + throw e; | ||
140 | + } | ||
141 | + } | ||
142 | + | ||
143 | + @Override | ||
123 | public void addSubscriber(MessageSubject subject, | 144 | public void addSubscriber(MessageSubject subject, |
124 | ClusterMessageHandler subscriber) { | 145 | ClusterMessageHandler subscriber) { |
125 | messagingService.registerHandler(subject.value(), new InternalClusterMessageHandler(subscriber)); | 146 | messagingService.registerHandler(subject.value(), new InternalClusterMessageHandler(subscriber)); |
... | @@ -144,4 +165,30 @@ public class ClusterCommunicationManager | ... | @@ -144,4 +165,30 @@ public class ClusterCommunicationManager |
144 | } | 165 | } |
145 | } | 166 | } |
146 | } | 167 | } |
168 | + | ||
169 | + private static final class InternalClusterMessageResponse implements ClusterMessageResponse { | ||
170 | + | ||
171 | + private final NodeId sender; | ||
172 | + private final Response responseFuture; | ||
173 | + | ||
174 | + public InternalClusterMessageResponse(NodeId sender, Response responseFuture) { | ||
175 | + this.sender = sender; | ||
176 | + this.responseFuture = responseFuture; | ||
177 | + } | ||
178 | + @Override | ||
179 | + public NodeId sender() { | ||
180 | + return sender; | ||
181 | + } | ||
182 | + | ||
183 | + @Override | ||
184 | + public byte[] get(long timeout, TimeUnit timeunit) | ||
185 | + throws TimeoutException { | ||
186 | + return responseFuture.get(timeout, timeunit); | ||
187 | + } | ||
188 | + | ||
189 | + @Override | ||
190 | + public byte[] get(long timeout) throws InterruptedException { | ||
191 | + return responseFuture.get(); | ||
192 | + } | ||
193 | + } | ||
147 | } | 194 | } | ... | ... |
... | @@ -3,14 +3,20 @@ package org.onlab.onos.store.flow.impl; | ... | @@ -3,14 +3,20 @@ package org.onlab.onos.store.flow.impl; |
3 | import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; | 3 | import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; |
4 | import static org.slf4j.LoggerFactory.getLogger; | 4 | import static org.slf4j.LoggerFactory.getLogger; |
5 | 5 | ||
6 | +import java.io.IOException; | ||
6 | import java.util.Collection; | 7 | import java.util.Collection; |
7 | import java.util.Collections; | 8 | import java.util.Collections; |
9 | +import java.util.concurrent.TimeUnit; | ||
10 | +import java.util.concurrent.TimeoutException; | ||
8 | 11 | ||
9 | import org.apache.felix.scr.annotations.Activate; | 12 | import org.apache.felix.scr.annotations.Activate; |
10 | import org.apache.felix.scr.annotations.Component; | 13 | import org.apache.felix.scr.annotations.Component; |
11 | import org.apache.felix.scr.annotations.Deactivate; | 14 | import org.apache.felix.scr.annotations.Deactivate; |
15 | +import org.apache.felix.scr.annotations.Reference; | ||
16 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
12 | import org.apache.felix.scr.annotations.Service; | 17 | import org.apache.felix.scr.annotations.Service; |
13 | import org.onlab.onos.ApplicationId; | 18 | import org.onlab.onos.ApplicationId; |
19 | +import org.onlab.onos.cluster.ClusterService; | ||
14 | import org.onlab.onos.net.DeviceId; | 20 | import org.onlab.onos.net.DeviceId; |
15 | import org.onlab.onos.net.flow.DefaultFlowEntry; | 21 | import org.onlab.onos.net.flow.DefaultFlowEntry; |
16 | import org.onlab.onos.net.flow.FlowEntry; | 22 | import org.onlab.onos.net.flow.FlowEntry; |
... | @@ -21,6 +27,13 @@ import org.onlab.onos.net.flow.FlowRuleEvent.Type; | ... | @@ -21,6 +27,13 @@ import org.onlab.onos.net.flow.FlowRuleEvent.Type; |
21 | import org.onlab.onos.net.flow.FlowRuleStore; | 27 | import org.onlab.onos.net.flow.FlowRuleStore; |
22 | import org.onlab.onos.net.flow.FlowRuleStoreDelegate; | 28 | import org.onlab.onos.net.flow.FlowRuleStoreDelegate; |
23 | import org.onlab.onos.store.AbstractStore; | 29 | import org.onlab.onos.store.AbstractStore; |
30 | +import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; | ||
31 | +import org.onlab.onos.store.cluster.messaging.ClusterMessage; | ||
32 | +import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse; | ||
33 | +import org.onlab.onos.store.flow.ReplicaInfo; | ||
34 | +import org.onlab.onos.store.serializers.DistributedStoreSerializers; | ||
35 | +import org.onlab.onos.store.serializers.KryoSerializer; | ||
36 | +import org.onlab.util.KryoPool; | ||
24 | import org.slf4j.Logger; | 37 | import org.slf4j.Logger; |
25 | 38 | ||
26 | import com.google.common.collect.ArrayListMultimap; | 39 | import com.google.common.collect.ArrayListMultimap; |
... | @@ -28,9 +41,8 @@ import com.google.common.collect.ImmutableSet; | ... | @@ -28,9 +41,8 @@ import com.google.common.collect.ImmutableSet; |
28 | import com.google.common.collect.Multimap; | 41 | import com.google.common.collect.Multimap; |
29 | 42 | ||
30 | /** | 43 | /** |
31 | - * Manages inventory of flow rules using trivial in-memory implementation. | 44 | + * Manages inventory of flow rules using a distributed state management protocol. |
32 | */ | 45 | */ |
33 | -//FIXME I LIE. I AIN'T DISTRIBUTED | ||
34 | @Component(immediate = true) | 46 | @Component(immediate = true) |
35 | @Service | 47 | @Service |
36 | public class DistributedFlowRuleStore | 48 | public class DistributedFlowRuleStore |
... | @@ -46,6 +58,28 @@ public class DistributedFlowRuleStore | ... | @@ -46,6 +58,28 @@ public class DistributedFlowRuleStore |
46 | private final Multimap<Short, FlowRule> flowEntriesById = | 58 | private final Multimap<Short, FlowRule> flowEntriesById = |
47 | ArrayListMultimap.<Short, FlowRule>create(); | 59 | ArrayListMultimap.<Short, FlowRule>create(); |
48 | 60 | ||
61 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
62 | + private ReplicaInfoManager replicaInfoManager; | ||
63 | + | ||
64 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
65 | + private ClusterCommunicationService clusterCommunicator; | ||
66 | + | ||
67 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
68 | + private ClusterService clusterService; | ||
69 | + | ||
70 | + protected static final KryoSerializer SERIALIZER = new KryoSerializer() { | ||
71 | + @Override | ||
72 | + protected void setupKryoPool() { | ||
73 | + serializerPool = KryoPool.newBuilder() | ||
74 | + .register(DistributedStoreSerializers.COMMON) | ||
75 | + .build() | ||
76 | + .populate(1); | ||
77 | + } | ||
78 | + }; | ||
79 | + | ||
80 | + // TODO: make this configurable | ||
81 | + private static final long FLOW_RULE_STORE_TIMEOUT_MILLIS = 1000; | ||
82 | + | ||
49 | @Activate | 83 | @Activate |
50 | public void activate() { | 84 | public void activate() { |
51 | log.info("Started"); | 85 | log.info("Started"); |
... | @@ -91,26 +125,92 @@ public class DistributedFlowRuleStore | ... | @@ -91,26 +125,92 @@ public class DistributedFlowRuleStore |
91 | } | 125 | } |
92 | 126 | ||
93 | @Override | 127 | @Override |
94 | - public synchronized void storeFlowRule(FlowRule rule) { | 128 | + public void storeFlowRule(FlowRule rule) { |
95 | - FlowEntry f = new DefaultFlowEntry(rule); | 129 | + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId()); |
96 | - DeviceId did = f.deviceId(); | 130 | + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) { |
97 | - if (!flowEntries.containsEntry(did, f)) { | 131 | + storeFlowEntryInternal(rule); |
98 | - flowEntries.put(did, f); | 132 | + return; |
99 | - flowEntriesById.put(rule.appId(), f); | ||
100 | } | 133 | } |
134 | + | ||
135 | + ClusterMessage message = new ClusterMessage( | ||
136 | + clusterService.getLocalNode().id(), | ||
137 | + FlowStoreMessageSubjects.STORE_FLOW_RULE, | ||
138 | + SERIALIZER.encode(rule)); | ||
139 | + | ||
140 | + try { | ||
141 | + ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | ||
142 | + response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); | ||
143 | + } catch (IOException | TimeoutException e) { | ||
144 | + // FIXME: throw a FlowStoreException | ||
145 | + throw new RuntimeException(e); | ||
146 | + } | ||
147 | + } | ||
148 | + | ||
149 | + private synchronized void storeFlowEntryInternal(FlowRule flowRule) { | ||
150 | + FlowEntry flowEntry = new DefaultFlowEntry(flowRule); | ||
151 | + DeviceId deviceId = flowRule.deviceId(); | ||
152 | + // write to local copy. | ||
153 | + if (!flowEntries.containsEntry(deviceId, flowEntry)) { | ||
154 | + flowEntries.put(deviceId, flowEntry); | ||
155 | + flowEntriesById.put(flowRule.appId(), flowEntry); | ||
156 | + } | ||
157 | + // write to backup. | ||
158 | + // TODO: write to a hazelcast map. | ||
101 | } | 159 | } |
102 | 160 | ||
103 | @Override | 161 | @Override |
104 | public synchronized void deleteFlowRule(FlowRule rule) { | 162 | public synchronized void deleteFlowRule(FlowRule rule) { |
105 | - FlowEntry entry = getFlowEntry(rule); | 163 | + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId()); |
164 | + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) { | ||
165 | + deleteFlowRuleInternal(rule); | ||
166 | + return; | ||
167 | + } | ||
168 | + | ||
169 | + ClusterMessage message = new ClusterMessage( | ||
170 | + clusterService.getLocalNode().id(), | ||
171 | + FlowStoreMessageSubjects.DELETE_FLOW_RULE, | ||
172 | + SERIALIZER.encode(rule)); | ||
173 | + | ||
174 | + try { | ||
175 | + ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | ||
176 | + response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); | ||
177 | + } catch (IOException | TimeoutException e) { | ||
178 | + // FIXME: throw a FlowStoreException | ||
179 | + throw new RuntimeException(e); | ||
180 | + } | ||
181 | + } | ||
182 | + | ||
183 | + private synchronized void deleteFlowRuleInternal(FlowRule flowRule) { | ||
184 | + FlowEntry entry = getFlowEntry(flowRule); | ||
106 | if (entry == null) { | 185 | if (entry == null) { |
107 | return; | 186 | return; |
108 | } | 187 | } |
109 | entry.setState(FlowEntryState.PENDING_REMOVE); | 188 | entry.setState(FlowEntryState.PENDING_REMOVE); |
189 | + // TODO: also update backup. | ||
110 | } | 190 | } |
111 | 191 | ||
112 | @Override | 192 | @Override |
113 | - public synchronized FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule) { | 193 | + public FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule) { |
194 | + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId()); | ||
195 | + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) { | ||
196 | + return addOrUpdateFlowRuleInternal(rule); | ||
197 | + } | ||
198 | + | ||
199 | + ClusterMessage message = new ClusterMessage( | ||
200 | + clusterService.getLocalNode().id(), | ||
201 | + FlowStoreMessageSubjects.ADD_OR_UPDATE_FLOW_RULE, | ||
202 | + SERIALIZER.encode(rule)); | ||
203 | + | ||
204 | + try { | ||
205 | + ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | ||
206 | + return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); | ||
207 | + } catch (IOException | TimeoutException e) { | ||
208 | + // FIXME: throw a FlowStoreException | ||
209 | + throw new RuntimeException(e); | ||
210 | + } | ||
211 | + } | ||
212 | + | ||
213 | + private synchronized FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) { | ||
114 | DeviceId did = rule.deviceId(); | 214 | DeviceId did = rule.deviceId(); |
115 | 215 | ||
116 | // check if this new rule is an update to an existing entry | 216 | // check if this new rule is an update to an existing entry |
... | @@ -128,15 +228,39 @@ public class DistributedFlowRuleStore | ... | @@ -128,15 +228,39 @@ public class DistributedFlowRuleStore |
128 | 228 | ||
129 | flowEntries.put(did, rule); | 229 | flowEntries.put(did, rule); |
130 | return null; | 230 | return null; |
231 | + | ||
232 | + // TODO: also update backup. | ||
131 | } | 233 | } |
132 | 234 | ||
133 | @Override | 235 | @Override |
134 | - public synchronized FlowRuleEvent removeFlowRule(FlowEntry rule) { | 236 | + public FlowRuleEvent removeFlowRule(FlowEntry rule) { |
237 | + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(rule.deviceId()); | ||
238 | + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) { | ||
239 | + // bypass and handle it locally | ||
240 | + return removeFlowRuleInternal(rule); | ||
241 | + } | ||
242 | + | ||
243 | + ClusterMessage message = new ClusterMessage( | ||
244 | + clusterService.getLocalNode().id(), | ||
245 | + FlowStoreMessageSubjects.REMOVE_FLOW_RULE, | ||
246 | + SERIALIZER.encode(rule)); | ||
247 | + | ||
248 | + try { | ||
249 | + ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get()); | ||
250 | + return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)); | ||
251 | + } catch (IOException | TimeoutException e) { | ||
252 | + // FIXME: throw a FlowStoreException | ||
253 | + throw new RuntimeException(e); | ||
254 | + } | ||
255 | + } | ||
256 | + | ||
257 | + private synchronized FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) { | ||
135 | // This is where one could mark a rule as removed and still keep it in the store. | 258 | // This is where one could mark a rule as removed and still keep it in the store. |
136 | if (flowEntries.remove(rule.deviceId(), rule)) { | 259 | if (flowEntries.remove(rule.deviceId(), rule)) { |
137 | return new FlowRuleEvent(RULE_REMOVED, rule); | 260 | return new FlowRuleEvent(RULE_REMOVED, rule); |
138 | } else { | 261 | } else { |
139 | return null; | 262 | return null; |
140 | } | 263 | } |
264 | + // TODO: also update backup. | ||
141 | } | 265 | } |
142 | } | 266 | } | ... | ... |
core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/FlowStoreMessageSubjects.java
0 → 100644
1 | +package org.onlab.onos.store.flow.impl; | ||
2 | + | ||
3 | +import org.onlab.onos.store.cluster.messaging.MessageSubject; | ||
4 | + | ||
5 | +/** | ||
6 | + * MessageSubjects used by DistributedFlowRuleStore peer-peer communication. | ||
7 | + */ | ||
8 | +public final class FlowStoreMessageSubjects { | ||
9 | + private FlowStoreMessageSubjects() {} | ||
10 | + public static final MessageSubject STORE_FLOW_RULE = new MessageSubject("peer-forward-store-flow-rule"); | ||
11 | + public static final MessageSubject DELETE_FLOW_RULE = new MessageSubject("peer-forward-delete-flow-rule"); | ||
12 | + public static final MessageSubject ADD_OR_UPDATE_FLOW_RULE = | ||
13 | + new MessageSubject("peer-forward-add-or-update-flow-rule"); | ||
14 | + public static final MessageSubject REMOVE_FLOW_RULE = new MessageSubject("peer-forward-remove-flow-rule"); | ||
15 | +} |
... | @@ -26,6 +26,7 @@ import org.onlab.onos.net.Port; | ... | @@ -26,6 +26,7 @@ import org.onlab.onos.net.Port; |
26 | import org.onlab.onos.net.PortNumber; | 26 | import org.onlab.onos.net.PortNumber; |
27 | import org.onlab.onos.net.device.DefaultDeviceDescription; | 27 | import org.onlab.onos.net.device.DefaultDeviceDescription; |
28 | import org.onlab.onos.net.device.DefaultPortDescription; | 28 | import org.onlab.onos.net.device.DefaultPortDescription; |
29 | +import org.onlab.onos.net.flow.DefaultFlowRule; | ||
29 | import org.onlab.onos.net.host.DefaultHostDescription; | 30 | import org.onlab.onos.net.host.DefaultHostDescription; |
30 | import org.onlab.onos.net.host.HostDescription; | 31 | import org.onlab.onos.net.host.HostDescription; |
31 | import org.onlab.onos.net.link.DefaultLinkDescription; | 32 | import org.onlab.onos.net.link.DefaultLinkDescription; |
... | @@ -86,7 +87,8 @@ public final class KryoPoolUtil { | ... | @@ -86,7 +87,8 @@ public final class KryoPoolUtil { |
86 | Timestamp.class, | 87 | Timestamp.class, |
87 | HostId.class, | 88 | HostId.class, |
88 | HostDescription.class, | 89 | HostDescription.class, |
89 | - DefaultHostDescription.class | 90 | + DefaultHostDescription.class, |
91 | + DefaultFlowRule.class | ||
90 | ) | 92 | ) |
91 | .register(URI.class, new URISerializer()) | 93 | .register(URI.class, new URISerializer()) |
92 | .register(NodeId.class, new NodeIdSerializer()) | 94 | .register(NodeId.class, new NodeIdSerializer()) | ... | ... |
... | @@ -155,6 +155,13 @@ | ... | @@ -155,6 +155,13 @@ |
155 | <feature>onos-api</feature> | 155 | <feature>onos-api</feature> |
156 | <bundle>mvn:org.onlab.onos/onos-app-config/1.0.0-SNAPSHOT</bundle> | 156 | <bundle>mvn:org.onlab.onos/onos-app-config/1.0.0-SNAPSHOT</bundle> |
157 | </feature> | 157 | </feature> |
158 | + | ||
159 | + <feature name="onos-app-optical" version="1.0.0" | ||
160 | + description="ONOS optical network config"> | ||
161 | + <feature>onos-api</feature> | ||
162 | + <bundle>mvn:org.onlab.onos/onos-app-optical/1.0.0-SNAPSHOT</bundle> | ||
163 | + </feature> | ||
164 | + | ||
158 | 165 | ||
159 | <feature name="onos-app-sdnip" version="1.0.0" | 166 | <feature name="onos-app-sdnip" version="1.0.0" |
160 | description="SDN-IP peering application"> | 167 | description="SDN-IP peering application"> | ... | ... |
... | @@ -223,7 +223,7 @@ public class FlowEntryBuilder { | ... | @@ -223,7 +223,7 @@ public class FlowEntryBuilder { |
223 | if (di.isCidrMask()) { | 223 | if (di.isCidrMask()) { |
224 | dip = IpPrefix.valueOf(di.getInt(), di.asCidrMaskLength()); | 224 | dip = IpPrefix.valueOf(di.getInt(), di.asCidrMaskLength()); |
225 | } else { | 225 | } else { |
226 | - dip = IpPrefix.valueOf(di.getInt()); | 226 | + dip = IpPrefix.valueOf(di.getInt(), IpPrefix.MAX_INET_MASK); |
227 | } | 227 | } |
228 | builder.matchIPDst(dip); | 228 | builder.matchIPDst(dip); |
229 | break; | 229 | break; |
... | @@ -233,7 +233,7 @@ public class FlowEntryBuilder { | ... | @@ -233,7 +233,7 @@ public class FlowEntryBuilder { |
233 | if (si.isCidrMask()) { | 233 | if (si.isCidrMask()) { |
234 | sip = IpPrefix.valueOf(si.getInt(), si.asCidrMaskLength()); | 234 | sip = IpPrefix.valueOf(si.getInt(), si.asCidrMaskLength()); |
235 | } else { | 235 | } else { |
236 | - sip = IpPrefix.valueOf(si.getInt()); | 236 | + sip = IpPrefix.valueOf(si.getInt(), IpPrefix.MAX_INET_MASK); |
237 | } | 237 | } |
238 | builder.matchIPSrc(sip); | 238 | builder.matchIPSrc(sip); |
239 | break; | 239 | break; |
... | @@ -249,6 +249,12 @@ public class FlowEntryBuilder { | ... | @@ -249,6 +249,12 @@ public class FlowEntryBuilder { |
249 | VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan()); | 249 | VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan()); |
250 | builder.matchVlanId(vlanId); | 250 | builder.matchVlanId(vlanId); |
251 | break; | 251 | break; |
252 | + case TCP_DST: | ||
253 | + builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort()); | ||
254 | + break; | ||
255 | + case TCP_SRC: | ||
256 | + builder.matchTcpSrc((short) match.get(MatchField.TCP_SRC).getPort()); | ||
257 | + break; | ||
252 | case ARP_OP: | 258 | case ARP_OP: |
253 | case ARP_SHA: | 259 | case ARP_SHA: |
254 | case ARP_SPA: | 260 | case ARP_SPA: |
... | @@ -272,8 +278,6 @@ public class FlowEntryBuilder { | ... | @@ -272,8 +278,6 @@ public class FlowEntryBuilder { |
272 | case MPLS_TC: | 278 | case MPLS_TC: |
273 | case SCTP_DST: | 279 | case SCTP_DST: |
274 | case SCTP_SRC: | 280 | case SCTP_SRC: |
275 | - case TCP_DST: | ||
276 | - case TCP_SRC: | ||
277 | case TUNNEL_ID: | 281 | case TUNNEL_ID: |
278 | case UDP_DST: | 282 | case UDP_DST: |
279 | case UDP_SRC: | 283 | case UDP_SRC: | ... | ... |
... | @@ -15,6 +15,7 @@ import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion; | ... | @@ -15,6 +15,7 @@ import org.onlab.onos.net.flow.criteria.Criteria.EthTypeCriterion; |
15 | import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion; | 15 | import org.onlab.onos.net.flow.criteria.Criteria.IPCriterion; |
16 | import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion; | 16 | import org.onlab.onos.net.flow.criteria.Criteria.IPProtocolCriterion; |
17 | import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion; | 17 | import org.onlab.onos.net.flow.criteria.Criteria.PortCriterion; |
18 | +import org.onlab.onos.net.flow.criteria.Criteria.TcpPortCriterion; | ||
18 | import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion; | 19 | import org.onlab.onos.net.flow.criteria.Criteria.VlanIdCriterion; |
19 | import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion; | 20 | import org.onlab.onos.net.flow.criteria.Criteria.VlanPcpCriterion; |
20 | import org.onlab.onos.net.flow.criteria.Criterion; | 21 | import org.onlab.onos.net.flow.criteria.Criterion; |
... | @@ -42,6 +43,7 @@ import org.projectfloodlight.openflow.types.Masked; | ... | @@ -42,6 +43,7 @@ import org.projectfloodlight.openflow.types.Masked; |
42 | import org.projectfloodlight.openflow.types.OFBufferId; | 43 | import org.projectfloodlight.openflow.types.OFBufferId; |
43 | import org.projectfloodlight.openflow.types.OFPort; | 44 | import org.projectfloodlight.openflow.types.OFPort; |
44 | import org.projectfloodlight.openflow.types.OFVlanVidMatch; | 45 | import org.projectfloodlight.openflow.types.OFVlanVidMatch; |
46 | +import org.projectfloodlight.openflow.types.TransportPort; | ||
45 | import org.projectfloodlight.openflow.types.U64; | 47 | import org.projectfloodlight.openflow.types.U64; |
46 | import org.projectfloodlight.openflow.types.VlanPcp; | 48 | import org.projectfloodlight.openflow.types.VlanPcp; |
47 | import org.projectfloodlight.openflow.types.VlanVid; | 49 | import org.projectfloodlight.openflow.types.VlanVid; |
... | @@ -199,6 +201,7 @@ public class FlowModBuilder { | ... | @@ -199,6 +201,7 @@ public class FlowModBuilder { |
199 | Match.Builder mBuilder = factory.buildMatch(); | 201 | Match.Builder mBuilder = factory.buildMatch(); |
200 | EthCriterion eth; | 202 | EthCriterion eth; |
201 | IPCriterion ip; | 203 | IPCriterion ip; |
204 | + TcpPortCriterion tp; | ||
202 | for (Criterion c : selector.criteria()) { | 205 | for (Criterion c : selector.criteria()) { |
203 | switch (c.type()) { | 206 | switch (c.type()) { |
204 | case IN_PORT: | 207 | case IN_PORT: |
... | @@ -250,6 +253,14 @@ public class FlowModBuilder { | ... | @@ -250,6 +253,14 @@ public class FlowModBuilder { |
250 | mBuilder.setExact(MatchField.VLAN_VID, | 253 | mBuilder.setExact(MatchField.VLAN_VID, |
251 | OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort()))); | 254 | OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort()))); |
252 | break; | 255 | break; |
256 | + case TCP_DST: | ||
257 | + tp = (TcpPortCriterion) c; | ||
258 | + mBuilder.setExact(MatchField.TCP_DST, TransportPort.of(tp.tcpPort())); | ||
259 | + break; | ||
260 | + case TCP_SRC: | ||
261 | + tp = (TcpPortCriterion) c; | ||
262 | + mBuilder.setExact(MatchField.TCP_SRC, TransportPort.of(tp.tcpPort())); | ||
263 | + break; | ||
253 | case ARP_OP: | 264 | case ARP_OP: |
254 | case ARP_SHA: | 265 | case ARP_SHA: |
255 | case ARP_SPA: | 266 | case ARP_SPA: |
... | @@ -276,8 +287,6 @@ public class FlowModBuilder { | ... | @@ -276,8 +287,6 @@ public class FlowModBuilder { |
276 | case PBB_ISID: | 287 | case PBB_ISID: |
277 | case SCTP_DST: | 288 | case SCTP_DST: |
278 | case SCTP_SRC: | 289 | case SCTP_SRC: |
279 | - case TCP_DST: | ||
280 | - case TCP_SRC: | ||
281 | case TUNNEL_ID: | 290 | case TUNNEL_ID: |
282 | case UDP_DST: | 291 | case UDP_DST: |
283 | case UDP_SRC: | 292 | case UDP_SRC: | ... | ... |
providers/openflow/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
1 | package org.onlab.onos.provider.of.host.impl; | 1 | package org.onlab.onos.provider.of.host.impl; |
2 | 2 | ||
3 | +import static org.onlab.onos.net.DeviceId.deviceId; | ||
4 | +import static org.onlab.onos.net.PortNumber.portNumber; | ||
5 | +import static org.slf4j.LoggerFactory.getLogger; | ||
6 | + | ||
3 | import org.apache.felix.scr.annotations.Activate; | 7 | import org.apache.felix.scr.annotations.Activate; |
4 | import org.apache.felix.scr.annotations.Component; | 8 | import org.apache.felix.scr.annotations.Component; |
5 | import org.apache.felix.scr.annotations.Deactivate; | 9 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -29,10 +33,6 @@ import org.onlab.packet.IpPrefix; | ... | @@ -29,10 +33,6 @@ import org.onlab.packet.IpPrefix; |
29 | import org.onlab.packet.VlanId; | 33 | import org.onlab.packet.VlanId; |
30 | import org.slf4j.Logger; | 34 | import org.slf4j.Logger; |
31 | 35 | ||
32 | -import static org.onlab.onos.net.DeviceId.deviceId; | ||
33 | -import static org.onlab.onos.net.PortNumber.portNumber; | ||
34 | -import static org.slf4j.LoggerFactory.getLogger; | ||
35 | - | ||
36 | /** | 36 | /** |
37 | * Provider which uses an OpenFlow controller to detect network | 37 | * Provider which uses an OpenFlow controller to detect network |
38 | * end-station hosts. | 38 | * end-station hosts. |
... | @@ -110,14 +110,16 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid | ... | @@ -110,14 +110,16 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid |
110 | // Potentially a new or moved host | 110 | // Potentially a new or moved host |
111 | if (eth.getEtherType() == Ethernet.TYPE_ARP) { | 111 | if (eth.getEtherType() == Ethernet.TYPE_ARP) { |
112 | ARP arp = (ARP) eth.getPayload(); | 112 | ARP arp = (ARP) eth.getPayload(); |
113 | - IpPrefix ip = IpPrefix.valueOf(arp.getSenderProtocolAddress()); | 113 | + IpPrefix ip = IpPrefix.valueOf(arp.getSenderProtocolAddress(), |
114 | + IpPrefix.MAX_INET_MASK); | ||
114 | HostDescription hdescr = | 115 | HostDescription hdescr = |
115 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); | 116 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); |
116 | providerService.hostDetected(hid, hdescr); | 117 | providerService.hostDetected(hid, hdescr); |
117 | 118 | ||
118 | } else if (ipLearn && eth.getEtherType() == Ethernet.TYPE_IPV4) { | 119 | } else if (ipLearn && eth.getEtherType() == Ethernet.TYPE_IPV4) { |
119 | IPv4 pip = (IPv4) eth.getPayload(); | 120 | IPv4 pip = (IPv4) eth.getPayload(); |
120 | - IpPrefix ip = IpPrefix.valueOf(pip.getSourceAddress()); | 121 | + IpPrefix ip = IpPrefix.valueOf(pip.getSourceAddress(), |
122 | + IpPrefix.MAX_INET_MASK); | ||
121 | HostDescription hdescr = | 123 | HostDescription hdescr = |
122 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); | 124 | new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip); |
123 | providerService.hostDetected(hid, hdescr); | 125 | providerService.hostDetected(hid, hdescr); | ... | ... |
tools/test/cells/single_optical
0 → 100644
1 | +# Local VirtualBox-based single ONOS instance & ONOS mininet box | ||
2 | + | ||
3 | +export ONOS_NIC=192.168.56.* | ||
4 | +export OC1="192.168.56.101" | ||
5 | +export OCN="192.168.56.103" | ||
6 | + | ||
7 | +export ONOS_FEATURES=webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd,onos-app-mobility,onos-app-tvue,onos-app-optical |
1 | +package org.onlab.util; | ||
2 | + | ||
3 | +public final class HexString { | ||
4 | + | ||
5 | + private HexString() { | ||
6 | + | ||
7 | + } | ||
8 | + | ||
9 | + /** | ||
10 | + * Convert a string of bytes to a ':' separated hex string. | ||
11 | + * | ||
12 | + * @param bytes | ||
13 | + * @return "0f:ca:fe:de:ad:be:ef" | ||
14 | + */ | ||
15 | + public static String toHexString(final byte[] bytes) { | ||
16 | + int i; | ||
17 | + StringBuilder ret = new StringBuilder(); | ||
18 | + String tmp; | ||
19 | + for (i = 0; i < bytes.length; i++) { | ||
20 | + if (i > 0) { | ||
21 | + ret.append(':'); | ||
22 | + } | ||
23 | + tmp = Integer.toHexString((bytes[i] & 0xff)); | ||
24 | + if (tmp.length() == 1) { | ||
25 | + ret.append('0'); | ||
26 | + } | ||
27 | + ret.append(tmp); | ||
28 | + } | ||
29 | + return ret.toString(); | ||
30 | + } | ||
31 | + | ||
32 | + public static String toHexString(final long val, final int padTo) { | ||
33 | + char[] arr = Long.toHexString(val).toCharArray(); | ||
34 | + String ret = ""; | ||
35 | + // prepend the right number of leading zeros | ||
36 | + int i = 0; | ||
37 | + for (; i < (padTo * 2 - arr.length); i++) { | ||
38 | + ret += "0"; | ||
39 | + if ((i % 2) != 0) { | ||
40 | + ret += ":"; | ||
41 | + } | ||
42 | + } | ||
43 | + for (int j = 0; j < arr.length; j++) { | ||
44 | + ret += arr[j]; | ||
45 | + if ((((i + j) % 2) != 0) && (j < (arr.length - 1))) { | ||
46 | + ret += ":"; | ||
47 | + } | ||
48 | + } | ||
49 | + return ret; | ||
50 | + } | ||
51 | + | ||
52 | + public static String toHexString(final long val) { | ||
53 | + return toHexString(val, 8); | ||
54 | + } | ||
55 | + | ||
56 | + /** | ||
57 | + * Convert a string of hex values into a string of bytes. | ||
58 | + * | ||
59 | + * @param values | ||
60 | + * "0f:ca:fe:de:ad:be:ef" | ||
61 | + * @return [15, 5 ,2, 5, 17] | ||
62 | + * @throws NumberFormatException | ||
63 | + * If the string can not be parsed | ||
64 | + */ | ||
65 | + public static byte[] fromHexString(final String values) { | ||
66 | + String[] octets = values.split(":"); | ||
67 | + byte[] ret = new byte[octets.length]; | ||
68 | + | ||
69 | + for (int i = 0; i < octets.length; i++) { | ||
70 | + if (octets[i].length() > 2) { | ||
71 | + throw new NumberFormatException("Invalid octet length"); | ||
72 | + } | ||
73 | + ret[i] = Integer.valueOf(octets[i], 16).byteValue(); | ||
74 | + } | ||
75 | + return ret; | ||
76 | + } | ||
77 | + | ||
78 | + public static long toLong(String value) { | ||
79 | + String[] octets = value.split(":"); | ||
80 | + if (octets.length > 8) { | ||
81 | + throw new NumberFormatException("Input string is too big to fit in long: " + value); | ||
82 | + } | ||
83 | + long l = 0; | ||
84 | + for (String octet: octets) { | ||
85 | + if (octet.length() > 2) { | ||
86 | + throw new NumberFormatException( | ||
87 | + "Each colon-separated byte component must consist of 1 or 2 hex digits: " + value); | ||
88 | + } | ||
89 | + short s = Short.parseShort(octet, 16); | ||
90 | + l = (l << 8) + s; | ||
91 | + } | ||
92 | + return l; | ||
93 | + } | ||
94 | +} |
1 | +package org.onlab.util; | ||
2 | + | ||
3 | +import org.junit.Test; | ||
4 | + | ||
5 | +import com.esotericsoftware.minlog.Log; | ||
6 | + | ||
7 | +import junit.framework.TestCase; | ||
8 | + | ||
9 | +/** | ||
10 | + * Test of the Hexstring. | ||
11 | + * | ||
12 | + */ | ||
13 | + | ||
14 | +public class HexStringTest extends TestCase { | ||
15 | + | ||
16 | + @Test | ||
17 | + public void testMarshalling() throws Exception { | ||
18 | + String dpidStr = "00:00:00:23:20:2d:16:71"; | ||
19 | + long dpid = HexString.toLong(dpidStr); | ||
20 | + String testStr = HexString.toHexString(dpid); | ||
21 | + TestCase.assertEquals(dpidStr, testStr); | ||
22 | + } | ||
23 | + | ||
24 | + @Test | ||
25 | + public void testToLong() { | ||
26 | + String dpidStr = "3e:1f:01:fc:72:8c:63:31"; | ||
27 | + long valid = 0x3e1f01fc728c6331L; | ||
28 | + long testLong = HexString.toLong(dpidStr); | ||
29 | + TestCase.assertEquals(valid, testLong); | ||
30 | + } | ||
31 | + | ||
32 | + @Test | ||
33 | + public void testToLongMSB() { | ||
34 | + String dpidStr = "ca:7c:5e:d1:64:7a:95:9b"; | ||
35 | + long valid = -3856102927509056101L; | ||
36 | + long testLong = HexString.toLong(dpidStr); | ||
37 | + TestCase.assertEquals(valid, testLong); | ||
38 | + } | ||
39 | + | ||
40 | + @Test | ||
41 | + public void testToLongError() { | ||
42 | + String dpidStr = "09:08:07:06:05:04:03:02:01"; | ||
43 | + try { | ||
44 | + HexString.toLong(dpidStr); | ||
45 | + fail("HexString.toLong() should have thrown a NumberFormatException"); | ||
46 | + } catch (NumberFormatException expected) { | ||
47 | + Log.info("HexString.toLong() have thrown a NumberFormatException"); | ||
48 | + } | ||
49 | + } | ||
50 | + | ||
51 | + @Test | ||
52 | + public void testToStringBytes() { | ||
53 | + byte[] dpid = {0, 0, 0, 0, 0, 0, 0, -1 }; | ||
54 | + String valid = "00:00:00:00:00:00:00:ff"; | ||
55 | + String testString = HexString.toHexString(dpid); | ||
56 | + TestCase.assertEquals(valid, testString); | ||
57 | + } | ||
58 | + | ||
59 | + @Test | ||
60 | + public void testFromHexStringError() { | ||
61 | + String invalidStr = "00:00:00:00:00:00:ffff"; | ||
62 | + try { | ||
63 | + HexString.fromHexString(invalidStr); | ||
64 | + fail("HexString.fromHexString() should have thrown a NumberFormatException"); | ||
65 | + } catch (NumberFormatException expected) { | ||
66 | + Log.info("HexString.toLong() have thrown a NumberFormatException"); | ||
67 | + } | ||
68 | + } | ||
69 | +} | ||
70 | + |
-
Please register or login to post a comment