packet_via_dmem 0.0.8 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0147a2a28aec0b7d80b8e8fc84b3ae62e228893f
4
- data.tar.gz: 231b1c57cbb1902621382913c3eab7c9d86e2c57
3
+ metadata.gz: 87a6a44720c7a589e77bee75c030bda1c59afee4
4
+ data.tar.gz: 3f05700efab522e4576b99d4c6a51c225d07cac4
5
5
  SHA512:
6
- metadata.gz: ec74f12df72f23334e86568b15a0e20f66ac7223fbc1d3072ae34d47f619d207353bb69b9d19168db4b071c0a12c4b0ee5cc214e4ce532f6f433b49e69ac9360
7
- data.tar.gz: e3772c982460028fd3d4fbc79a78cd1ce8dc4328fdb95db108cceaaeb3f2add2a32da506bd9230b853ab27c8cde1123e376f420022bdb46918ad379787a6e986
6
+ metadata.gz: 227fd4c042a6d5cd24bc3aa79eb9b3c59a5d4feb4c351bbaed301762ebc2bda825e7c2e1f98fb164e0f879b9f691ab2224e94d526438fbd0a596aeb9d8cb5aa5
7
+ data.tar.gz: dbd9cb160260210dba193663616b768fb075c404d54ddee39a6968d65501ab36d2c39c169ff5eec9947a241ffb2ebb695db7c1cdcce8783ea15ed73bee528b41
data/README.md CHANGED
@@ -83,27 +83,22 @@ To capture say packets with IP address 10.11.12.13
83
83
  ## Header format
84
84
  ### Received header
85
85
 
86
- * First byte is type of header?
87
- * 00 'lu packet' (i.e. whole packet was sent for lookup, i.e. small packet)
88
- * 10 'lu packet head' (i.e. only head of packet was sent for lookup, i.e. large packet)
89
-
90
- * Second and third byte appear to tell nothing about where packet came from,
91
- but more when it came from. Timing? Counter? Randomness?
92
-
93
- * Fourth byte is 0xf0 on MX80, tendency for last nibble to be 0. Perhaps src fabric stream? If it is zero, we get what seems to be trash (internal stuff?)
94
-
95
- * Fifth byte appears to be source port?
96
-
97
- * Sixth byte is perhaps source NPU? If it is zero, we get what seems to be trash (internal stuff)
98
-
99
- * value of fift+sixth seems to sometime indicate special cases
100
- * 0x1fff - Packet missing everything before IPv4 TTL, yet has some extra. I saw BGP from control-plane with this and also TCP/SMB2 with Seq1, it was transit, but perhaps it was via ARP resolve/punt and thus coming from control-plane?
101
- * 0x2000 - BFD frames from control-plane or LACP IPv4, if next byte is 1 like below, if next byte is 0 missing MACs too (+5bytes)
102
- * 0x4220 - Was LACP MPLS traffic, missing ethertype, MACs changed, 2 mystery bytes
103
- * 0x8000 - I need to pop 14 bytes extra
104
-
105
- * 00 (22) (33) (44) \<src\> (66)
106
- * 10 (22) (33) (44) \<si\> \<ze\> \<src\> (66)
86
+ * first four bits is message type
87
+ * 0 'lu packet' (i.e. whole packet was sent for lookup, i.e. small packet)
88
+ * 1 'lu packet head' (i.e. only head of packet was sent for lookup, i.e. large packet)
89
+ * next 13 bits is table entry (memory loc)
90
+ * next 11 bits is stream
91
+ * next 3 bits offset (for fabric cell sharing)
92
+ * next bit is size (17th bit, no way to test, would need >65k packets)
93
+ * next 16 bits is size (if message type is 1)
94
+ * next 8 bits is port
95
+ * next 8 bits is packet type
96
+
97
+ * packet type
98
+ * 0x00 real PITA, looks to be packets from control-plane, but amount of bytes that I need to pop I can't really figure out. I now rely on port# which likely isn't robust. This made me change my mind that 5th byte isn't port, but combined type, as it allowed, what seemed cleaner classification, but unfortunately it is not so.
99
+ * 0x08 is no-op, i don't need to pop anything, DMAC follows
100
+ * 0x20 this seems to be quite reliably mpls, i need to do some magic, as we're missing ethertype and my macs are wrong, there is also two extra bytes
101
+ * 0x80 is some short trash (payload 0xc013c6752759644ae0) no clue what it is
107
102
 
