blob: e3edff0e710c0fa2e268f6bf004936e6c1ada4a4 [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;
Yoshi Muroi212e5ca2014-02-20 22:42:37 -080014import com.google.protobuf.ByteString;
15import com.google.protobuf.InvalidProtocolBufferException;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080016
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -080017import edu.stanford.ramcloud.JRamCloud;
Yoshi Muroi212e5ca2014-02-20 22:42:37 -080018import net.onrc.onos.datastore.RCProtos.LinkProperty;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080019import net.onrc.onos.datastore.RCObject;
20import net.onrc.onos.datastore.RCTable;
Yuta HIGUCHIb5107282014-02-14 17:18:24 -080021import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
22import net.onrc.onos.ofcontroller.networkgraph.PortEvent;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080023
24public class RCLink extends RCObject {
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080025 private static final Logger log = LoggerFactory.getLogger(RCLink.class);
26
27 private static final ThreadLocal<Kryo> linkKryo = new ThreadLocal<Kryo>() {
28 @Override
29 protected Kryo initialValue() {
30 Kryo kryo = new Kryo();
31 kryo.setRegistrationRequired(true);
32 kryo.setReferences(false);
33 kryo.register(byte[].class);
34 kryo.register(byte[][].class);
35 kryo.register(HashMap.class);
36 // TODO check if we should explicitly specify EnumSerializer
37 kryo.register(STATUS.class);
38 return kryo;
39 }
40 };
41
42 public static class SwitchPort {
43 public final Long dpid;
44 public final Long number;
45
46 public SwitchPort(Long dpid, Long number) {
47 this.dpid = dpid;
48 this.number = number;
49 }
50
51 public byte[] getPortID() {
52 return RCPort.getPortID(dpid, number);
53 }
54
55 public byte[] getSwitchID() {
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -080056 return RCSwitch.getSwitchID(dpid);
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080057 }
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -080058
59 @Override
60 public String toString() {
61 return "(" + Long.toHexString(dpid) + "@" + number + ")";
62 }
63
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080064 }
65
66 public static final String GLOBAL_LINK_TABLE_NAME = "G:Link";
67
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080068 // must not re-order enum members, ordinal will be sent over wire
69 public enum STATUS {
70 INACTIVE, ACTIVE;
71 }
72
73 private final SwitchPort src;
74 private final SwitchPort dst;
75 private STATUS status;
76
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080077 public static byte[] getLinkID(Long src_dpid, Long src_port_no,
78 Long dst_dpid, Long dst_port_no) {
Yuta HIGUCHIb5107282014-02-14 17:18:24 -080079 return LinkEvent.getLinkID(src_dpid, src_port_no, dst_dpid,
Yuta HIGUCHIa341b112014-02-23 15:42:00 -080080 dst_port_no).array();
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080081 }
82
Yuta HIGUCHI1ca1afa2014-02-04 19:33:57 -080083 public static StringBuilder keysToSB(Collection<byte[]> keys) {
84 StringBuilder sb = new StringBuilder();
85 sb.append("[");
86 boolean hasWritten = false;
87 for (byte[] key : keys) {
88 if (hasWritten) {
89 sb.append(", ");
90 }
91 sb.append(keyToString(key));
92 hasWritten = true;
93 }
94 sb.append("]");
95 return sb;
96 }
97
98 public static String keyToString(byte[] key) {
99 // For debug log
100 long[] tuple = getLinkTupleFromKey(key);
101 return "L" + "S" + HexString.toHexString(tuple[0]) + "P" + tuple[1]
102 + "S" + HexString.toHexString(tuple[2]) + "P" + tuple[3];
103 }
104
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800105 public static long[] getLinkTupleFromKey(byte[] key) {
106 return getLinkTupleFromKey(ByteBuffer.wrap(key));
107 }
108
109 public static long[] getLinkTupleFromKey(ByteBuffer keyBuf) {
110 long tuple[] = new long[4];
111 if (keyBuf.getChar() != 'L') {
112 throw new IllegalArgumentException("Invalid Link key");
113 }
114 long src_port_pair[] = RCPort.getPortPairFromKey(keyBuf.slice());
Yuta HIGUCHIb5107282014-02-14 17:18:24 -0800115 keyBuf.position(2 + PortEvent.PORTID_BYTES);
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800116 long dst_port_pair[] = RCPort.getPortPairFromKey(keyBuf.slice());
117
118 tuple[0] = src_port_pair[0];
119 tuple[1] = src_port_pair[1];
120 tuple[2] = dst_port_pair[0];
121 tuple[3] = dst_port_pair[1];
122
123 return tuple;
124 }
125
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800126 public RCLink(Long src_dpid, Long src_port_no, Long dst_dpid,
127 Long dst_port_no) {
128 super(RCTable.getTable(GLOBAL_LINK_TABLE_NAME), getLinkID(src_dpid,
129 src_port_no, dst_dpid, dst_port_no));
130
131 src = new SwitchPort(src_dpid, src_port_no);
132 dst = new SwitchPort(dst_dpid, dst_port_no);
133 status = STATUS.INACTIVE;
134 }
135
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800136 /**
137 * Get an instance from Key.
138 *
139 * @note You need to call `read()` to get the DB content.
140 * @param key
141 * @return RCLink instance
142 */
143 public static <L extends RCObject> L createFromKey(byte[] key) {
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800144 long linkTuple[] = getLinkTupleFromKey(key);
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800145 @SuppressWarnings("unchecked")
146 L l = (L) new RCLink(linkTuple[0], linkTuple[1], linkTuple[2],
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800147 linkTuple[3]);
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800148 return l;
149 }
150
151 public static Iterable<RCLink> getAllLinks() {
152 return new LinkEnumerator();
153 }
154
155 public static class LinkEnumerator implements Iterable<RCLink> {
156
157 @Override
158 public Iterator<RCLink> iterator() {
159 return new LinkIterator();
160 }
161 }
162
163 public static class LinkIterator extends ObjectIterator<RCLink> {
164
165 public LinkIterator() {
166 super(RCTable.getTable(GLOBAL_LINK_TABLE_NAME));
167 }
168
169 @Override
170 public RCLink next() {
171 JRamCloud.Object o = enumerator.next();
172 RCLink e = RCLink.createFromKey(o.key);
173 e.setValueAndDeserialize(o.value, o.version);
174 return e;
175 }
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800176 }
177
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800178 public STATUS getStatus() {
179 return status;
180 }
181
182 public void setStatus(STATUS status) {
183 this.status = status;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800184 }
185
186 public SwitchPort getSrc() {
187 return src;
188 }
189
190 public SwitchPort getDst() {
191 return dst;
192 }
193
194 public byte[] getId() {
195 return getKey();
196 }
197
198 @Override
199 public void serializeAndSetValue() {
200 Map<Object, Object> map = getObjectMap();
201
Yoshi Muroi212e5ca2014-02-20 22:42:37 -0800202 LinkProperty.Builder link = LinkProperty.newBuilder();
203 link.setSrcSwId(ByteString.copyFrom(src.getSwitchID()));
204 link.setSrcPortId(ByteString.copyFrom(src.getPortID()));
205 link.setDstSwId(ByteString.copyFrom(dst.getSwitchID()));
206 link.setDstPortId(ByteString.copyFrom(dst.getPortID()));
207 link.setStatus(status.ordinal());
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800208
Yoshi Muroi212e5ca2014-02-20 22:42:37 -0800209 if (!map.isEmpty()) {
210 serializeAndSetValue(linkKryo.get(), map);
211 link.setValue(ByteString.copyFrom(this.getSerializedValue()));
212 }
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800213
Yoshi Muroi212e5ca2014-02-20 22:42:37 -0800214 this.value = link.build().toByteArray();
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800215 }
216
217 @Override
218 public Map<Object, Object> deserializeObjectFromValue() {
Yoshi Muroi212e5ca2014-02-20 22:42:37 -0800219 LinkProperty link = null;
220 Map<Object, Object> map = null;
221 try {
222 link = LinkProperty.parseFrom(this.value);
223 this.value = link.getValue().toByteArray();
224 if (this.value.length >= 1) {
225 map = deserializeObjectFromValue(linkKryo.get());
226 } else {
227 map = new HashMap<>();
228 }
229 this.status = STATUS.values()[link.getStatus()];
230 return map;
231 } catch (InvalidProtocolBufferException e) {
232 log.error("{" + toString() + "}: Read Link: ", e);
233 return null;
Yuta HIGUCHIa341b112014-02-23 15:42:00 -0800234 }
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800235 }
236
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800237 @Override
238 public String toString() {
239 return "[RCLink " + src + "->" + dst + " STATUS:" + status + "]";
240 }
241
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800242 public static void main(String[] args) {
243 // TODO Auto-generated method stub
244
245 }
246
247}