blob: 9ce88572610164600c1ed1acc3df24f36750f74c [file] [log] [blame]
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -08001package net.onrc.onos.datastore.topology;
2
3import java.nio.ByteBuffer;
Yuta HIGUCHI1ca1afa2014-02-04 19:33:57 -08004import java.util.Collection;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -08005import java.util.HashMap;
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -08006import java.util.Iterator;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -08007import java.util.Map;
8
Yuta HIGUCHI1ca1afa2014-02-04 19:33:57 -08009import org.openflow.util.HexString;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080010import org.slf4j.Logger;
11import org.slf4j.LoggerFactory;
12
13import com.esotericsoftware.kryo.Kryo;
14
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -080015import edu.stanford.ramcloud.JRamCloud;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080016import net.onrc.onos.datastore.RCObject;
17import net.onrc.onos.datastore.RCTable;
Yuta HIGUCHIb5107282014-02-14 17:18:24 -080018import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
19import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080020
21public class RCLink extends RCObject {
22 @SuppressWarnings("unused")
23 private static final Logger log = LoggerFactory.getLogger(RCLink.class);
24
25 private static final ThreadLocal<Kryo> linkKryo = new ThreadLocal<Kryo>() {
26 @Override
27 protected Kryo initialValue() {
28 Kryo kryo = new Kryo();
29 kryo.setRegistrationRequired(true);
30 kryo.setReferences(false);
31 kryo.register(byte[].class);
32 kryo.register(byte[][].class);
33 kryo.register(HashMap.class);
34 // TODO check if we should explicitly specify EnumSerializer
35 kryo.register(STATUS.class);
36 return kryo;
37 }
38 };
39
40 public static class SwitchPort {
41 public final Long dpid;
42 public final Long number;
43
44 public SwitchPort(Long dpid, Long number) {
45 this.dpid = dpid;
46 this.number = number;
47 }
48
49 public byte[] getPortID() {
50 return RCPort.getPortID(dpid, number);
51 }
52
53 public byte[] getSwitchID() {
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -080054 return RCSwitch.getSwitchID(dpid);
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080055 }
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -080056
57 @Override
58 public String toString() {
59 return "(" + Long.toHexString(dpid) + "@" + number + ")";
60 }
61
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080062 }
63
64 public static final String GLOBAL_LINK_TABLE_NAME = "G:Link";
65
66 // FIXME these should be Enum or some number, not String
67 private static final String PROP_STATUS = "status";
68 private static final String PROP_SRC_SW_ID = "src-sw-id";
69 private static final String PROP_SRC_PORT_ID = "src-port-id";
70 private static final String PROP_DST_SW_ID = "dst-sw-id";
71 private static final String PROP_DST_PORT_ID = "dst-port-id";
72
73 // must not re-order enum members, ordinal will be sent over wire
74 public enum STATUS {
75 INACTIVE, ACTIVE;
76 }
77
78 private final SwitchPort src;
79 private final SwitchPort dst;
80 private STATUS status;
81
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080082 public static byte[] getLinkID(Long src_dpid, Long src_port_no,
83 Long dst_dpid, Long dst_port_no) {
Yuta HIGUCHIb5107282014-02-14 17:18:24 -080084 return LinkEvent.getLinkID(src_dpid, src_port_no, dst_dpid,
85 dst_port_no);
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080086 }
87
Yuta HIGUCHI1ca1afa2014-02-04 19:33:57 -080088 public static StringBuilder keysToSB(Collection<byte[]> keys) {
89 StringBuilder sb = new StringBuilder();
90 sb.append("[");
91 boolean hasWritten = false;
92 for (byte[] key : keys) {
93 if (hasWritten) {
94 sb.append(", ");
95 }
96 sb.append(keyToString(key));
97 hasWritten = true;
98 }
99 sb.append("]");
100 return sb;
101 }
102
103 public static String keyToString(byte[] key) {
104 // For debug log
105 long[] tuple = getLinkTupleFromKey(key);
106 return "L" + "S" + HexString.toHexString(tuple[0]) + "P" + tuple[1]
107 + "S" + HexString.toHexString(tuple[2]) + "P" + tuple[3];
108 }
109
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800110 public static long[] getLinkTupleFromKey(byte[] key) {
111 return getLinkTupleFromKey(ByteBuffer.wrap(key));
112 }
113
114 public static long[] getLinkTupleFromKey(ByteBuffer keyBuf) {
115 long tuple[] = new long[4];
116 if (keyBuf.getChar() != 'L') {
117 throw new IllegalArgumentException("Invalid Link key");
118 }
119 long src_port_pair[] = RCPort.getPortPairFromKey(keyBuf.slice());
Yuta HIGUCHIb5107282014-02-14 17:18:24 -0800120 keyBuf.position(2 + PortEvent.PORTID_BYTES);
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800121 long dst_port_pair[] = RCPort.getPortPairFromKey(keyBuf.slice());
122
123 tuple[0] = src_port_pair[0];
124 tuple[1] = src_port_pair[1];
125 tuple[2] = dst_port_pair[0];
126 tuple[3] = dst_port_pair[1];
127
128 return tuple;
129 }
130
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800131 public RCLink(Long src_dpid, Long src_port_no, Long dst_dpid,
132 Long dst_port_no) {
133 super(RCTable.getTable(GLOBAL_LINK_TABLE_NAME), getLinkID(src_dpid,
134 src_port_no, dst_dpid, dst_port_no));
135
136 src = new SwitchPort(src_dpid, src_port_no);
137 dst = new SwitchPort(dst_dpid, dst_port_no);
138 status = STATUS.INACTIVE;
139 }
140
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800141 /**
142 * Get an instance from Key.
143 *
144 * @note You need to call `read()` to get the DB content.
145 * @param key
146 * @return RCLink instance
147 */
148 public static <L extends RCObject> L createFromKey(byte[] key) {
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800149 long linkTuple[] = getLinkTupleFromKey(key);
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800150 @SuppressWarnings("unchecked")
151 L l = (L) new RCLink(linkTuple[0], linkTuple[1], linkTuple[2],
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800152 linkTuple[3]);
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800153 return l;
154 }
155
156 public static Iterable<RCLink> getAllLinks() {
157 return new LinkEnumerator();
158 }
159
160 public static class LinkEnumerator implements Iterable<RCLink> {
161
162 @Override
163 public Iterator<RCLink> iterator() {
164 return new LinkIterator();
165 }
166 }
167
168 public static class LinkIterator extends ObjectIterator<RCLink> {
169
170 public LinkIterator() {
171 super(RCTable.getTable(GLOBAL_LINK_TABLE_NAME));
172 }
173
174 @Override
175 public RCLink next() {
176 JRamCloud.Object o = enumerator.next();
177 RCLink e = RCLink.createFromKey(o.key);
178 e.setValueAndDeserialize(o.value, o.version);
179 return e;
180 }
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800181 }
182
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800183 public STATUS getStatus() {
184 return status;
185 }
186
187 public void setStatus(STATUS status) {
188 this.status = status;
189 getObjectMap().put(PROP_STATUS, status);
190 }
191
192 public SwitchPort getSrc() {
193 return src;
194 }
195
196 public SwitchPort getDst() {
197 return dst;
198 }
199
200 public byte[] getId() {
201 return getKey();
202 }
203
204 @Override
205 public void serializeAndSetValue() {
206 Map<Object, Object> map = getObjectMap();
207
208 map.put(PROP_SRC_SW_ID, src.getSwitchID());
209 map.put(PROP_SRC_PORT_ID, src.getPortID());
210 map.put(PROP_DST_SW_ID, dst.getSwitchID());
211 map.put(PROP_DST_PORT_ID, dst.getPortID());
212
213 serializeAndSetValue(linkKryo.get(), map);
214 }
215
216 @Override
217 public Map<Object, Object> deserializeObjectFromValue() {
218 Map<Object, Object> map = deserializeObjectFromValue(linkKryo.get());
219
220 this.status = (STATUS) map.get(PROP_STATUS);
221 return map;
222 }
223
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800224 @Override
225 public String toString() {
226 return "[RCLink " + src + "->" + dst + " STATUS:" + status + "]";
227 }
228
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800229 public static void main(String[] args) {
230 // TODO Auto-generated method stub
231
232 }
233
234}