108
103
  Example from MX960
109
104
 
@@ -185,17 +180,6 @@ Example from MX80
185
180
  10 07 80 f0 05 b4 81 08
186
181
  10 0b 00 f0 02 28 81 08
187
182
 
188
- For this box, second to last byte, divmod 64, returns these ports, which are
189
- correct port for source.
190
-
191
- TAZ-TBB-0(X vty)# show ixchip ifd
192
- IFD IFD IX WAN Ing Queue Egr Queue
193
- Index Name Id Port Rt/Ct/Be H/L
194
- ====== ========== ====== ====== ============== ======
195
- 148 ge-1/0/0 2 0 0/32/64 0/32
196
- 149 ge-1/0/1 2 1 1/33/65 1/33
197
- 166 ge-1/1/8 2 18 18/50/82 18/50
198
-
199
183
  ### Sent header
200
184
  I'm really not sure about sent headers, need more data to figure out what is
201
185
  our type. For all my examples, when we sent frame without L2 headers for
data/capture/generate.rb CHANGED
@@ -25,7 +25,7 @@ class PacketViaDMEM
25
25
  when :sent then sent << packet.packet.join
26
26
  else raise StandardError, "invalid type #{type}"
27
27
  end
28
- headers << packet.header.join
28
+ headers << packet.header.to_s
29
29
  originals << packet.original.join
30
30
  end
31
31
  File.write('header-' + name + '.txt', headers.join("\n"))
@@ -35,7 +35,7 @@ class PacketViaDMEM
35
35
  end
36
36
  packet = @opts.original? ? pkt.pretty_original : pkt.pretty_packet
37
37
  packet = pkt.pretty pkt.pop(pop) if pop
38
- puts '### Packet %d ###' % [count+=1]
38
+ puts '# Pkt#%d # %s' % [count+=1, pkt.header]
39
39
  puts packet
40
40
  $stderr.puts pkt.header.join(' ') if @opts.headers?
41
41
  puts
@@ -0,0 +1,20 @@
1
+ class PacketViaDMEM
2
+ class Header
3
+ class Received
4
+ attr_accessor :msg_type,
5
+ :table,
6
+ :stream,
7
+ :offset,
8
+ :size,
9
+ :port,
10
+ :type
11
+
12
+ def to_s
13
+ ssize = ''
14
+ ssize = "size: %d # " % size if msg_type > 0
15
+ "RX: %sport: %d (%s) # strm: %d # type: 0x%x # tbl: %d # o: %d" %
16
+ [ ssize, port, port.divmod(64).join('/'), stream, type, table, offset ]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ class PacketViaDMEM
2
+ class Header
3
+ class Sent
4
+ attr_accessor :msg_type,
5
+ :statistics,
6
+ :increment_reference,
7
+ :fragment_info,
8
+ :drop_hash,
9
+ :decrement_reference,
10
+ :prequeue_priority,
11
+ :offset,
12
+ :table,
13
+ :color,
14
+ :queue_drop_opcode,
15
+ :queue_system,
16
+ :life,
17
+ :queue_number,
18
+ :port,
19
+ :type
20
+
21
+ def to_s
22
+ type_str = 'unk'
23
+ type_str = 'wan' if msg_type == 8
24
+ type_str = 'fab' if msg_type == 0
25
+ flags = ''
26
+ flags << (statistics ? 'S' : 's')
27
+ flags << (increment_reference ? 'I' : 'i')
28
+ flags << (fragment_info ? 'F' : 'f')
29
+ flags << (drop_hash ? 'H' : 'h')
30
+ flags << (decrement_reference ? 'D' : 'd')
31
+ flags << (prequeue_priority ? 'P' : 'p')
32
+ "TX: %s # %s # P:%d(%s) # Ty:%x # Q(%d@%d) # C:%d # D:%d # O:%d # T:%d # L:%d" %
33
+ [ type_str, flags, port, port.divmod(64).join('/'), type, queue_number,
34
+ queue_system, color, queue_drop_opcode, offset, table, life ]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -2,18 +2,18 @@ class PacketViaDMEM
2
2
 
3
3
  class Packet
4
4
  class NoPayload < Error; end
5
- attr_reader :type, :packet, :header, :original
5
+ attr_reader :type, :packet, :header, :popped, :original
6
6
 
7
7
  def pop bytes
8
8
  @original[bytes..-1]
9
9
  end
10
10
 
11
- def header_and_packet packet, pop_bytes, push_bytes
12
- header = packet[0..pop_bytes-1]
11
+ def popped_and_packet packet, pop_bytes, push_bytes
12
+ popped = packet[0..pop_bytes-1]
13
13
  payload = packet[pop_bytes..-1]
14
14
  raise NoPayload, "no payload for #{packet}" unless payload
15
15
  payload = push_bytes + payload
16
- [header, payload]
16
+ [popped, payload]
17
17
  end
18
18
 
19
19
  def to_s
@@ -49,6 +49,61 @@ class PacketViaDMEM
49
49
  out
50
50
  end
51
51
 
52
+ private
53
+
54
+ def get_pop_push pkt, type, port, macs
55
+ pop, push = 0, []
56
+ case type
57
+ when *Type::MPLS
58
+ pop, push = general_pop_push(pkt, pop, macs, FAKE[:etype_mpls])
59
+ when *Type::SELF
60
+ pop, push = self_pop_push(pkt, port, macs, pop)
61
+ when *Type::NOPOP
62
+ # no op, DMAC follows
63
+ end
64
+ [pop, push]
65
+ end
66
+
67
+ def general_pop_push pkt, pop, macs, ether_type
68
+ pop += 2
69
+ if macs
70
+ pop+=12
71
+ push = FAKE[:dmac] + FAKE[:smac] + ether_type
72
+ #push = pkt[2..13] + ether_type
73
+ [pop, push]
74
+ else
75
+ pop+=3
76
+ push = FAKE[:dmac] + FAKE[:smac] + ether_type
77
+ [pop, push]
78
+ end
79
+ end
80
+
81
+ def self_pop_push pkt, port, macs, pop
82
+ push = []
83
+ case port
84
+ when 0x80
85
+ pop+=14
86
+ when 0x1f
87
+ pop+=7
88
+ push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4] + FAKE[:ipv4]
89
+ else
90
+ if macs and port == 0x20
91
+ pop+=23
92
+ else
93
+ pop, push = general_pop_push(pkt, pop, macs, FAKE[:etype_ipv4])
94
+ end
95
+ end
96
+ [pop, push]
97
+ end
98
+
99
+
100
+
101
+ module Type
102
+ SELF = [ 0x00, 0x40 ]
103
+ NOPOP = [ 0x08, 0x80 ]
104
+ MPLS = [ 0x20 ]
105
+ end
106
+
52
107
 
53
108
  end
54
109
  end
@@ -1,70 +1,38 @@
1
+ require_relative 'header/received'
1
2
  class PacketViaDMEM
2
3
  class Received < Packet
3
4
 
4
5
  def initialize packet, debug
5
- @debug = debug
6
- @type = :received
7
- @original = packet
8
- @header, @packet = parse_packet packet
6
+ @debug = debug
7
+ @type = :received
8
+ @original = packet.dup
9
+ @header = Header::Received.new
10
+ @popped, @packet = parse_packet packet
9
11
  end
10
12
 
11
13
  private
12
14
 
13
15
  def parse_packet pkt
