Add a new feature for optimizining ipfw rulesets - substitution of the
  action argument with the value obtained from table lookup. The feature
  is now applicable only to "pipe", "queue", "divert", "tee", "netgraph"
  and "ngtee" rules.
This commit is contained in:
glebius 2006-01-15 01:00:55 +00:00
parent 9bfc349ebe
commit 470df2fb19
4 changed files with 95 additions and 52 deletions

View File

@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd August 13, 2005
.Dd January 16, 2006
.Dt IPFW 8
.Os
.Sh NAME
@ -1523,6 +1523,19 @@ the routing table (see
.Xr route 4 ) .
.Pp
Lookup tables currently support IPv4 addresses only.
.Pp
The
.Cm tablearg
feature provides the ability to use a value, looked up in the table, as
the argument for a rule action.
This can significantly reduce number of rules in some configurations.
The
.Cm tablearg
argument can be used with the following actions:
.Cm pipe , queue, divert, tee, netgraph, ngtee .
See the
.Sx EXAMPLES
Section for example usage of tables and the tablearg keyword.
.Sh SETS OF RULES
Each rule belongs to one of 32 different
.Em sets
@ -2425,6 +2438,23 @@ on a net with per-host limits, rather than per-network limits:
.Dl "ipfw add pipe 2 ip from any to 192.168.2.0/24 in"
.Dl "ipfw pipe 1 config mask src-ip 0x000000ff bw 200Kbit/s queue 20Kbytes"
.Dl "ipfw pipe 2 config mask dst-ip 0x000000ff bw 200Kbit/s queue 20Kbytes"
.Ss LOOKUP TABLES
In the following example, we need to create several traffic bandwidth
classes and we need different hosts/networks to fall into different classes.
We create one pipe for each class and configure them accordingly.
Then we create a single table and fill it with IP subnets and addresses.
For each subnet/host we set the argument equal to the number of the pipe
that it should use.
Then we classify traffic using a single rule:
.Pp
.Dl "ipfw pipe 1 config bw 1000Kbyte/s"
.Dl "ipfw pipe 4 config bw 4000Kbyte/s"
.Dl "..."
.Dl "ipfw table 1 add 192.168.2.0/24 1"
.Dl "ipfw table 1 add 192.168.0.0/27 4"
.Dl "ipfw table 1 add 192.168.0.2 1"
.Dl "..."
.Dl "ipfw pipe tablearg ip from table(1) to any"
.Ss SETS OF RULES
To add a set of rules atomically, e.g.\& set 18:
.Pp

View File

