2 """ Please make sure you read the README COMPLETELY BEFORE reading anything below.
3 It is very critical that you read coding guidelines in Section E in README file.
12 def IterateProcChannels(proc
):
13 """ Iterate through all channels in the given process
16 proc - the proc object
17 returns: nothing, this is meant to be used as a generator function
18 kc - yields each kern_channel in the process
21 proc_filedesc
= proc
.p_fd
22 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
23 proc_ofiles
= proc_filedesc
.fd_ofiles
26 while count
<= proc_lastfile
:
27 if unsigned(proc_ofiles
[count
]) != 0:
28 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
29 if (unsigned(proc_fd_fglob
.fg_ops
.fo_type
) == 10):
30 yield Cast(proc_fd_fglob
.fg_data
, 'kern_channel *')
33 def IterateKernChannelRings(kc
, kind
):
34 """ Iterate through all rings on a given channel
43 rings
= kc
.ch_na
.na_rx_rings
45 rings
= kc
.ch_na
.na_tx_rings
47 rings
= kc
.ch_na
.na_alloc_rings
49 rings
= kc
.ch_na
.na_free_rings
51 # note that ch_last is actually one greater than the last
52 # as per the comment in ch_connect
53 for i
in xrange(kc
.ch_first
[kind
], kc
.ch_last
[kind
]):
54 yield addressof(rings
[i
])
56 # Note this is broken if you have type summaries enabled
57 # because we are summarizing the pointer to the structure
58 # and not the structure itself. Unfortunately, that's
59 # the pattern used elsewhere.
60 # Trying to actually use the type summary will blow up
61 # because it has a linked list pointer to itself
63 @lldb_type_summary(['kern_channel_t', 'kern_channel *'])
64 @header('{:<20s} {:<36s}'.format('kern_channel', 'uuid'))
65 def GetKernChannelSummary(kc
):
66 """ Summarizes a kern_channel and related information
68 returns: str - summary of kern_channel
71 format_string
= '{o: <#020x} {u: <36s}'
72 return format_string
.format(
74 u
=GetUUIDSummary(kc
.ch_info
.cinfo_ch_id
))
76 @lldb_type_summary(['__kern_channel_ring *'])
77 @header('{:<20s} {:<65s} {:>10s} | {:<5s} {:<5s} | {:<5s} {:<5s} {:<5s} | {:<5s} {:<5s} {:<5s}'.format(
78 'kernchannelring', 'name', 'flags', 'kc', 'kt', 'rc', 'rh', 'rt', 'c', 'h', 't'))
79 def GetKernChannelRingSummary(kring
):
80 """ Summarizes a __kern_channel_ring and related information
82 returns: str - summary of kern_channel_ring
85 format_string
= '{o: <#020x} "{name: <63s}" {flags: >#010x} | {kh: <5d} {kt: <5d} | {rh: <5d} {rt: <5d} | {h: <5d} {t: <5d}'
86 return format_string
.format(
89 flags
=kring
.ckr_flags
,
94 h
=kring
.ckr_ring
.ring_head
,
95 t
=kring
.ckr_ring
.ring_tail
)
97 @lldb_command('showprocchannels')
98 def ShowProcChannels(cmd_args
=None):
99 """ Show the skywalk channels for a given process.
101 usage: showprocchannels <proc_t>
105 raise ArgumentError('missing struct proc * argument')
107 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
109 print GetKernChannelSummary
.header
110 for kc
in IterateProcChannels(proc
):
111 print GetKernChannelSummary(kc
)
113 @lldb_command('showchannelrings')
114 def ShowChannelRings(cmd_args
=None):
115 """ Show the skywalk rings for a given channel.
117 usage: showchannelrings <struct kern_channel *>
121 raise ArgumentError('missing struct kern_channel * argument')
123 kc
= kern
.GetValueFromAddress(cmd_args
[0], 'kern_channel *')
126 print GetKernChannelRingSummary
.header
127 for ring
in IterateKernChannelRings(kc
, 0) :
128 print GetKernChannelRingSummary(ring
)
131 print GetKernChannelRingSummary
.header
132 for ring
in IterateKernChannelRings(kc
, 1) :
133 print GetKernChannelRingSummary(ring
)
136 print GetKernChannelRingSummary
.header
137 for ring
in IterateKernChannelRings(kc
, 2) :
138 print GetKernChannelRingSummary(ring
)
141 print GetKernChannelRingSummary
.header
142 for ring
in IterateKernChannelRings(kc
, 3) :
143 print GetKernChannelRingSummary(ring
)
145 def SkmemCacheModeAsString(mode
) :
147 SKM_MODE_NOCACHE
= 0x1
150 if (mode
& SKM_MODE_NOCACHE
) :
154 if (mode
& SKM_MODE_AUDIT
) :
161 @lldb_command('showskmemcache')
162 def ShowSkmemCache(cmd_args
=None) :
163 """ Show the global list of skmem caches
166 format_string
= "{:<4s} {:<18s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<4s} {:<s}"
167 print format_string
.format("", "ADDR", "BUFI", "BUFM", "RESC", "SLCR", "SLDE", "SLAL", "SLFR", "DECO", "MODE", "NAME")
170 skmhead
= kern
.globals.skmem_cache_head
172 for skm
in IterateTAILQ_HEAD(skmhead
, "skm_link") :
173 format_string
= "{:>4d}: 0x{:<08x} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4d} {:<4s} \"{:<s}\""
174 print format_string
.format(i
, skm
, skm
.skm_bufinuse
, skm
.skm_bufmax
, skm
.skm_rescale
, skm
.skm_sl_create
, skm
.skm_sl_destroy
, skm
.skm_sl_alloc
, skm
.skm_sl_free
, skm
.skm_depot_contention
, SkmemCacheModeAsString(skm
.skm_mode
), str(skm
.skm_name
))
177 @lldb_command('showskmemslab')
178 def ShowBufCtl(cmd_args
=None) :
179 """ Show slabs and bufctls of a skmem cache
182 if (cmd_args
== None or len(cmd_args
) == 0) :
183 print "Missing argument 0 (skmem_cache address)."
186 skm
= kern
.GetValueFromAddress(cmd_args
[0], 'skmem_cache *')
188 for slab
in IterateTAILQ_HEAD(skm
.skm_sl_partial
, "sl_link") :
189 format_string
= "{:<08x} {:<4d} 0x{:<08x} 0x{:08x}"
190 print format_string
.format(slab
, slab
.sl_refcnt
, slab
.sl_base
, slab
.sl_basem
)
192 for slab
in IterateTAILQ_HEAD(skm
.skm_sl_empty
, "sl_link") :
193 format_string
= "{:<08x} {:<4d} 0x{:<08x} 0x{:08x}"
194 print format_string
.format(slab
, slab
.sl_refcnt
, slab
.sl_base
, slab
.sl_basem
)
196 def SkmemArenaTypeAsString(type) :
198 SKMEM_ARENA_TYPE_NEXUS
= 0
199 SKMEM_ARENA_TYPE_NECP
= 1
200 SKMEM_ARENA_TYPE_SYSTEM
= 2
202 if (type == SKMEM_ARENA_TYPE_NEXUS
) :
203 out_string
+= "NEXUS"
204 elif (type == SKMEM_ARENA_TYPE_NECP
) :
206 elif (type == SKMEM_ARENA_TYPE_SYSTEM
) :
207 out_string
+= "SYSTEM"
213 @lldb_command('showskmemarena')
214 def ShowSkmemArena(cmd_args
=None) :
215 """ Show the global list of skmem arenas
219 arhead
= kern
.globals.skmem_arena_head
221 for ar
in IterateTAILQ_HEAD(arhead
, "ar_link") :
222 format_string
= "{:>4d}: 0x{:<08x} {:<6s} {:>5d} KB \"{:<s}\""
223 print format_string
.format(i
, ar
, SkmemArenaTypeAsString(ar
.ar_type
), ar
.ar_mapsize
>> 10, str(ar
.ar_name
))
226 @lldb_command('showskmemregion')
227 def ShowSkmemRegion(cmd_args
=None) :
228 """ Show the global list of skmem regions
232 skrhead
= kern
.globals.skmem_region_head
234 for skr
in IterateTAILQ_HEAD(skrhead
, "skr_link") :
235 format_string
= "{:>4d}: 0x{:<08x} \"{:<s}\""
236 print format_string
.format(i
, skr
, str(skr
.skr_name
))
239 @lldb_command('showchannelupphash')
240 def ShowChannelUppHash(cmd_args
=None) :
241 """ Show channel user packet pool hash chain
244 if (cmd_args
== None or len(cmd_args
) == 0) :
245 print "Missing argument 0 (skmem_cache address)."
248 ch
= kern
.GetValueFromAddress(cmd_args
[0], 'kern_channel *')
249 KERN_CHANNEL_UPP_HTBL_SIZE
= 256
251 for i
in range(KERN_CHANNEL_UPP_HTBL_SIZE
) :
252 bkt
= addressof(ch
.ch_upp_hash_table
[i
])
253 format_string
= "{:>4d} 0x{:<08x}"
254 print format_string
.format(i
, bkt
)
255 for kqum
in IterateListEntry(bkt
.upp_head
, 'struct __kern_quantum *',
256 'qum_upp_link', list_prefix
='s') :
257 format_string
= "0x{:<08x}"
258 print format_string
.format(kqum
)
260 @lldb_type_summary(['struct ns *'])
261 @header('{:<20s} {:<5s} {:<48s} {:<4s}'.format('ns', 'proto', 'addr', 'nreservations'))
262 def GetStructNsSummary(ns
):
263 """ Summarizes a struct ns from the netns
265 returns: str - summary of struct ns
268 if (ns
.ns_proto
== IPPROTO_TCP
):
270 elif (ns
.ns_proto
== IPPROTO_UDP
):
273 proto
= str(ns
.ns_proto
)
275 if (ns
.ns_addr_len
== sizeof('struct in_addr')):
276 addr
= GetInAddrAsString(addressof(ns
.ns_inaddr
))
277 elif (ns
.ns_addr_len
== sizeof('struct in6_addr')):
278 addr
= GetIn6AddrAsString(ns
.ns_in6addr
.__u6_addr
.__u6_addr
8)
280 addr
= str(ns_addr
) + " bad len {:u}".format(ns
.ns_addr_len
)
282 format_string
= '{o:#020x} {p:<5s} {a:<48s} {n:<4d}'
284 """ show ports and refs, one per line
286 ports_string
= "ports & refs\n"
287 for f
in IterateRBTreeEntry(ns
.ns_reservations
, 'struct ns_reservation *', 'nsr_link'):
288 ports_string
+= "\t%u" % f
.nsr_port
289 ports_string
+= "\tlisten %d\tskywalk %d\tbsd %d\tpf %d\n" % (f
.nsr_refs
[0], f
.nsr_refs
[1], f
.nsr_refs
[2], f
.nsr_refs
[3])
290 """ show just the ports, not refs
292 ports_string = "\nports:\t"
293 for f in IterateRBTreeEntry(ns.ns_reservations, 'struct ns_reservation *', 'nsr_link'):
294 if (len(ports_string)-offs > 70):
295 ports_string += "\n\t"
296 offs = len(ports_string)
297 ports_string += " %u" % f.nsr_port
300 return format_string
.format(
304 n
=ns
.ns_n_reservations
) + ports_string
306 @lldb_command('shownetns')
307 def ShowNetNS(cmd_args
=None):
308 """ Show the netns table
310 print"\nnetns_namespaces:"
311 print GetStructNsSummary
.header
313 namespaces
= kern
.globals.netns_namespaces
314 for ns
in IterateRBTreeEntry(namespaces
, 'struct ns *', 'ns_link'):
315 print GetStructNsSummary(ns
)
317 print "\nwild: (these should be duplicated above)"
318 print GetStructNsSummary
.header
320 print GetStructNsSummary(kern
.globals.netns_global_wild
[i
])
323 print GetStructNsSummary
.header
325 print GetStructNsSummary(kern
.globals.netns_global_non_wild
[i
])
328 @lldb_type_summary(['struct ns_token *'])
329 @header('{:<20s} {:<5s} {:<48s} {:<12s} {:<8s} {:<38s} {:<38s} {:<12s}'.format('nt', 'proto', 'addr', 'port', 'owner', 'ifp', 'parent', 'flags'))
330 def GetNsTokenSummary(nt
):
331 """ Summarizes a struct ns from the netns
333 returns: str - summary of struct ns
336 if (nt
.nt_proto
== IPPROTO_TCP
):
338 elif (nt
.nt_proto
== IPPROTO_UDP
):
341 proto
= str(nt
.nt_proto
)
343 if (nt
.nt_addr_len
== sizeof('struct in_addr')):
344 addr
= GetInAddrAsString(addressof(nt
.nt_inaddr
))
345 elif (nt
.nt_addr_len
== sizeof('struct in6_addr')):
346 addr
= GetIn6AddrAsString(nt
.nt_in6addr
.__u6_addr
.__u6_addr
8)
348 addr
= str(nt_addr
) + " bad len {:u}".format(nt
.nt_addr_len
)
350 format_string
= '{o:#020x} {p:<5s} {a:<48s} {pt:<12s} {wn:<8s} {ifp:38s} {pa:38s} {f:#012x}'
352 ports
= "%u" % nt
.nt_port
354 ifp
= "(struct ifnet *)" + hex(nt
.nt_ifp
)
356 if ((nt
.nt_flags
& 0x7) == 0x00):
358 parent
= "(void *)" + hex(nt
.nt_parent
)
359 elif ((nt
.nt_flags
& 0x7) == 0x01):
361 parent
= "(struct flow_entry *)" + hex(nt
.nt_parent_skywalk
)
362 elif ((nt
.nt_flags
& 0x7) == 0x02): # XXX xnudefines?
364 parent
= "(struct inpcb *)" + hex(nt
.nt_parent_bsd
)
365 elif ((nt
.nt_flags
& 0x7) == 0x03): # XXX xnudefines?
367 parent
= "(void *)" + hex(nt
.nt_parent
)
369 return format_string
.format(
379 @lldb_command("showallnetnstokens")
380 def ShowAllNetNSTokens(cmd_args
=None):
381 """ show all netns tokens
384 tokenhead
= kern
.globals.netns_all_tokens
385 print GetNsTokenSummary
.header
386 for nt
in IterateListEntry(tokenhead
, 'struct ns_token *', 'nt_all_link', list_prefix
='s'):
387 print GetNsTokenSummary(nt
)
389 @lldb_command("shownetnstokens")
390 def ShowNetNSTokens(cmd_args
=None):
391 """ show netns tokens attached to an ifp
392 with no args, shows unbound tokens
395 if (cmd_args
== None or len(cmd_args
) == 0):
396 print "No ifp argument provided, showing unbound tokens"
397 tokenhead
= kern
.globals.netns_unbound_tokens
398 elif len(cmd_args
) > 0:
399 ifp
= kern
.GetValueFromAddress(cmd_args
[0], 'ifnet *')
400 print "Showing tokens for ifp %r" % ifp
401 tokenhead
= ifp
.if_netns_tokens
403 print "Missing ifp argument 0 in shownetnstokens"
407 print GetNsTokenSummary
.header
408 for nt
in IterateListEntry(tokenhead
, 'struct ns_token *', 'nt_ifp_link', list_prefix
='s'):
409 print GetNsTokenSummary(nt
)
411 def IterateSTAILQ_HEAD(headval
, element_name
):
412 iter_val
= headval
.stqh_first
413 while unsigned(iter_val
) != 0 :
415 iter_val
= iter_val
.__getattr
__(element_name
).stqe_next
418 @lldb_command("shownexuschannels")
419 def ShowNexusChannels(cmd_args
=None):
420 """ show nexus channels
422 if (cmd_args
== None or len(cmd_args
) == 0):
423 print "Missing argument 0 (kern_nexus address)."
426 nx
= kern
.GetValueFromAddress(cmd_args
[0], 'kern_nexus *')
429 format_string
= "{:>4s} {:<18s} {:>4s} {:<7s} {:<7s} {:<18s} {:<18s} {:<18s} {:>8s} {:6s} {:<18s} {:>4s} {:s}"
430 print format_string
.format("", "addr", "refs", "txrings", "rxrings", "arena", "ioskmap", "mapaddr", "mapsize", "maprdr", "na", "fd", "process")
432 for ch
in IterateSTAILQ_HEAD(nx
.nx_ch_head
, "ch_link"):
433 format_string
= "{:>4d}: 0x{:<08x} {:>4d} [{:2d},{:2d}] [{:2d},{:2d}] 0x{:<08x} 0x{:<08x} 0x{:<16x} {:>8d} {:>6d} 0x{:<08x} {:>4d} {:s}({:d})"
434 print format_string
.format(i
, ch
, ch
.ch_refcnt
, ch
.ch_first
[0], ch
.ch_last
[0], ch
.ch_first
[1], ch
.ch_last
[1], ch
.ch_mmap
.ami_arena
, ch
.ch_mmap
.ami_mapref
, ch
.ch_mmap
.ami_mapaddr
, ch
.ch_mmap
.ami_mapsize
, ch
.ch_mmap
.ami_redirect
, ch
.ch_na
, ch
.ch_fd
, ch
.ch_name
, ch
.ch_pid
)
437 for ch
in IterateSTAILQ_HEAD(nx
.nx_ch_nonxref_head
, "ch_link"):
438 format_string
= "{:>4d}: 0x{:<08x} {:>4d} [{:2d},{:2d}] [{:2d},{:2d}] 0x{:<08x} 0x{:<08x} 0x{:<16x} {:>8d} {:>6d} 0x{:<08x} {:>4d} {:s}({:d})"
439 print format_string
.format(i
, ch
, ch
.ch_refcnt
, ch
.ch_first
[0], ch
.ch_last
[0], ch
.ch_first
[1], ch
.ch_last
[1], ch
.ch_mmap
.ami_arena
, ch
.ch_mmap
.ami_mapref
, ch
.ch_mmap
.ami_mapaddr
, ch
.ch_mmap
.ami_mapsize
, ch
.ch_mmap
.ami_redirect
, ch
.ch_na
, ch
.ch_fd
, ch
.ch_name
, ch
.ch_pid
)
442 def IterateProcNECP(proc
):
443 """ Iterate through all NECP descriptors in the given process
446 proc - the proc object
447 returns: nothing, this is meant to be used as a generator function
448 necp - yields each necp_fd_data in the process
451 proc_filedesc
= proc
.p_fd
452 proc_lastfile
= unsigned(proc_filedesc
.fd_lastfile
)
453 proc_ofiles
= proc_filedesc
.fd_ofiles
456 while count
<= proc_lastfile
:
457 if unsigned(proc_ofiles
[count
]) != 0:
458 proc_fd_fglob
= proc_ofiles
[count
].f_fglob
459 if (unsigned(proc_fd_fglob
.fg_ops
.fo_type
) == 9):
460 yield Cast(proc_fd_fglob
.fg_data
, 'necp_fd_data *')
463 def GetNECPClientBitFields(necp
):
464 """ Return the bit fields in necp_client as string
466 returns: str - string representation of necp_client bit fields
469 bitfields_string
= ''
470 if necp
.result_read
!= 0:
471 bitfields_string
+= 'r'
473 bitfields_string
+= '-'
474 if necp
.allow_multiple_flows
!= 0:
475 bitfields_string
+= 'm'
477 bitfields_string
+= '-'
478 if necp
.background
!= 0:
479 bitfields_string
+= 'b'
481 bitfields_string
+= '-'
482 if necp
.background_update
!= 0:
483 bitfields_string
+= 'B'
485 bitfields_string
+= '-'
486 if necp
.platform_binary
!= 0:
487 bitfields_string
+= 'p'
489 bitfields_string
+= '-'
491 return bitfields_string
493 def GetNECPFlowBitFields(flow_registration
):
494 """ Return the bit fields in necp_client_flow_registration as string
496 returns: str - string representation of necp_client_flow_registration bit fields
499 bitfields_string
= ''
500 if flow_registration
.flow_result_read
!= 0:
501 bitfields_string
+= 'r'
503 bitfields_string
+= '-'
504 if flow_registration
.defunct
!= 0:
505 bitfields_string
+= 'd'
507 bitfields_string
+= '-'
509 return bitfields_string
511 @lldb_type_summary(['necp_fd_data *'])
512 @header('{:<20s} {:<8s}'.format('necp_fd_data', "flags"))
513 def GetNECPSummary(necp
):
514 """ Summarizes a necp_fd_data and related information
516 returns: str - summary of necp_fd_data
519 format_string
= '{o: <#020x} {u:<#08x}'
521 stats_arenas_string
= "\n\n\t%-18s %-39s %-4s %-10s\n" % ("stats_arenas", "mmap", "refs", "flags")
522 for sa
in IterateListEntry(necp
.stats_arena_list
, 'struct necp_arena_info *', 'nai_chain'):
523 stats_arenas_string
+= "\t0x%016x " % sa
524 stats_arenas_string
+= "[0x%016x-0x%016x) " % (sa
.nai_mmap
.ami_mapaddr
,(sa
.nai_mmap
.ami_mapaddr
+sa
.nai_mmap
.ami_mapsize
))
525 stats_arenas_string
+= "%4u " % sa
.nai_use_count
526 stats_arenas_string
+= "0x%08x " % sa
.nai_flags
527 stats_arenas_string
+= "\n"
530 for c
in IterateRBTreeEntry(necp
.clients
, 'struct necp_client *', 'link'):
531 clients_string
+= "\n\t%-18s %-36s %-4s %-5s\n" % ("necp_clients", "client_id", "refs", "flags")
532 clients_string
+= "\t0x%016x " % c
533 clients_string
+= "%36s " % GetUUIDSummary(c
.client_id
)
534 clients_string
+= "%4u " % c
.reference_count
535 clients_string
+= "%5s " % GetNECPClientBitFields(c
)
537 for f
in IterateRBTreeEntry(c
.flow_registrations
, 'struct necp_client_flow_registration *', 'client_link'):
539 clients_string
+= "\n\t\t%-18s %-36s %-2s %-18s %-18s %-18s\n" % ("flow_registration", "registraton_id", "flags", "stats_arena", "kstats_obj", "ustats_obj")
540 clients_string
+= "\t\t0x%016x " % f
541 clients_string
+= "%36s " % GetUUIDSummary(f
.registration_id
)
542 clients_string
+= "%2s " % GetNECPFlowBitFields(f
)
543 clients_string
+= "0x%016x " % f
.stats_arena
544 clients_string
+= "0x%016x " % f
.kstats_kaddr
545 clients_string
+= "0x%016x " % f
.ustats_uaddr
546 clients_string
+= "\n"
548 return format_string
.format(
550 u
=necp
.flags
) + stats_arenas_string
+ clients_string
552 @lldb_command('showprocnecp')
553 def ShowProcNECP(cmd_args
=None):
554 """ Show NECP descriptors for a given process.
556 usage: showprocnecp <proc_t>
560 raise ArgumentError('missing struct proc * argument')
562 proc
= kern
.GetValueFromAddress(cmd_args
[0], 'proc_t')
564 print GetNECPSummary
.header
565 for kc
in IterateProcNECP(proc
):
566 print GetNECPSummary(kc
)