Commit 9f2e1cf72f92cab43e23f0734494eb7bbdcd8b0b

Authored by adumas
1 parent ffceab69

export of stats

src/main/java/net/floodlightcontroller/pelstats/PELStats.java
... ... @@ -39,8 +39,10 @@ import org.openflow.protocol.Pel.PelThresholdData;
39 39 import org.openflow.protocol.Pel.PelVendorHeader;
40 40 import org.openflow.protocol.Pel.StatisticReplyBody;
41 41 import org.openflow.protocol.Pel.StatisticsReplyParser;
  42 +import org.openflow.protocol.Pel.statistics.StatisticVoIP_SIP;
42 43 import org.openflow.protocol.Pel.statistics.VideoMetricDevice;
43 44 import org.openflow.protocol.Pel.threshold.PelVendorExtension;
  45 +import org.openflow.protocol.Pel.statistics.StatisticVoIP;
44 46 import org.openflow.protocol.Pel.statistics.StatisticVoIP_CAC;
45 47 import org.openflow.protocol.statistics.OFStatistics;
46 48 import org.openflow.protocol.statistics.OFVendorStatistics;
... ... @@ -63,8 +65,10 @@ public class PELStats implements IFloodlightModule, IOFMessageListener, RestAPIP
63 65 //holds all the received threshold messages
64 66 public static ConcurrentHashMap<IOFSwitch, List<ThresholdMessage>> thresholdMap;
65 67  
  68 + public static ConcurrentHashMap<Integer, List<double[]>> callStatsMap;
  69 + public static ConcurrentHashMap<IOFSwitch,List<double[][]>> statsMap;
66 70  
67   - //public static ConcurrentHashMap<IOFSwitch, List<Integer>> PortsCallsMap;
  71 + public static ConcurrentHashMap<IOFSwitch, List<Integer>> portsCallsMap;
68 72  
69 73 private double previousMos=-1;
70 74  
... ... @@ -109,6 +113,38 @@ public class PELStats implements IFloodlightModule, IOFMessageListener, RestAPIP
109 113  
110 114 receivedStatistics.addStatistic(sw, srb.getIPsrc(), srb.getIPdst(), srb.getStatistic());
111 115  
  116 + /*if (srb.getStatistic().getType()==6){
  117 + List<Integer> SwitchPorts=new ArrayList<Integer>(portsCallsMap.get(sw));
  118 + int[] RTPPorts = ((StatisticVoIP_SIP)srb.getStatistic()).getRTPPorts();
  119 +
  120 + if (enabledStatistics.get(sw).contains(new Integer(8))){//If the queue management is enabled on this switch
  121 + for (Object obj : RTPPorts){ //For each call on the switch
  122 + if (!SwitchPorts.contains(obj)){ //if the call isn't already assigned to a queue
  123 +
  124 + }
  125 + }
  126 + }
  127 +
  128 +
  129 + }*/
  130 + if (srb.getStatistic().getType()==5){
  131 + //System.out.println("Getting stat5");
  132 + double[][] stats= ((StatisticVoIP)srb.getStatistic()).getStats();
  133 + //System.out.println("stats received: "+stats[0][0]);
  134 + List<double[][]> calls=new ArrayList<double[][]>();
  135 + //System.out.println("calls memory attibution");
  136 + if (statsMap.get(sw)!=null) {
  137 + //System.out.println("statsmap.get not null");
  138 + calls=new ArrayList<double[][]>(statsMap.get(sw));
  139 + //System.out.println("Stats found");
  140 + }
  141 + //System.out.println("calls created");
  142 + calls.add(stats);
  143 + //System.out.println("Stats added to call");
  144 + statsMap.put(sw, calls);
  145 + //System.out.println("Stats added to map");
  146 +
  147 + }