@ -420,6 +420,8 @@ struct _s_x rule_options[] = {
{ NULL, 0 } /* terminator */
};
#define TABLEARG "tablearg"
static __inline uint64_t
align_uint64(uint64_t *pll) {
uint64_t ret;
@ -1457,33 +1459,28 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
print_unreach6_code(cmd->arg1);
break;
#define PRINT_WITH_ARG(o) \
if (cmd->arg1 == IP_FW_TABLEARG) \
printf("%s tablearg", (o)); \
else \
printf("%s %u", (o), cmd->arg1); \
break;
case O_SKIPTO:
printf("skipto %u", cmd->arg1);
break;
PRINT_WITH_ARG("skipto");
case O_PIPE:
printf("pipe %u", cmd->arg1);
break;
PRINT_WITH_ARG("pipe");
case O_QUEUE:
printf("queue %u", cmd->arg1);
break;
PRINT_WITH_ARG("queue");
case O_DIVERT:
printf("divert %u", cmd->arg1);
break;
PRINT_WITH_ARG("divert");
case O_TEE:
printf("tee %u", cmd->arg1);
break;
PRINT_WITH_ARG("tee");
case O_NETGRAPH:
printf("netgraph %u", cmd->arg1);
break;
PRINT_WITH_ARG("netgraph");
case O_NGTEE:
printf("ngtee %u", cmd->arg1);
break;
PRINT_WITH_ARG("ngtee");
#undef PRINT_WITH_ARG
case O_FORWARD_IP:
{
@ -3863,26 +3860,38 @@ add(int ac, char *av[])
break;
case TOK_QUEUE:
action->len = F_INSN_SIZE(ipfw_insn_pipe);
action->opcode = O_QUEUE;
goto chkarg;
case TOK_PIPE:
action->len = F_INSN_SIZE(ipfw_insn_pipe);
action->opcode = O_PIPE;
goto chkarg;
case TOK_SKIPTO:
if (i == TOK_QUEUE)
action->opcode = O_QUEUE;
else if (i == TOK_PIPE)
action->opcode = O_PIPE;
else if (i == TOK_SKIPTO)
action->opcode = O_SKIPTO;
NEED1("missing skipto/pipe/queue number");
action->arg1 = strtoul(*av, NULL, 10);
av++; ac--;
break;
action->opcode = O_SKIPTO;
goto chkarg;
case TOK_NETGRAPH:
action->opcode = O_NETGRAPH;
goto chkarg;
case TOK_NGTEE:
action->opcode = O_NGTEE;
goto chkarg;
case TOK_DIVERT:
action->opcode = O_DIVERT;
goto chkarg;
case TOK_TEE:
action->opcode = (i == TOK_DIVERT) ? O_DIVERT : O_TEE;
NEED1("missing divert/tee port");
action->arg1 = strtoul(*av, NULL, 0);
if (action->arg1 == 0) {
action->opcode = O_TEE;
chkarg:
if (!ac)
errx(EX_USAGE, "missing argument for %s", *(av - 1));
if (isdigit(**av)) {
action->arg1 = strtoul(*av, NULL, 10);
if (action->arg1 <= 0 || action->arg1 >= IP_FW_TABLEARG)
errx(EX_DATAERR, "illegal argument for %s",
*(av - 1));
} else if (_substrcmp(*av, TABLEARG) == 0) {
action->arg1 = IP_FW_TABLEARG;
} else if (i == TOK_DIVERT || i == TOK_TEE) {
struct servent *s;
setservent(1);
s = getservbyname(av[0], "divert");
@ -3890,17 +3899,8 @@ add(int ac, char *av[])
action->arg1 = ntohs(s->s_port);
else
errx(EX_DATAERR, "illegal divert/tee port");
}
ac--; av++;
break;
case TOK_NETGRAPH:
case TOK_NGTEE:
action->opcode = (i == TOK_NETGRAPH ) ? O_NETGRAPH : O_NGTEE;
NEED1("missing netgraph cookie");
action->arg1 = strtoul(*av, NULL, 0);
if (action->arg1 == 0)
errx(EX_DATAERR, "illegal netgraph cookie");
} else
errx(EX_DATAERR, "illegal argument for %s", *(av - 1));
ac--; av++;
break;

View File

@ -474,6 +474,8 @@ typedef struct _ipfw_table {
ipfw_table_entry ent[0]; /* entries */
} ipfw_table;
#define IP_FW_TABLEARG 65535
/*
* Main firewall chains definitions and global var's definitions.
*/

View File

@ -2383,9 +2383,9 @@ do { \
* Now scan the rules, and parse microinstructions for each rule.
*/
for (; f; f = f->next) {
int l, cmdlen;
ipfw_insn *cmd;
int skip_or; /* skip rest of OR block */
uint32_t tablearg = 0;
int l, cmdlen, skip_or; /* skip rest of OR block */
again:
if (set_disable & (1 << f->set) )
@ -2548,6 +2548,8 @@ check_body:
if (cmdlen == F_INSN_SIZE(ipfw_insn_u32))
match =
((ipfw_insn_u32 *)cmd)->d[0] == v;
else
tablearg = v;
}
break;
@ -2999,7 +3001,10 @@ check_body:
case O_PIPE:
case O_QUEUE:
args->rule = f; /* report matching rule */
args->cookie = cmd->arg1;
if (cmd->arg1 == IP_FW_TABLEARG)
args->cookie = tablearg;
else
args->cookie = cmd->arg1;
retval = IP_FW_DUMMYNET;
goto done;
@ -3020,7 +3025,10 @@ check_body:
}
dt = (struct divert_tag *)(mtag+1);
dt->cookie = f->rulenum;
dt->info = cmd->arg1;
if (cmd->arg1 == IP_FW_TABLEARG)
dt->info = tablearg;
else
dt->info = cmd->arg1;
m_tag_prepend(m, mtag);
retval = (cmd->opcode == O_DIVERT) ?
IP_FW_DIVERT : IP_FW_TEE;
@ -3085,7 +3093,10 @@ check_body:
case O_NETGRAPH:
case O_NGTEE:
args->rule = f; /* report matching rule */
args->cookie = cmd->arg1;
if (cmd->arg1 == IP_FW_TABLEARG)
args->cookie = tablearg;
else
args->cookie = cmd->arg1;
retval = (cmd->opcode == O_NETGRAPH) ?
IP_FW_NETGRAPH : IP_FW_NGTEE;
goto done;