blob: 79daa665481b72937f2d4529f33cbb90d5b07b40 [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 {
25 @SuppressWarnings("unused")
26 private static final Logger log = LoggerFactory.getLogger(RCLink.class);
27
28 private static final ThreadLocal<Kryo> linkKryo = new ThreadLocal<Kryo>() {
29 @Override
30 protected Kryo initialValue() {
31 Kryo kryo = new Kryo();
32 kryo.setRegistrationRequired(true);
33 kryo.setReferences(false);
34 kryo.register(byte[].class);
35 kryo.register(byte[][].class);
36 kryo.register(HashMap.class);
37 // TODO check if we should explicitly specify EnumSerializer
38 kryo.register(STATUS.class);
39 return kryo;
40 }
41 };
42
43 public static class SwitchPort {
44 public final Long dpid;
45 public final Long number;
46
47 public SwitchPort(Long dpid, Long number) {
48 this.dpid = dpid;
49 this.number = number;
50 }
51
52 public byte[] getPortID() {
53 return RCPort.getPortID(dpid, number);
54 }
55
56 public byte[] getSwitchID() {
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -080057 return RCSwitch.getSwitchID(dpid);
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080058 }
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -080059
60 @Override
61 public String toString() {
62 return "(" + Long.toHexString(dpid) + "@" + number + ")";
63 }
64
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080065 }
66
67 public static final String GLOBAL_LINK_TABLE_NAME = "G:Link";
68
69 // FIXME these should be Enum or some number, not String
70 private static final String PROP_STATUS = "status";
71 private static final String PROP_SRC_SW_ID = "src-sw-id";
72 private static final String PROP_SRC_PORT_ID = "src-port-id";
73 private static final String PROP_DST_SW_ID = "dst-sw-id";
74 private static final String PROP_DST_PORT_ID = "dst-port-id";
75
76 // must not re-order enum members, ordinal will be sent over wire
77 public enum STATUS {
78 INACTIVE, ACTIVE;
79 }
80
81 private final SwitchPort src;
82 private final SwitchPort dst;
83 private STATUS status;
84
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080085 public static byte[] getLinkID(Long src_dpid, Long src_port_no,
86 Long dst_dpid, Long dst_port_no) {
Yuta HIGUCHIb5107282014-02-14 17:18:24 -080087 return LinkEvent.getLinkID(src_dpid, src_port_no, dst_dpid,
88 dst_port_no);
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -080089 }
90
Yuta HIGUCHI1ca1afa2014-02-04 19:33:57 -080091 public static StringBuilder keysToSB(Collection<byte[]> keys) {
92 StringBuilder sb = new StringBuilder();
93 sb.append("[");
94 boolean hasWritten = false;
95 for (byte[] key : keys) {
96 if (hasWritten) {
97 sb.append(", ");
98 }
99 sb.append(keyToString(key));
100 hasWritten = true;
101 }
102 sb.append("]");
103 return sb;
104 }
105
106 public static String keyToString(byte[] key) {
107 // For debug log
108 long[] tuple = getLinkTupleFromKey(key);
109 return "L" + "S" + HexString.toHexString(tuple[0]) + "P" + tuple[1]
110 + "S" + HexString.toHexString(tuple[2]) + "P" + tuple[3];
111 }
112
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800113 public static long[] getLinkTupleFromKey(byte[] key) {
114 return getLinkTupleFromKey(ByteBuffer.wrap(key));
115 }
116
117 public static long[] getLinkTupleFromKey(ByteBuffer keyBuf) {
118 long tuple[] = new long[4];
119 if (keyBuf.getChar() != 'L') {
120 throw new IllegalArgumentException("Invalid Link key");
121 }
122 long src_port_pair[] = RCPort.getPortPairFromKey(keyBuf.slice());
Yuta HIGUCHIb5107282014-02-14 17:18:24 -0800123 keyBuf.position(2 + PortEvent.PORTID_BYTES);
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800124 long dst_port_pair[] = RCPort.getPortPairFromKey(keyBuf.slice());
125
126 tuple[0] = src_port_pair[0];
127 tuple[1] = src_port_pair[1];
128 tuple[2] = dst_port_pair[0];
129 tuple[3] = dst_port_pair[1];
130
131 return tuple;
132 }
133
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800134 public RCLink(Long src_dpid, Long src_port_no, Long dst_dpid,
135 Long dst_port_no) {
136 super(RCTable.getTable(GLOBAL_LINK_TABLE_NAME), getLinkID(src_dpid,
137 src_port_no, dst_dpid, dst_port_no));
138
139 src = new SwitchPort(src_dpid, src_port_no);
140 dst = new SwitchPort(dst_dpid, dst_port_no);
141 status = STATUS.INACTIVE;
142 }
143
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800144 /**
145 * Get an instance from Key.
146 *
147 * @note You need to call `read()` to get the DB content.
148 * @param key
149 * @return RCLink instance
150 */
151 public static <L extends RCObject> L createFromKey(byte[] key) {
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800152 long linkTuple[] = getLinkTupleFromKey(key);
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800153 @SuppressWarnings("unchecked")
154 L l = (L) new RCLink(linkTuple[0], linkTuple[1], linkTuple[2],
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800155 linkTuple[3]);
Yuta HIGUCHI10eebea2014-02-03 10:41:41 -0800156 return l;
157 }
158
159 public static Iterable<RCLink> getAllLinks() {
160 return new LinkEnumerator();
161 }
162
163 public static class LinkEnumerator implements Iterable<RCLink> {
164
165 @Override
166 public Iterator<RCLink> iterator() {
167 return new LinkIterator();
168 }
169 }
170
171 public static class LinkIterator extends ObjectIterator<RCLink> {
172
173 public LinkIterator() {
174 super(RCTable.getTable(GLOBAL_LINK_TABLE_NAME));
175 }
176
177 @Override
178 public RCLink next() {
179 JRamCloud.Object o = enumerator.next();
180 RCLink e = RCLink.createFromKey(o.key);
181 e.setValueAndDeserialize(o.value, o.version);
182 return e;
183 }
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800184 }
185
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800186 public STATUS getStatus() {
187 return status;
188 }
189
190 public void setStatus(STATUS status) {
191 this.status = status;
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800192 }
193
194 public SwitchPort getSrc() {
195 return src;
196 }
197
198 public SwitchPort getDst() {
199 return dst;
200 }
201
202 public byte[] getId() {
203 return getKey();
204 }
205
206 @Override
207 public void serializeAndSetValue() {
208 Map<Object, Object> map = getObjectMap();
209
Yoshi Muroi212e5ca2014-02-20 22:42:37 -0800210 LinkProperty.Builder link = LinkProperty.newBuilder();
211 link.setSrcSwId(ByteString.copyFrom(src.getSwitchID()));
212 link.setSrcPortId(ByteString.copyFrom(src.getPortID()));
213 link.setDstSwId(ByteString.copyFrom(dst.getSwitchID()));
214 link.setDstPortId(ByteString.copyFrom(dst.getPortID()));
215 link.setStatus(status.ordinal());
216
217 if (!map.isEmpty()) {
218 serializeAndSetValue(linkKryo.get(), map);
219 link.setValue(ByteString.copyFrom(this.getSerializedValue()));
220 }
221
222 this.value = link.build().toByteArray();
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800223 }
224
225 @Override
226 public Map<Object, Object> deserializeObjectFromValue() {
Yoshi Muroi212e5ca2014-02-20 22:42:37 -0800227 LinkProperty link = null;
228 Map<Object, Object> map = null;
229 try {
230 link = LinkProperty.parseFrom(this.value);
231 this.value = link.getValue().toByteArray();
232 if (this.value.length >= 1) {
233 map = deserializeObjectFromValue(linkKryo.get());
234 } else {
235 map = new HashMap<>();
236 }
237 this.status = STATUS.values()[link.getStatus()];
238 return map;
239 } catch (InvalidProtocolBufferException e) {
240 log.error("{" + toString() + "}: Read Link: ", e);
241 return null;
242 }
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800243 }
244
Yuta HIGUCHIc9d06ef2014-01-31 15:55:12 -0800245 @Override
246 public String toString() {
247 return "[RCLink " + src + "->" + dst + " STATUS:" + status + "]";
248 }
249
Yuta HIGUCHI1ef85c42014-01-29 17:23:21 -0800250 public static void main(String[] args) {
251 // TODO Auto-generated method stub
252
253 }
254
255}