112 148 if (srb.getStatistic().getType()==7){
113 149 double mos= ((StatisticVoIP_CAC)srb.getStatistic()).getMos();
114 150 sendThreshold(sw,mos,cntx);
... ... @@ -209,6 +245,9 @@ public class PELStats implements IFloodlightModule, IOFMessageListener, RestAPIP
209 245 receivedStatistics = new ReceivedStatistics();
210 246 PelVendorExtension.initialize();
211 247 PELStats.enabledStatistics = new ConcurrentHashMap<IOFSwitch, List<Integer>>();
  248 + PELStats.portsCallsMap=new ConcurrentHashMap<IOFSwitch, List<Integer>>();
  249 + PELStats.callStatsMap=new ConcurrentHashMap<Integer, List<double[]>>() ;
  250 + PELStats.statsMap=new ConcurrentHashMap<IOFSwitch, List<double[][]>>() ;
212 251 requestThread.start();
213 252 }
214 253  
... ...
src/main/java/net/floodlightcontroller/pelstats/rest/RESTExportStats.java 0 → 100644
  1 +package net.floodlightcontroller.pelstats.rest;
  2 +
  3 +import java.io.FileNotFoundException;
  4 +import java.io.IOException;
  5 +import java.io.PrintWriter;
  6 +import java.util.ArrayList;
  7 +import java.util.Date;
  8 +import java.util.List;
  9 +import java.util.Map;
  10 +import java.util.concurrent.ConcurrentHashMap;
  11 +
  12 +import javax.swing.JOptionPane;
  13 +
  14 +import net.floodlightcontroller.core.IOFSwitch;
  15 +import net.floodlightcontroller.pelstats.PELStats;
  16 +import net.floodlightcontroller.pelstats.rest.RESTQueue.StatEnable;
  17 +
  18 +import org.openflow.protocol.OFFlowMod;
  19 +import org.openflow.protocol.OFMatch;
  20 +import org.openflow.protocol.OFStatisticsRequest;
  21 +import org.openflow.protocol.Pel.IPAddress;
  22 +import org.openflow.protocol.Pel.PelVendorHeader;
  23 +import org.openflow.protocol.Pel.SetConfigurationMessage;
  24 +import org.openflow.protocol.Pel.statistics.Statistic;
  25 +import org.openflow.protocol.action.OFAction;
  26 +import org.openflow.protocol.action.OFActionEnqueue;
  27 +import org.openflow.protocol.statistics.OFPortStatisticsRequest;
  28 +import org.openflow.protocol.statistics.OFStatistics;
  29 +import org.openflow.protocol.statistics.OFStatisticsType;
  30 +import org.restlet.resource.Get;
  31 +import org.restlet.resource.ServerResource;
  32 +
  33 +public class RESTExportStats extends ServerResource{
  34 + public static ConcurrentHashMap<IOFSwitch, List<StatEnable>> enabledStats = new ConcurrentHashMap<IOFSwitch, List<StatEnable>>();
  35 +
  36 + class StatEnable {
  37 +
  38 + public StatEnable() {
  39 + }
  40 +
  41 + }
  42 +
  43 + @Get
  44 + public String retrieve() {
  45 +
  46 + String switchId = (String) getRequestAttributes().get("idSwitch");
  47 + String sIdVoip = (String) getRequestAttributes().get("idVoip");
  48 + int idVoip;
  49 +
  50 +
  51 +
  52 + // create SET CONFIG message
  53 + System.out.println("Exporting stats(REST):");
  54 + System.out.println(" Switch : " + switchId);
  55 + System.out.println(" call ID : " + sIdVoip);
  56 +
  57 +
  58 + SetConfigurationMessage setConfigMsg = new SetConfigurationMessage();
  59 +
  60 +
  61 + try {
  62 + idVoip = Integer.parseInt(sIdVoip);
  63 + if(idVoip<0)return "{\"resultCode\" : 0, \"error\" : \"Invalid idVoip value \"}";
  64 + } catch (Exception e) {
  65 + return "{\"resultCode\" : 0, \"error\" : \"Invalid idVoip value \"}";
  66 + }
  67 +
  68 +
  69 + IOFSwitch mySwitch = null;
  70 + for (IOFSwitch itSw : PELStats.floodlightProvider.getSwitches().values()) {
  71 + if (itSw.getStringId().equals(switchId)) {
  72 + mySwitch = itSw;
  73 + }
  74 + }
  75 + if (mySwitch == null) {
  76 + return "{\"resultCode\" : 0, \"error\" : \"The switch " + switchId
  77 + + " doesn't exist\"}";
  78 + }
  79 + System.out.println("-> starting stats export from switch "
  80 + + mySwitch.getStringId());
  81 +
  82 +
  83 +
  84 +
  85 +
  86 + PrintWriter out=null;
  87 + try{
  88 + out = new PrintWriter("statsExport.txt");
  89 +
  90 + //Retrieving all stats
  91 + ConcurrentHashMap<Double, List<double[]>> callsStatsMap = new ConcurrentHashMap<Double, List<double[]>>();
  92 + List<double[]> callsStats=new ArrayList<double[]>();
  93 + double callID;
  94 +
  95 + for (double[][] list:PELStats.statsMap.get(mySwitch)){
  96 +
  97 + for (int i=0;i<list.length;i++){
  98 + callID=new Double(list[i][0]);
  99 + if (callsStatsMap.get(callID)!=null) {
  100 +
  101 + callsStats=new ArrayList<double[]>(callsStatsMap.get(callID));
  102 + }
  103 + callsStats.add(list[i]);
  104 + callsStatsMap.put(callID, callsStats);
  105 + }
  106 +
  107 + }
  108 +
  109 + if (idVoip==0){
  110 + for (Map.Entry<Double, List<double[]>> entry : callsStatsMap.entrySet()){
  111 + out.println("Call:\t"+entry.getKey());
  112 + out.println("Elapsed Time (s)\tSSRC0\tiMOS0\tLoss0 (%)\tJitter0 (ms)\tDelay0 (ms)\tSSRC1\tiMOS1\tLoss1 (%)\tJitter1 (ms)\tDelay1 (ms)");
  113 + for (double[] statLine : entry.getValue()){
  114 + String line=new String();
  115 + for (int i=1;i<12;i++){
  116 + line+=statLine[i]+"\t";
  117 + }
  118 + out.println(line);
  119 + System.out.println(line);
  120 + }
  121 + out.println("\n");
  122 + }
  123 + }
  124 + else{
  125 + out.println("Call:\t"+idVoip);
  126 + out.println("Elapsed Time (s)\tSSRC0\tiMOS0\tLoss0 (%)\tJitter0 (ms)\tDelay0 (ms)\tSSRC1\tiMOS1\tLoss1 (%)\tJitter1 (ms)\tDelay1 (ms)");
  127 + for (double[] statLine : callsStatsMap.get(new Double(idVoip))){
  128 + String line=new String();
  129 + for (int i=0;i<12;i++){
  130 + line+=statLine[i]+"\t";
  131 + }
  132 + out.println(line);
  133 + System.out.println(line);
  134 + }
  135 +
  136 +
  137 + }
  138 + //out.println(PELStats.statsMap.get(mySwitch).get(0)[0][0]);
  139 + System.out.println("-> stats export successful");
  140 + }catch (FileNotFoundException e) {
  141 + System.out.println("Error during the stats export");
  142 + e.printStackTrace();
  143 + } finally {
  144 + if (out != null) out.close();
  145 + }
  146 +
  147 +
  148 +
  149 + return "{\"resultCode\" : 1, \"error\" : \"\"}";
  150 + }
  151 +}
0 152 \ No newline at end of file
... ...
src/main/java/net/floodlightcontroller/pelstats/rest/StatsRoutable.java
... ... @@ -37,6 +37,7 @@ public class StatsRoutable implements RestletRoutable{
37 37 router.attach("/switch/{idSwitch}/{enable}/type/{metricType}/opt/{ipSrc}/{ipDst}/{threshold}/{idVoip}/json",RESTVoip.class);
38 38 router.attach("/switch/{idSwitch}/{enable}/type/{metricType}/cac/{nominalNbOfCalls}/{lowMos}/{highMos}/{meanMos}/{cir}/{maxBurst}/json",RESTCallAdmissionControl.class);
39 39 router.attach("/switch/{idSwitch}/{enable}/type/{metricType}/queue/{action}/{idQueue}/{priority}/{protocol}/json",RESTQueue.class);
  40 + router.attach("/switch/{idSwitch}/export/{idVoip}/json",RESTExportStats.class);
40 41  
41 42 return router;
42 43 }
... ...
src/main/java/org/openflow/protocol/Pel/statistics/StatisticVoIP.java
... ... @@ -29,7 +29,7 @@ public class StatisticVoIP extends Statistic{
29 29  
30 30 @Override
31 31 public void getData(ByteBuffer b) {
32   -
  32 +
33 33 nbCalls=b.getInt();
34 34 System.out.println("nbCalls: "+nbCalls);
35 35  
... ... @@ -66,7 +66,26 @@ public class StatisticVoIP extends Statistic{
66 66 }
67 67 }
68 68 }
69   -
  69 + public double[][] getStats(){
  70 + double[][] table = null;
  71 + if (nbCalls>0)table=new double[nbCalls][12];
  72 + for (int i=0;i<nbCalls;i++){
  73 +
  74 + table[i][0]=(double)callID[i];
  75 + table[i][1]=(double)elapsedTime[i];
  76 + table[i][2]=(double)SSRC0[i];
  77 + table[i][3]=imos0[i];
  78 + table[i][4]=loss0[i];
  79 + table[i][5]=jitter0[i];
  80 + table[i][6]=delay0[i];
  81 + table[i][7]=(double)SSRC1[i];
  82 + table[i][8]=imos1[i];
  83 + table[i][9]=loss1[i];
  84 + table[i][10]=jitter1[i];
  85 + table[i][11]=delay1[i];
  86 + }
  87 + return table;
  88 + }
