November 15, 2011

Changing traffic policies of DHCPv4 Filtering STREAMS Module at run-time using Solaris MDB

Overview
What will you do, if you are running a mission critical DHCP server and you want to adjust some traffic policies of dhcpmod kernel module without process restart?
The answer is: by using Solaris MDB.

            Finding out where the traffic policies reside
            It is assumed that you have already heard about Solaris STREAMS or even more have read STREAMS Programming Guide.
The basic concept is that Solaris exports special DDI interfaces for working with queues (queue_t). We use reading queue parameter q_ptr which stores the address to user-specific pointer - a structure created by routine mstrmod_open() when the queue is opened. In the case of dhcpmod all traffic policy parameters resides as unsigned integers in that structure. You can consult the dhcpmod's sources for more details.

Firstly you should look for dhcpmod in system streams cache:

mdb -k
> ::walk stream_head_cache | ::stream
<output stripped>
| ^
v |
+-----------------------+-----------------------+
| 0xffffffff9f2ce648| 0xffffffff9f2ce550|
| dhcpmod | dhcpmod |
| | |
| cnt = 0t0 | cnt = 0t0 |
| flg = 0x00000822 | flg = 0x00000832|
+-----------------------+-----------------------+
| ^
<output stripped>

0xffffffff9f2ce550 is a pointer to reading queue of filtering instance 1.

We need to print more information about it:

> ffffffff9f2ce550::print queue_t
{
q_qinfo = mstrmod_rinit
q_first = 0
q_last = 0
q_next = 0xffffffffa1546008
q_link = 0
q_ptr = 0xfffffe86a09d7400
q_count = 0
q_flag = 0x832
q_minpsz = 0
q_maxpsz = 0xffffffffffffffff
q_hiwat = 0
q_lowat = 0
q_bandp = 0
q_lock = {
_opaque = [ 0 ]
}
q_stream = 0xffffffffa1558d90
q_syncq = 0xffffffff9f2ce740
q_nband = 0
q_wait = {
_opaque = 0
}
q_sync = {
_opaque = 0
}
q_nfsrv = 0xfffffe86f89d0aa8
q_nbsrv = 0
q_draining = 0
q_struiot = 0xffff
q_syncqmsgs = 0
q_mblkcnt = 0
q_sqhead = 0
q_sqtail = 0xffffffff91e1c600
q_sqflags = 0
q_rwcnt = 0
q_sqnext = 0
q_sqprev = 0
q_sqtstamp = 0x3a55c18
q_qtstamp = 0xbaddcafebaddcafe
q_spri = 0
q_fp = 0xfffffe8683fca0b0
}

The parameter q_flag is from struct module_info and is equal 0x832 (for module dhcpmod). About STREAMS structures you can consult <sys/stream.h> for more details.
The parameter q_qinfo = mstrmod_rinit is our reading queue's primitive which confirms we are in the right place. The parameter q_ptr (0xfffffe86a09d7400) is our structure.
Now we dump what first 4 paragraphs (in MDB terms) of structure contains:

> 0xfffffe86a09d7400::dump -eq -w 4
fffffe86a09d7400:
9e9e82b0 ffffffff 00000000 00000000
8f81835 00000001 00000001 00000001
0000000a 00000005 00000001 00000000
000000ff 00000000 48a36f90 fffffe82

Offset 18 is the runtime-dependent instance ID of our queue (you can verify it's value via kstat as discussed earlier). If it isn't what you've requested, you should iterate via ::walk stream_head_cache to the next instance until succeeded.

> 0xffffffe86a09d7400+18/B
0xffffffe86a09d7400: 1
Offset 20 contains allowed packets per minute parameter. Offset 30 shows discard by rate policy parameter.
Note that for 32-bit kernel offset values will be different. Specifically, instance ID offset will be 9, allowed packets per minute offset will be 10, discard by rate policy offset will be 15.
Now we can accomplish our tasks.

Task 1. Turn off discard by rate policy.
Verifying discard by rate policy's current setting:

> 0xffffffe86a09d7400+30/B
0xffffffe86a09d7400: ff
You see ff → 255

Writing a new value:

> 0xffffffe86a09d7400+30/W 0x0
0xffffffe86a09d7400: 0xff = 0x0


Task 2. Increasing allowed packets per minute value
Verifying allowed packets per minute value:

> 0xffffffe86a09d7400+20/B
0xffffffe86a09d7400: a
You see a → 10


To increase allowed packets per minute value from 10 to 20 (0x14), type:

> 0xffffffe86a09d7400+20/W 0x14
0xffffffe86a09d7400: 0xa = 0x14


No comments:

Post a Comment