Class: Scriptroute::Tulip::Train

Inherits:
Object
  • Object
show all
Defined in:
lib/scriptroute/tulip/helper.rb

Overview

generic train ################

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dsts, numpackets, resolution, types, ttls, shuffle = false) ⇒ Train

Returns a new instance of Train.



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/scriptroute/tulip/helper.rb', line 312

def initialize(dsts, numpackets, resolution, types, ttls, shuffle=false) 
  @dsts, @numpackets, @resolution, @types, @ttls, @shuffle = dsts, numpackets, resolution, types, ttls, shuffle;
  @reverse_ttls, @rem_srcs, @num_losses, @packets = Array.new(), Array.new(), Array.new(), Array.new();
  (@dsts).each_index { |i| 
    @packets[i], @reverse_ttls[i], @rem_srcs[i], @num_losses[i] = Array.new(),  Array.new(), Array.new(), 0;
  }

  num_dsts = @dsts.length;
  max_train = (MAX_TRAIN/num_dsts).floor;
  seq_id = 0; order = 0;
  allResponsePackets = Array.new();
  ( 0 .. (numpackets/max_train).ceil ).each { |trainnum|
    packetsThisRound = (numpackets < (trainnum+1)*max_train)? (numpackets - trainnum*max_train) : max_train;
    delayedPackets = Array.new();
    ( seq_id .. seq_id + packetsThisRound-1).each { |rep|
	
	##construct probe packets
	probes = Array.new();
	(@dsts).each_index { |i|
        case types[i]
        when "tcp"
   probes[i] = Scriptroute::TCP.new(12);
        when "udp"
   probes[i] = Scriptroute::UDP.new(12);
   probes[i].uh_dport = 33444 ## unknown effect; five-tuple balancing may occur
        when "echo"
   probes[i] = Scriptroute::ICMP.new(0)
          probes[i].icmp_type = Scriptroute::ICMP::ICMP_ECHO;
   probes[i].icmp_code = 0;
   probes[i].icmp_seq = rep;
        when "tstamp"
   probes[i] = Scriptroute::ICMP.new(0)
          probes[i].icmp_type = Scriptroute::ICMP::ICMP_TSTAMP;
   probes[i].icmp_code = 0;
   probes[i].icmp_seq = rep;
        else 
          raise("ERROR: unsupported packettype #{types[i]} in sendAndReceiveTrain\n");
 end	
 probes[i].ip_ttl = @ttls[i];
 probes[i].ip_dst = @dsts[i];
 @dsts[i] = probes[i].ip_dst; # accomplishes a name lookup so responses can be classified - nspring

	}

	##insert probe packets in the order desired
	(@dsts).each_index { |i|
 delay = (i==0)? resolution : 0;
 #puts "delay: #{delay} (#{i})";
 insert = (order + i) % num_dsts;
 delayedPackets.push(Struct::DelayedPacket.new(delay, probes[insert]));
 order = (order + 1) % num_dsts if (@shuffle);
	} 	  
    } ##each rep

    #puts "before real =  %.3f" % [Time.now.to_f*1000];
    allResponsePackets.push(Scriptroute::send_train(delayedPackets));
    #puts "after real =  %.3f" % [Time.now.to_f*1000];

  } ##each trainnum
  allResponsePackets.flatten!
  #allResponsePackets.sort!{ |a,b| a.probe.time <=> b.probe.time }

  allResponsePackets.each { |pr|
    if (pr and pr.probe and pr.probe.time) 
	i = getIndex(pr);
	@packets[i].push(pr);
	if (pr.response) then
 @reverse_ttls[i].push(pr.response.packet.ip_ttl) if !@reverse_ttls[i].index(pr.response.packet.ip_ttl);
 @rem_srcs[i].push(pr.response.packet.ip_src) if !@rem_srcs[i].index(pr.response.packet.ip_src);
	else
 @num_losses[i] += 1;
	end
    end
  }

  # nspring thinks the following is a no-op.
  (@dsts).each_index { |i| 
    @packets[i].sort! { |a,b| a.probe.time <=> b.probe.time }
  }

  ##check sanity of the train
  (@dsts).each_index { |i|
    if (@reverse_ttls[i].length > 1) 
	puts "WARNING: too many reverse TTLs for index #{i}: #{@reverse_ttls[i].join(" ")}";
    end
    
    if (@rem_srcs[i].length > 1) 
	puts "WARNING: too many remote sources for index #{i}: #{@rem_srcs[i].join(" ")}";
    end

    ##todo: should really check a pattern in losses 
    ##      to distinguish between high loss rate and rate-limiting
    if (@num_losses[i] > 0.2*@numpackets) 
	#STDERR.puts "WARNING: too many losses #{@num_losses[i]} for index #{i}";
    end
  }