70 89 private double getDoubleBytes(ByteBuffer b, int nbBytes){
71 90 byte[] bytes=new byte[4];
72 91 byte zero=0;
... ...
src/main/java/org/openflow/protocol/Pel/statistics/StatisticVoIP_SIP.java
... ... @@ -126,6 +126,10 @@ public class StatisticVoIP_SIP extends Statistic{
126 126 return toJson;
127 127  
128 128 }
  129 +
  130 + public int[] getRTPPorts(){
  131 + return this.RTPPort;
  132 + }
129 133  
130 134 private String statusString(int i) {
131 135 String returnString = new String();
... ...
src/main/resources/web/js/models/voipmodel.js
... ... @@ -100,18 +100,20 @@ window.allStatsCollection = Backbone.Collection.extend({
100 100 //console.log("\t\tCall already exist:"+scscm.id);
101 101 }
102 102  
103   -
  103 + if(scscm.scsc.length>=15){
  104 + scscm.scsc.shift();
  105 + }
104 106 //console.log("\t\t\tAdding "+vs.elapsedTime +" on call "+scscm.id);
105 107 var stat= new callStatsModel();
106 108 stat.elapsedTime=vs.elapsedTime;
107 109 stat.iMOS0=vs.iMOS0;
108   - stat.delay0=vs.delay0;
  110 + /*stat.delay0=vs.delay0;
109 111 stat.jitter0=vs.jitter0;
110   - stat.loss0=vs.loss0;
  112 + stat.loss0=vs.loss0;*/
111 113 stat.iMOS1=vs.iMOS1;
112   - stat.delay1=vs.delay1;
  114 + /*stat.delay1=vs.delay1;
113 115 stat.jitter1=vs.jitter1;
114   - stat.loss1=vs.loss1;
  116 + stat.loss1=vs.loss1;*/
115 117 scscm.scsc.add(stat);
116 118 //console.log("stat added: "+stat.elapsedTime +" : "+vs.elapsedTime);
117 119  
... ...
src/main/resources/web/js/views/voip.js
... ... @@ -131,7 +131,7 @@ window.VoIPGraphView = Backbone.View.extend({
131 131  
132 132  
133 133  
134   -
  134 +/*
135 135 window.Stats0ListItemView = Backbone.View.extend({
136 136  
137 137 tagName:"tr",
... ... @@ -170,20 +170,20 @@ window.Stats1ListItemView = Backbone.View.extend({
170 170 return this;
171 171 },
172 172  
173   -});
  173 +});*/
174 174  
175 175 window.VoIPView = Backbone.View.extend({
176 176  
177 177 model: VoIP,
178 178  
179   - defaults: {
  179 + /*defaults: {
180 180 historic0View:null,
181 181 historic1View:null,
182   - },
  182 + },*/
183 183  
184 184 events: {
185   - "click input[name=historic0]" : "showHistoric0",
186   - "click input[name=historic1]" : "showHistoric1",
  185 + //"click input[name=historic0]" : "showHistoric0",
  186 + "click input[name=export]" : "Export",
187 187 "click img" : "clicked",
188 188 },
189 189  
... ... @@ -200,44 +200,58 @@ window.VoIPView = Backbone.View.extend({
200 200 this.template = _.template(tpl.get('voip'));
201 201 //this.model.bind("change", this.render, this);
202 202 this.model.bind("add", this.render, this);
203   - historic0View=false;
204   - historic1View=false;
  203 + /*historic0View=false;
  204 + historic1View=false;*/
205 205 },
206 206  
207 207 render:function (eventName) {
208 208 $(this.el).html(this.template(this.model.toJSON()));
209 209 //console.log("voip render: "+v.id+" : "+v.idswitch);
210 210  
211   - //rendering the stats historic
  211 + /*/rendering the stats historic
212 212 if(allStats.get(v.idswitch).ssc.get(v.id)!=undefined && historic0View==true){
213 213 _.each(allStats.get(v.idswitch).ssc.get(v.id).scsc.models, function (stat) {
214 214 $(this.el).find('table.call0-table > tbody')
215 215 .append(new Stats0ListItemView({model:stat}).render().el);
216 216 }, this);
217   - }
  217 + }//*//*
218 218 if(allStats.get(v.idswitch).ssc.get(v.id)!=undefined && historic1View==true){
219 219 _.each(allStats.get(v.idswitch).ssc.get(v.id).scsc.models, function (stat) {
220 220 $(this.el).find('table.call1-table > tbody')
221 221 .append(new Stats1ListItemView({model:stat}).render().el);
222 222 }, this);
223   - }
  223 + }//*/
224 224  
225   - if (historic0View==true){$(this.el).find("#2").toggle();}
226   - if (historic1View==true){$(this.el).find("#3").toggle();}
  225 + /*if (historic0View==true){$(this.el).find("#2").toggle();}
  226 + if (historic1View==true){$(this.el).find("#3").toggle();}*/
227 227 $(this.el).addClass("src0");
228 228 return this;
229 229 },
230 230  
231   - showHistoric0:function(e){
232   - if (historic0View==true){historic0View=false;}
233   - else {historic0View=true;}
  231 + Export:function(e){
  232 + /*if (historic0View==true){historic0View=false;}
  233 + else {historic0View=true;}*/
  234 + var self=this;
  235 + console.log("Export on "+self.model.idswitch);
  236 + $.ajax({
  237 + url:hackBase + '/wm/iptv/switch/'+self.model.idswitch+'/export/'+v.id+'/json',
  238 + dataType:"json",
  239 + success:function (data) {
  240 +
  241 + if ( data.resultCode == 0 ) alert(data.error);
  242 + else {
  243 + console.log("Export started for call "+v.id+" on "+self.model.idswitch);
  244 + }
  245 + },
  246 + });
  247 +
234 248 },
235 249  
236   - showHistoric1:function(e){
  250 + /*showHistoric1:function(e){
237 251 //$(this.el).find("#3").toggle();
238 252 if (historic1View==true){historic1View=false;}
239 253 else {historic1View=true;}
240   - },
  254 + },*/
241 255  
242 256  
243 257 });
... ... @@ -264,6 +278,7 @@ window.VoIPListView = Backbone.View.extend({
264 278  
265 279 events: {
266 280 "click img" : "clicked",
  281 + "click input[name=export]" : "Export",
267 282 },
268 283 clicked:function(e){
269 284 if( $(e.currentTarget).attr("alt") == "update" ){
... ... @@ -294,6 +309,24 @@ window.VoIPListView = Backbone.View.extend({
294 309 }, this);
295 310 return this;
296 311 },
  312 + Export:function(e){
  313 + /*if (historic0View==true){historic0View=false;}
  314 + else {historic0View=true;}*/
  315 + var self=this;
  316 + console.log("Export on "+self.model.idswitch);
  317 + $.ajax({
  318 + url:hackBase + '/wm/iptv/switch/'+self.model.idswitch+'/export/0/json',
  319 + dataType:"json",
  320 + success:function (data) {
  321 +
  322 + if ( data.resultCode == 0 ) alert(data.error);
  323 + else {
  324 + console.log("Export started for "+self.model.idswitch);
  325 + }
  326 + },
  327 + });
  328 +
  329 + },
297 330  
298 331 });
299 332  
... ...
src/main/resources/web/tpl/voip-list.html
... ... @@ -10,8 +10,16 @@
10 10 </table>
11 11  
12 12 <div class="page-header">
13   - <h1>Calls (<%= nvoip %>)</h1>
  13 + <table style="width: 770px;">
  14 + <tbody>
  15 + <tr>
  16 + <td><h1>Calls (<%= nvoip %>)</h1></td>
  17 + <td style="text-align: center;"><input value="Export" name="export" type="button"></td>
  18 + </tr>
  19 + </tbody>
  20 + </table>
14 21 </div>
  22 +
15 23  
16 24 <table class="table table-striped voipList-table">
17 25 <thead><tr><th>Call ID</th><th>Caller</th><th>Receiver</th><th>Connected Since</th></tr></thead>
... ...
src/main/resources/web/tpl/voip.html
... ... @@ -13,24 +13,26 @@
13 13 </table>
14 14  
15 15 <div class="page-header">
16   - <h1>Flows Stats</h1>
  16 + <table style="width: 90%;">
  17 + <tbody><tr><td><h1>Flows Stats</h1></td><td style="width: 0px;"> </td><td style="text-align: right;"><a href="/voip/<%= idswitch %>/<%= idvoip %>/graph" >Graph</a>
  18 + </td><td style="text-align: center;"><input value="Export" type="button" name="export"></td></tr>
  19 + </tbody></table>
17 20 </div>
18 21  
19 22 <table class="table table-striped voip-table">
20   - <!--<tr><th>SSRC</th><th>src</th><th>dst</th><th>iMOS</th><th>Delay</th><th>Jitter</th><th>Loss</th><th><form action="/voip/<%= idswitch %>/<%= idvoip %>/graph" method="get"><button>Graph</button></form></th></tr>-->
21 23 <tr><th>SSRC</th><th>src</th><th>dst</th><th>iMOS</th><th>Delay (ms)</th><th>Jitter (ms)</th><th>Loss (%)</th><th><a href="/voip/<%= idswitch %>/<%= idvoip %>/graph" >Graph</a></th></tr>
22 24 <tr id="0">
23   - <td><%= id0 %></a></td>
  25 + <td><%= id0 %></td>
24 26 <td><%= src0 %></td>
25 27 <td><%= dst0 %></td>
26 28 <td><%= iMOS0 %></td>
27 29 <td><%= delay0 %></td>
28 30 <td><%= jitter0 %></td>
29 31 <td><%= loss0 %></td>
30   - <td><input type="button" value="historic" name="historic0"/><span> </span></td>
  32 + <!--<td><input type="button" value="historic" name="historic0"/><span> </span></td>-->
31 33 </tr>
32 34  
33   - <tr id="2" style="display:none">
  35 + <!--<tr id="2" style="display:none">
34 36 <td></td><td></td><td colspan="5">
35 37 <div style="max-height:100px;overflow:auto;">
36 38 <table class="table table-striped call0-table">
... ... @@ -43,23 +45,23 @@
43 45 </tr>
44 46 <tbody>
45 47 <!-- switches will be inserted here by SwitchListView:render -->
46   - </tbody>
  48 + <!--</tbody>
47 49 </table>
48 50 </div>
49 51 </td>
50   - </tr>
  52 + </tr>-->
51 53  
52 54 <tr id="1">
53   - <td><%= id1 %></a></td>
  55 + <td><%= id1 %></td>
54 56 <td><%= src1 %></td>
55 57 <td><%= dst1 %></td>
56 58 <td><%= iMOS1 %></td>
57 59 <td><%= delay1 %></td>
58 60 <td><%= jitter1 %></td>
59 61 <td><%= loss1 %></td>
60   - <td><input type="button" value="historic" name="historic1"/><span> </span></td>
  62 + <!--<td><input type="button" value="historic" name="historic1"/><span> </span></td>-->
61 63 </tr>
62   - <tr id="3" style="display:none">
  64 + <!--<tr id="3" style="display:none">
63 65 <td></td><td></td><td colspan="5">
64 66 <div style="max-height:100px;overflow:auto;">
65 67 <table class="table table-striped call1-table">
... ... @@ -72,11 +74,11 @@
72 74 </tr>
73 75 <tbody>
74 76 <!-- switches will be inserted here by SwitchListView:render -->
75   - </tbody>
  77 + <!--</tbody>
76 78 </table>
77 79 </div>
78 80 </td>
79   - </tr>
  81 + </tr>-->
80 82 </table>
81 83 </div>
82 84 </div>
... ...