Vviewpoints
DOI: 10.1145/2347736.2347747
Article development led by
queue.acm.org
Kode Vicious
A nice piece of code
In MY lAst column (A System Is Not a Product, August Com- munications) I mentioned I had recently read two pieces of code that had actually lowered,
rather than raised, my blood pressure.
As promised, this column covers that
second piece of code.
One of the things that can make me
really like a piece of code—other than
the obvious ones such as decent documentation, proper indenting, and rational variable names—is when a function or subsystem is properly reused.
Over the past month, I have been reading the IPFW (IP Firewall) code written
by Luigi Rizzo at the University of Pisa,
which is one of the firewalls available in
FreeBSD. Like any firewall, IPFW needs
to examine packets and then decide to
drop, modify, or pass the packets unchanged through the system. Having
reviewed several pieces of software that
do similar work, I have to say that IPFW
does the best job of reusing the code
around it. Here are two examples.
Part of the job of a firewall is to
classify packets and then decide what
to do with them. There are a few ways
to go about this, but what IPFW does
is quite elegant. It reuses a tried and
tested idea from another place in the
kernel, the BPF (Berkeley Packet Fil-
ter). BPF classifies packets using a set
of opcodes—sort of like a machine lan-
guage for processing network packet
headers—to decide whether a packet
matches a filter that has been specified
by the user. Using opcodes and a state
machine for packet classification leads
to a flexible and compact implemen-
tation of the packet classifier, com-
pared with hand coding rules for later
use. IPFW extends the set of opcodes
that can be used for classifying pack-
ets, but the idea is exactly the same,
and the resulting code is easy to read
and understand, and therefore easier
to maintain and less likely to contain
bugs that might let malicious packets
through. The entire state machine that
executes any and all firewall rules in
IPFW is only 1,200 lines of C code, in-
cluding comments. Another advantage
of using a set of opcodes to express the
packet-processing rules is that the en-
tire chunk of C code, which is really a
bytecode interpreter, can be replaced
by just-in-time compiled code, gener-
ated by an optimizing compiler. This
leads to an even greater increase in
packet-processing speed.
An example of good code.
1 int
2 ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
uint32_t *val)
{
3
4
5
6
7
8 if (tbl >= IPFW_TABLES_MAX)
9 return (0);
10 rnh = ch->tables[tbl];
11 KEY_LEN(sa) = 8;
12 sa.sin_addr.s_addr = addr;
13 ent = (struct table_entry *)(rnh->rnh_lookup(&sa, NULL, rnh));
14 if (ent != NULL) {
15 *val = ent->value;
16 return ( 1);
17 }
18 return (0);
19 }
struct radix_node_head *rnh;
struct table_entry *ent;
struct sockaddr_in sa;