14
- pop, push = 6, []
15
- offset = 0
16
- case pkt.first.to_i(16)
17
- when 0x00 then offset = 0 #1,2,3,4,5,6
18
- when 0x10 then offset = 2 #1,2,3,4,7,8,5,6
19
- end
20
- pop += offset
21
- type = pkt[4+offset..5+offset].join.to_i(16)
22
- macs = pkt[6+offset].to_i(16) > 0 # macs, maybe...
23
- case type
24
- # these were self originated
25
- when 0x8000
26
- pop+=14
27
- # ae/802.1AX is special, I seem to have 2 bytes I don't know
28
- # and ethertype missing, and MAC is weird, mpls labels are present
29
- # i'd need example carrying IPv4/IPv6 instead of MPLS to decide those two bytes
30
- when *MAGIC::MPLS
31
- pop, push = get_pop_push(pkt, pop, offset, macs, FAKE[:etype_mpls])
32
- when *MAGIC::IPV4 # these were BFD packets from control-plane
33
- pop, push = get_pop_push(pkt, pop, offset, macs, FAKE[:etype_ipv4])
34
- # some BGP packets were like this
35
- # also SMB2 TCP Seq1 (maybe post ARP from control-plane?)
36
- # they are misssing all of ipv4 headers before TTL
37
- when 0x1f00
38
- pop+=7
39
- push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4] + FAKE[:ipv4]
40
- when *MAGIC::NOPOP
41
- # no-op, DMAC follows immedately
42
- else
43
- $stderr.puts "unknown type: 0x#{type.to_s(16)}" if @debug
44
- end
45
- header_and_packet pkt, pop, push
46
- end
16
+ head = pkt.shift(4).join.to_i(16)
47
17
 
48
- def get_pop_push pkt, pop, offset, macs, ether_type
49
- if macs
50
- pop+=14 #pop macs and weird two bytes (return macs in push)
51
- push = pkt[8+offset..19+offset] + ether_type
52
- [pop, push]
53
- else
54
- pop+=5
55
- push = FAKE[:dmac] + FAKE[:smac] + ether_type
56
- [pop, push]
57
- end
58
- end
18
+ @header.msg_type = (head & 0xf0000000) >> 28
19
+ @header.table = (head & 0xfff8000) >> 15
20
+ @header.stream = (head & 0x7ff0) >> 4
21
+ @header.offset = (head & 0xe) >> 1
22
+ @header.size = (head & 0x1) << 16
23
+
24
+ @header.size += pkt.shift(2).join.to_i(16) if @header.msg_type == PACKET_HEAD
25
+ @header.port = pkt.shift.to_i(16)
26
+ @header.type = pkt.shift.to_i(16)
59
27
 
60
- module MAGIC
61
- MPLS = [ 0x4220 ]
62
- IPV4 = [ 0x2000 ]
63
- # 4008, 8008, 8108 were ETH, MPLS, IPV4
64
- # 9208 was ETH, IPv4, UDP, IPSEC/ESP
65
- # 4108 was ETH, IPv4, UDP, BFD
66
- # b080 was unknown just 9 bytes after header (c013c6752759644ae0)
67
- NOPOP = [ 0x4008, 0x4108, 0x8008, 0x8108, 0x9208, 0xb080 ]
28
+ pop, push = 0, []
29
+ macs = pkt.first.to_i(16) > 0 # macs, maybe...
30
+
31
+ pop, push = get_pop_push pkt, @header.type, @header.port, macs
32
+ popped_and_packet pkt, pop, push
68
33
  end
34
+
35
+ PACKET = 0
36
+ PACKET_HEAD = 1
69
37
  end
70
38
  end
@@ -1,31 +1,52 @@
1
+ require_relative 'header/sent'
1
2
  class PacketViaDMEM
2
3
  class Sent < Packet
3
4
 
4
5
  def initialize packet, debug
5
6
  @debug = debug
6
7
  @type = :sent
7
- @original = packet
8
- @header, @packet = parse_packet packet
8
+ @original = packet.dup
9
+ @header = Header::Sent.new
10
+ @popped, @packet = parse_packet packet
9
11
  end
10
12
 
11
13
  private
12
14
 
13
15
  def parse_packet pkt
