📄 c-extend3.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html><head><link rel="STYLESHEET" type="text/css" href="wrs.css"><title> Extending Tornado Tools </title></head><body bgcolor="FFFFFF"><p class="navbar" align="right"><a href="index.html"><img border="0" alt="[Contents]" src="icons/contents.gif"></a><a href="c-extend.html"><img border="0" alt="[Index]" src="icons/index.gif"></a><a href="c-extend.html"><img border="0" alt="[Top]" src="icons/top.gif"></a><a href="c-extend2.html"><img border="0" alt="[Prev]" src="icons/prev.gif"></a><a href="c-extend4.html"><img border="0" alt="[Next]" src="icons/next.gif"></a></p><font face="Helvetica, sans-serif" class="sans"><h3 class="H2"><i><a name="84463">5.3 Extracting Information from a Structure</a></i></h3></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="84464"> </a>Extracting the information needed from the <b class="symbol_lc">ifnet</b> structure can be broken into several steps. First, determine how the data is stored. Then locate the first element, identify the remaining elements, and finally, query each element to obtain its contents. As you proceed through this chapter, you will build up expressions as you go. For example, you will write a Tcl expression and then use the value returned by that routine as an argument for the next Tcl expression.</p></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="84465">5.3.1 Definitions and Structures</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="84467"> </a>A network interface is an entity over which packets can be sent. It can represent a physical Ethernet hardware device or a logical device (such as the loopback interface) that simply relays packets. Generally, when a VxWorks target has Ethernet capability, there are at least two interfaces: one for the device and one loopback interface for local packet communication.</p><dd><p class="Body"><a name="84468"> </a>A network interface in VxWorks is represented as a linked list of structures. The structure that contains most of the information for a network interface, <b class="symbol_lc">struct ifnet</b>, and the subsidiary structure,<b class="symbol_lc"> struct if_data</b>, are found in the include file <i class="textVariable">installDir</i><b class="file">/target/h/net/if.h</b>:</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="85475">struct ifnet { char * if_name; /* name, as "en" or "lo" */ struct ifnet * if_next; /* all struct ifnets are chained */ struct ifaddr * if_addrlist; /* linked list of addresses per if */ int if_pcount; /* number of promiscuous listeners */ caddr_t if_bpf; /* packet filter structure */ u_short if_index; /* numeric abbreviation for if */ short if_unit; /* sub-unit for lower level driver */ short if_timer; /* time until if_watchdog called */ short if_flags; /* up/down, broadcast, etc. */ struct if_data if_data; /* stats and other data about if */ struct mBlk * pInmMblk; /* chain of multicast addresses */ ... struct ifqueue if_snd; /* output queue */ };</a></b><dd> <b><a name="85553">struct if_data { /* generic interface information */ u_char ifi_type; /* ethernet, tokenring, etc. */ u_char ifi_addrlen; /* media address length */ u_char ifi_hdrlen; /* media header length */ u_long ifi_mtu; /* maximum transmission unit */ u_long ifi_metric; /* routing metric (external only) */ u_long ifi_baudrate; /* linespeed */ /* volatile statistics */ u_long ifi_ipackets; /* packets received on interface */ u_long ifi_ierrors; /* input errors on interface */ u_long ifi_opackets; /* packets sent on interface */ u_long ifi_oerrors; /* output errors on interface */ u_long ifi_collisions; /* collisions on csma interfaces */ u_long ifi_ibytes; /* total number of octets received */ u_long ifi_obytes; /* total number of octets sent */ u_long ifi_imcasts; /* packets received via multicast */ u_long ifi_omcasts; /* packets sent via multicast */ u_long ifi_iqdrops; /* dropped on input, this interface */ u_long ifi_noproto; /* destined for unsupported protocol */ u_long ifi_lastchange; /* last updated */ };</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="84484"> </a>In VxWorks, the global variable <b class="symbol_lc">ifnet</b> points to the structure that contains the first network interface. If there is an additional network interface, the last item in the structure points to the next structure. (See <a href="c-extend3.html#84491">Figure 5-2</a>.) <div class="frame"><h4 class="EntityTitle"><a name="84491"><font face="Helvetica, sans-serif" size="-1" class="sans">Figure 5-2: A Linked List of Structures</font></a></h4><dl class="margin"><div class="Anchor"><a name="84518"> </a><img class="figure" border="0" src="images/c-extenda1.gif"></div></dl></div></p></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="84519">5.3.2 Locating the Start of the First Structure</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="84520"> </a>The first piece of information needed is the address of the first node of the list, which is stored in the global variable <b class="symbol_lc">ifnet</b>. The address of this symbol can be found in the target server symbol table. The <b class="command">wtxtcl</b> procedure to query the symbol table is:</p><dl class="margin"><dd><pre class="Code2"><b><a name="84521"></b><tt class="output">wtxtcl> </tt><b>wtxSymFind -name ifnet </b><tt class="output">_ifnet 0x95ae0 0x9 0 0 ""</tt><b></a></b></pre></dl><dd><p class="Body"><a name="84523"> </a>This procedure returns a list of information about the symbol, which includes a pointer to its location in memory. Use <b class="tclProc">wtxMemRead</b> to find the location of the first structure by extracting the symbol address from the list returned by <b class="tclProc">wtxSymFind</b> and using this as an argument to <b class="tclProc">wtxMemRead</b>:</p><dl class="margin"><dd><pre class="Code2"><b><a name="84524"></b><tt class="output">wtxtcl> </tt><b>set block [wtxMemRead [lindex [wtxSymFind -name ifnet] 1] 4] </b><tt class="output">mblk0 wtxtcl> </tt><b>set ifnet [memBlockGet -l $block] </b><tt class="output">0x001a3098 wtxtcl> </tt><b>memBlockDelete $block </b><tt class="output">wtxtcl> </tt><b>set ifnet </b><tt class="output">0x001a3098</tt><b> </a></b></pre></dl><dd><p class="Body"><a name="84529"> </a>Read a memory block of 4 bytes and store the block handle in the variable <b class="symbol_lc">block</b>. Then fetch the 4 bytes in this block to the variable <b class="symbol_lc">ifnet</b><i class="textVariable"> </i>and free the block. You now know the location of the first element of the linked list.</p></dl></dl><font face="Helvetica, sans-serif" class="sans"><h4 class="H3"><i><a name="84530">5.3.3 Listing All Network Interfaces</a></i></h4></font><dl class="margin"><dl class="margin"><dd><p class="Body"><a name="84531"> </a>One algorithm to move from one structure of the linked list to the next looks like the following:</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="84532"> p = ifnet; while (p != NULL) { print p; p = p->if_next; }</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="84539"> </a>You could implement this with WTX Tcl by repeatedly using <b class="tclProc">wtxMemRead</b>, but in Tornado there is a simpler way: you can write a Gopher script and send it to the target agent from the Tornado shell. The target agent executes it in one step and returns the results. Here is the Gopher implementation of the algorithm:</p></dl><dl class="margin"><dd><pre class="Code"><b><a name="84540"> <i class="textVariable">ifnet</i> {! + 4 *}</a></b></pre></dl><dl class="margin"><dd><p class="Body"><a name="84543"> </a>For detailed information on writing a Gopher script, see <a href="c-wtx3.html#84997"><i class="title">4.3.11 Gopher Support</i></a>. A summary of the function of the script tokens follows.</p></dl><dl class="margin"><dd><div class="Item"><a name="84545"> </a><i class="textVariable">ifnet</i></div><dl class="margin"><dl class="margin"><dd><div class="Indent2"><a name="84546"> </a>is an unsigned integer constant which sets the value of the Gopher <i class="emphasis">pointer.</i></div><br></dl></dl><dd><div class="Item"><a name="84547"> </a>open brace (<b>{</b>)</div><dl class="margin"><dl class="margin"><dd><div class="Indent2"><a name="84548"> </a>introduces a loop; the subprogram inside the braces is executed while the pointer is not <b class="symbol_UC">NULL</b>.</div><br></dl></dl><dd><div class="Item"><a name="84549"> </a>exclamation (<b>!</b>)</div><dl class="margin"><dl class="margin"><dd><div class="Indent2"><a name="84550"> </a>copies the value of the pointer to the Gopher <i class="term">tape</i> (result buffer).</div><br></dl></dl><dd><div class="Item"><a name="84551"> </a><b class="command">+4</b> </div><dl class="margin"><dl class="margin"><dd><div class="Indent2"><a name="84552"> </a>increments the pointer by this value. (We computed the value 4 by inspecting the sizes of the constituent elements.)</div><br></dl></dl><dd><div class="Item"><a name="84553"> </a>asterisk (<b>*</b>)</div><dl class="margin"><dl class="margin"><dd><div class="Indent2"><a name="84554"> </a>dereferences the pointer.</div><br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -