blob: 285c912cd148478a1c0a3c627dd0ab208efe9dab [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001/*
2 Copyright 2012 IBM
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17window.Switch = Backbone.Model.extend({
18
19 urlRoot:"/wm/core/switch/",
20
21 defaults: {
22 datapathDescription: '',
23 hardwareDescription: '',
24 manufacturerDescription: '',
25 serialNumber: '',
26 softwareDescription: '',
27 flowCount: ' ',
28 packetCount: ' ',
29 byteCount: ' ',
30 },
31
32 initialize:function () {
33 var self = this;
34
35 //console.log("fetching switch " + this.id + " desc")
36 $.ajax({
37 url:hackBase + "/wm/core/switch/" + self.id + '/desc/json',
38 dataType:"json",
39 success:function (data) {
40 //console.log("fetched switch " + self.id + " desc");
41 //console.log(data[self.id][0]);
42 self.set(data[self.id][0]);
43 }
44 });
45
46 //console.log("fetching switch " + this.id + " aggregate")
47 $.ajax({
48 url:hackBase + "/wm/core/switch/" + self.id + '/aggregate/json',
49 dataType:"json",
50 success:function (data) {
51 //console.log("fetched switch " + self.id + " aggregate");
52 //console.log(data[self.id][0]);
53 self.set(data[self.id][0]);
54 }
55 });
56 self.trigger('add');
57 this.ports = new PortCollection();
58 this.flows = new FlowCollection();
59 //this.loadPorts();
60 //this.loadFlows();
61 },
62
63 fetch:function () {
64 this.initialize()
65 },
66
67 loadPorts:function () {
68 var self = this;
69 //console.log("fetching switch " + this.id + " ports")
70 //console.log("fetching switch " + this.id + " features")
71 $.when($.ajax({
72 url:hackBase + "/wm/core/switch/" + self.id + '/port/json',
73 dataType:"json",
74 success:function (data) {
75 //console.log("fetched switch " + self.id + " ports");
76 //console.log(data[self.id]);
77 // create port models
78 _.each(data[self.id], function(p) {
79 p.id = self.id+'-'+p.portNumber;
80 p.dropped = p.receiveDropped + p.transmitDropped;
81 p.errors = p.receiveCRCErrors + p.receiveErrors + p.receiveOverrunErrors +
82 p.receiveFrameErrors + p.transmitErrors;
83 // this is a knda kludgy way to merge models
84 var m = self.ports.get(p.id);
85 if(m) {
86 m.set(p, {silent: true});
87 } else {
88 self.ports.add(p, {silent: true});
89 }
90 //console.log(p);
91 });
92 }
93 }),
94 $.ajax({
95 url:hackBase + "/wm/core/switch/" + self.id + '/features/json',
96 dataType:"json",
97 success:function (data) {
98 //console.log("fetched switch " + self.id + " features");
99 //console.log(data[self.id]);
100 // update port models
101 _.each(data[self.id].ports, function(p) {
102 p.id = self.id+'-'+p.portNumber;
103 if(p.name != p.portNumber) {
104 p.name = p.portNumber + ' (' + p.name + ')';
105 }
106 p.status = '';
107 p.status += (p.state & 1) ? 'DOWN' : 'UP';
108 switch(p.currentFeatures & 0x7f) {
109 case 1:
110 p.status += ' 10 Mbps';
111 break;
112 case 2:
113 p.status += ' 10 Mbps FDX';
114 break;
115 case 4:
116 p.status += ' 100 Mbps';
117 break;
118 case 8:
119 p.status += ' 100 Mbps FDX';
120 break;
121 case 16:
122 p.status += ' 1 Gbps'; // RLY?
123 break;
124 case 32:
125 p.status += ' 1 Gbps FDX';
126 break;
127 case 64:
128 p.status += ' 10 Gbps FDX';
129 break;
130 }
131 // TODO parse copper/fiber, autoneg, pause
132
133 // this is a knda kludgy way to merge models
134 var m = self.ports.get(p.id);
135 if(m) {
136 m.set(p, {silent: true});
137 } else {
138 self.ports.add(p, {silent: true});
139 }
140 //console.log(p);
141 });
142 }
143 })).done(function() {
144 self.ports.trigger('add'); // batch redraws
145 });
146 },
147
148 loadFlows:function () {
149 var self = this;
150 //console.log("fetching switch " + this.id + " flows")
151 $.ajax({
152 url:hackBase + "/wm/core/switch/" + self.id + '/flow/json',
153 dataType:"json",
154 success:function (data) {
155 //console.log("fetched switch " + self.id + " flows");
156 var flows = data[self.id];
157 //console.log(flows);
158
159 // create flow models
160 var i = 0;
161 _.each(flows, function(f) {
162 f.id = self.id + '-' + i++;
163
164 // build human-readable match
165 f.matchHTML = '';
166 if(!(f.match.wildcards & (1<<0))) { // input port
167 f.matchHTML += "port=" + f.match.inputPort + ", ";
168 }
169 if(!(f.match.wildcards & (1<<1))) { // VLAN ID
170 f.matchHTML += "VLAN=" + f.match.dataLayerVirtualLan + ", ";
171 }
172 if(!(f.match.wildcards & (1<<20))) { // VLAN prio
173 f.matchHTML += "prio=" + f.match.dataLayerVirtualLanPriorityCodePoint + ", ";
174 }
175 if(!(f.match.wildcards & (1<<2))) { // src MAC
176 f.matchHTML += "src=<a href='/host/" + f.match.dataLayerSource + "'>" +
177 f.match.dataLayerSource + "</a>, ";
178 }
179 if(!(f.match.wildcards & (1<<3))) { // dest MAC
180 f.matchHTML =+ "dest=<a href='/host/" + f.match.dataLayerDestination + "'>" +
181 f.match.dataLayerDestination + "</a>, ";
182 }
183 if(!(f.match.wildcards & (1<<4))) { // Ethertype
184 // TODO print a human-readable name instead of hex
185 f.matchHTML += "ethertype=" + f.match.dataLayerType + ", ";
186 }
187 if(!(f.match.wildcards & (1<<5))) { // IP protocol
188 // TODO print a human-readable name
189 f.matchHTML += "proto=" + f.match.networkProtocol + ", ";
190 }
191 if(!(f.match.wildcards & (1<<6))) { // TCP/UDP source port
192 f.matchHTML += "IP src port=" + f.match.transportSource + ", ";
193 }
194 if(!(f.match.wildcards & (1<<7))) { // TCP/UDP dest port
195 f.matchHTML += "IP dest port=" + f.match.transportDestination + ", ";
196 }
197 if(!(f.match.wildcards & (32<<8))) { // src IP
198 f.matchHTML += "src=" + f.match.networkSource + ", ";
199 }
200 if(!(f.match.wildcards & (32<<14))) { // dest IP
201 f.matchHTML += "dest=" + f.match.networkDestination + ", ";
202 }
203 if(!(f.match.wildcards & (1<<21))) { // IP TOS
204 f.matchHTML += "TOS=" + f.match.networkTypeOfService + ", ";
205 }
206 // remove trailing ", "
207 f.matchHTML = f.matchHTML.substr(0, f.matchHTML.length - 2);
208
209 // build human-readable action list
210 f.actionText = _.reduce(f.actions, function (memo, a) {
211 switch (a.type) {
212 case "OUTPUT":
213 return memo + "output " + a.port + ', ';
214 case "OPAQUE_ENQUEUE":
215 return memo + "enqueue " + a.port + ':' + a.queueId + ', ';
216 case "STRIP_VLAN":
217 return memo + "strip VLAN, ";
218 case "SET_VLAN_ID":
219 return memo + "VLAN=" + a.virtualLanIdentifier + ', ';
220 case "SET_VLAN_PCP":
221 return memo + "prio=" + a.virtualLanPriorityCodePoint + ', ';
222 case "SET_DL_SRC":
223 return memo + "src=" + a.dataLayerAddress + ', ';
224 case "SET_DL_DST":
225 return memo + "dest=" + a.dataLayerAddress + ', ';
226 case "SET_NW_TOS":
227 return memo + "TOS=" + a.networkTypeOfService + ', ';
228 case "SET_NW_SRC":
229 return memo + "src=" + a.networkAddress + ', ';
230 case "SET_NW_DST":
231 return memo + "dest=" + a.networkAddress + ', ';
232 case "SET_TP_SRC":
233 return memo + "src port=" + a.transportPort + ', ';
234 case "SET_TP_DST":
235 return memo + "dest port=" + a.transportPort + ', ';
236 }
237 }, "");
238 // remove trailing ", "
239 f.actionText = f.actionText.substr(0, f.actionText.length - 2);
240
241 //console.log(f);
242 self.flows.add(f, {silent: true});
243 });
244 self.flows.trigger('add');
245 }
246 });
247 },
248});
249
250window.SwitchCollection = Backbone.Collection.extend({
251
252 model:Switch,
253
254 initialize:function () {
255 var self = this;
256 //console.log("fetching switch list")
257 $.ajax({
258 url:hackBase + "/wm/core/controller/switches/json",
259 dataType:"json",
260 success:function (data) {
261 //console.log("fetched switch list: " + data.length);
262 //console.log(data);
263 _.each(data, function(sw) {self.add({id: sw['dpid'],
264 inetAddress: sw.inetAddress,
265 connectedSince: new Date(sw.connectedSince).toLocaleString()})});
266 }
267 });
268 },
269
270 fetch:function () {
271 this.initialize()
272 }
273
274
275});