14
- pop, push = nil, []
15
- case pkt.first.to_i(16)
16
- when 0x00 # we're sending to fabric
17
- # we may send MAC to fabric,byte 6, 7, 9, 11, 21?
18
- if pkt[5].to_i(16) == 0xf0 # we don't send MAC to fabric
19
- push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_mpls]
20
- pop = 24
21
- else # we send MAC to fabric
22
- pop = 33
23
- end
24
- when 0x08 then pop = 13
25
- else pop = @sent
16
+ head = pkt.shift(4).join.to_i(16)
17
+ @header.msg_type = (head & 0xffffffff) >> 28
18
+ @header.statistics = head[27] == 1
19
+ @header.increment_reference = head[26] == 1
20
+ @header.fragment_info = head[25] == 1
21
+ @header.drop_hash = head[24] == 1
22
+ @header.decrement_reference = head[23] == 1
23
+ @header.prequeue_priority = head[22] == 1
24
+ @header.offset = (head & 0x3fffff) >> 13
25
+ @header.table = (head & 0x1fff)
26
+
27
+ head = pkt.shift(4).join.to_i(16)
28
+ raise Packet::NoPayload, "#{@original.join(' ')} had no payload" unless pkt[0]
29
+ @header.color = (head & 0x7fffffff) >> 29
30
+ @header.queue_drop_opcode = (head & 0xcffffff) >> 27
31
+ @header.queue_system = (head & 0x3ffffff) >> 24
32
+ @header.life = (head & 0x7fffff) >> 21
33
+ @header.queue_number = (head & 0x1fffff)
34
+
35
+ pop, push = 0, []
36
+ @header.port = pkt.shift.to_i(16)
37
+ @header.type = pkt.shift.to_i(16)
38
+ macs = pkt.first.to_i(16) > 0 # macs, maybe..
39
+ # uuhhohh, msg_type is always
40
+ if not @header.statistics
41
+ pop, push = get_pop_push pkt, @header.type, @header.port, macs
42
+ else
43
+ pop = 3
26
44
  end
27
- header_and_packet pkt, pop, push
45
+ popped_and_packet pkt, pop, push
28
46
  end
29
47
 
48
+ FABRIC = 0
49
+ WAN = 8
50
+
30
51
  end
31
52
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'packet_via_dmem'
3
- s.version = '0.0.8'
3
+ s.version = '0.0.10'
4
4
  s.licenses = %w( Apache-2.0 )
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = [ 'Saku Ytti' ]
@@ -23,7 +23,7 @@ describe PacketViaDMEM do
23
23
  when 'received' then @received[name] = File.read(entry).split
24
24
  when 'sent' then @sent[name] = File.read(entry).split
25
25
  when 'original' then @original[name] = File.read(entry).split
26
- when 'header' then @header[name] = File.read(entry).split
26
+ when 'header' then @header[name] = File.read(entry).split "\n"
27
27
  end
28
28
  end
29
29
  end
@@ -43,7 +43,7 @@ describe PacketViaDMEM do
43
43
  it 'produces correct headers' do
44
44
  @parsed.each do |name, packets|
45
45
  packets.each_with_index do |packet, index|
46
- packet.header.join.must_equal @header[name][index], "header #{name} at line #{index+1}"
46
+ packet.header.to_s.must_equal @header[name][index], "header #{name} at line #{index+1}"
47
47
  end
48
48
  packets.size.must_equal @header[name].size, "header #{name} has incorrect amount of packets"
49
49
  end
@@ -76,7 +76,7 @@ describe PacketViaDMEM do
76
76
  packets.each_with_index do |packet, index|
77
77
  packet.original.join.must_equal @original[name][index], "original #{name} at line #{index+1}"
78
78
  end
79
- packets.size.must_equal @header[name].size, "original #{name} has incorrect amount of packets"
79
+ packets.size.must_equal @original[name].size, "original #{name} has incorrect amount of packets"
80
80
  end
81
81
  end
82
82
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packet_via_dmem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Saku Ytti
@@ -41,6 +41,8 @@ files:
41
41
  - capture/generate.rb
42
42
  - lib/packet_via_dmem.rb
43
43
  - lib/packet_via_dmem/cli.rb
44
+ - lib/packet_via_dmem/header/received.rb
45
+ - lib/packet_via_dmem/header/sent.rb
44
46
  - lib/packet_via_dmem/packet.rb
45
47
  - lib/packet_via_dmem/packets.rb
46
48
  - lib/packet_via_dmem/received.rb