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 +4 -4
- data/README.md +16 -32
- data/capture/generate.rb +1 -1
- data/lib/packet_via_dmem/cli.rb +1 -1
- data/lib/packet_via_dmem/header/received.rb +20 -0
- data/lib/packet_via_dmem/header/sent.rb +38 -0
- data/lib/packet_via_dmem/packet.rb +59 -4
- data/lib/packet_via_dmem/received.rb +24 -56
- data/lib/packet_via_dmem/sent.rb +36 -15
- data/packet_via_dmem.gemspec +1 -1
- data/spec/packet_via_dmem_spec.rb +3 -3
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87a6a44720c7a589e77bee75c030bda1c59afee4
|
4
|
+
data.tar.gz: 3f05700efab522e4576b99d4c6a51c225d07cac4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
*
|
87
|
-
*
|
88
|
-
*
|
89
|
-
|
90
|
-
*
|
91
|
-
|
92
|
-
|
93
|
-
*
|
94
|
-
|
95
|
-
*
|
96
|
-
|
97
|
-
*
|
98
|
-
|
99
|
-
|
100
|
-
*
|
101
|
-
*
|
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.
|
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"))
|
data/lib/packet_via_dmem/cli.rb
CHANGED
@@ -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 '
|
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
|
12
|
-
|
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
|
-
[
|
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
|
6
|
-
@type
|
7
|
-
@original
|
8
|
-
@header
|
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
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
data/lib/packet_via_dmem/sent.rb
CHANGED
@@ -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
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
data/packet_via_dmem.gemspec
CHANGED
@@ -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.
|
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 @
|
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.
|
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
|