end

Instance Attribute Details

#dstsObject (readonly)

Returns the value of attribute dsts.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def dsts
  @dsts
end

#num_lossesObject (readonly)

Returns the value of attribute num_losses.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def num_losses
  @num_losses
end

#numpacketsObject (readonly)

Returns the value of attribute numpackets.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def numpackets
  @numpackets
end

#packetsObject (readonly)

Returns the value of attribute packets.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def packets
  @packets
end

#resolutionObject (readonly)

Returns the value of attribute resolution.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def resolution
  @resolution
end

#reverse_ttlsObject (readonly)

Returns the value of attribute reverse_ttls.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def reverse_ttls
  @reverse_ttls
end

#shuffleObject (readonly)

Returns the value of attribute shuffle.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def shuffle
  @shuffle
end

#ttlsObject (readonly)

Returns the value of attribute ttls.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def ttls
  @ttls
end

#typesObject (readonly)

Returns the value of attribute types.



283
284
285
# File 'lib/scriptroute/tulip/helper.rb', line 283

def types
  @types
end

Instance Method Details

#getIndex(pr) ⇒ Object



300
301
302
303
304
305
306
307
308
309
310
# File 'lib/scriptroute/tulip/helper.rb', line 300

def getIndex (pr)
  pkt = pr.probe.packet;
  @dsts.each_index { |i|
    if (pkt.ip_dst == @dsts[i] and  
 pkt.ip_ttl == @ttls[i] and 
 getType(pkt) == @types[i]) 
	return i;
    end
  }
  raise "ERROR: could not classify packet: #{pkt.to_s}";
end

#getType(pkt) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/scriptroute/tulip/helper.rb', line 285

def getType (pkt) 
  if (pkt.is_a?(Scriptroute::TCP)) 
    return "tcp";
  elsif (pkt.is_a?(Scriptroute::UDP)) 
    return "udp";
  elsif (pkt.is_a?(Scriptroute::ICMP))
    if (pkt.icmp_type == Scriptroute::ICMP::ICMP_ECHO)
	return "echo";
    elsif (pkt.icmp_type == Scriptroute::ICMP::ICMP_TSTAMP)
	return "tstamp";
    end
  end
  raise "ERROR: unknown packet type: #{pkt.to_s}";
end

#to_sObject



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/scriptroute/tulip/helper.rb', line 411

def to_s
  str = "train: #{@dsts} #{@numpackets} #{@resolution} (#{@types}) (#{@ttls})\n";
  @packets[0].each_index { |i| 
    (@dsts).each_index { |j|
	pr = @packets[j][i];
	stime = pr.probe.time.to_f * 1000;
	srcid = pr.probe.packet.ip_id;
	rtt = (pr.probe and pr.response) ? (pr.response.time - pr.probe.time) * 1000 : -1;
	str += "#{@dsts[j]} %d %.3f %d " %[rtt, stime, srcid];
	if (@types[j] == "tstamp") then 
 rem_time =  (pr.response)? pr.response.packet.icmp_ttime : 0;
 ott = (pr.response)? stime - pr.response.packet.icmp_ttime : -1;
 str += "#{rem_time} %.3f " % [ott];
	end
    }
    str += "\n";
  }
  str += "losses: #{@num_losses.join(" ")}\n";
  return str;
end