[Xorp-hackers] XORP, Click and its configuration...
Rafael Paoliello Guimaraes
rafael.guimaraes@ac.upc.edu
Wed, 26 Jan 2005 13:39:41 +0100
This is a multi-part message in MIME format.
--------------060504090302010507020407
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Hello,
I was trying to use the click element KernelTun in my click
configuration in order to allow packets generated by the same computer
to be routed through click. In order to do this, I have changed the
xorp_fea_click_config_generator script. This new script (which I am
attaching to this email) works fine, it creates a new TUN interface
(tun0) with 172.16.0.1 as its address. Finally, I have to create a
default route to this new interface and delete every other route (so
that all generated packets go through tun0) and configured linux not to
do forwarding (in order to let this functionality to click).
By doing this, I am able to ping to every node and almost everything
goes fine. The only problem is that, whenever I create a new route (I
tried through static_routes), the TUN interfaces changes from tun0 to
tun1. And if I create another route (or delete an existant one), it goes
from tun0 to tun1. Why is this happening? Does XORP reinitiate Click
after each route change? How can I avoid this?
Cheers,
--
===========================================
Rafael Paoliello Guimaraes
PhD Student - Computer Networking Group
Department of Computer Architecture (DAC)
Polytechnic University of Catalonia (UPC)
Phone: +34-934017187 Fax: +34-934017055
URL: http://people.ac.upc.es/rpaoliel
===========================================
--------------060504090302010507020407
Content-Type: text/plain;
name="xorp_fea_click_config_generator"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="xorp_fea_click_config_generator"
#!/usr/bin/awk -f
#
# $XORP: xorp/fea/xorp_fea_click_config_generator,v 1.9 2004/12/18 02:03:21 pavlin Exp $
#
#
# A sample script to generate Click configuration from XORP configuration.
# The first argument is the XORP configuration file name.
#
# Currently, the script is called on-demand by the FEA whenever
# the network interface information changes.
#
# Requirements:
# 1. The Click lookup element name must be "_xorp_rt".
# That element must support interface similar to element LinearIPLookup()
# for adding and removing forwarding entries.
# 2. The first network interface/vif must be connected to _xorp_rt[0],
# the second network interface/vif must be connected to _xorp_rt[1],
# and so-on.
#
# Note that if both kernel-level and user-level Click are enabled
# (which is allowed), this script will print the kernel-level Click
# configuration.
#
BEGIN {
# Various constants
ipv4_addr_bitlen = 32; # IPv4 address bitmask length
ipv6_addr_bitlen = 128; # IPv6 address bitmask length
iftree_interfaces_max = 0;
iftree_vifs_max = 0;
is_click_enabled = 0;
is_kernel_click = 0;
is_user_click = 0;
is_debug = 0;
xorp_ip = "_xorp_ip";
xorp_rt = "_xorp_rt";
xorp_arpt = "_xorp_arpt";
xorp_toh = "_xorp_toh";
# TODO: XXX: fix ether_encap if necessary
ether_encap = "EtherEncap(0x0800, 1:1:1:1:1:1, 2:2:2:2:2:2)";
statement = "";
in_comment = 0;
is_syntax_error = 0;
is_internal_error = 0;
config_level = 0;
ignore_level[0] = 1;
is_level0_interfaces = 0;
is_level0_fea = 0;
is_level0_fea_level1_click = 0;
is_level0_fea_level1_click_level2_kernel_click = 0;
is_level0_fea_level1_click_level2_user_click = 0;
is_ipv4_address = 0;
is_ipv6_address = 0;
max_xorp_rt_port = 0;
iftree_interfaces_targetname = "fea";
fea_targetname = "fea";
# KernelTun Initializations: rafael
# kerneltun_ip_addr = "192.168.254.1"
# kerneltun_ip_prefix = "24"
# kerneltun_port = 0;
}
function calculate_state()
{
iftree_vifs_max = 0;
xorp_rt_port = 0;
#
# Clear-up some temporary state
# At the same time, compute the value of iftree_vifs_max
#
for (ii = 0; ii < iftree_interfaces_max; ii++) {
ifaces_chosen[ii] = 0;
for (vi = 0; vi < iftree_interfaces_vifs_max[ii]; vi++) {
ifaces_vifs_chosen[ii,vi] = 0;
iftree_vifs_max++;
}
}
#
# Select the interfaces and vifs by using string comparison:
# the "smaller" name first.
#
for (ci = 0; ci < iftree_interfaces_max; ci++) {
best_ii = -1;
for (ii = 0; ii < iftree_interfaces_max; ii++) {
if (ifaces_chosen[ii])
continue;
if (best_ii == -1) {
best_ii = ii;
continue;
}
best_ifname = iftree_interfaces_ifname[best_ii];
if (iftree_interfaces_ifname[ii] < best_ifname) {
best_ii = ii;
}
}
if (best_ii < 0) {
internal_error("Internal error: cannot sort the interface names\n");
}
ifaces_chosen[best_ii] = 1;
for (cv = 0; cv < iftree_interfaces_vifs_max[best_ii]; cv++) {
best_vi = -1;
for (vi = 0; vi < iftree_interfaces_vifs_max[best_ii]; vi++) {
if (ifaces_vifs_chosen[best_ii,vi])
continue;
if (best_vi == -1) {
best_vi = vi;
continue;
}
best_vifname = iftree_interfaces_vifs_vifname[best_ii,best_vi];
if (iftree_interfaces_vifs_vifname[best_ii,vi] < best_vifname) {
best_vi = vi;
}
}
if (best_vi < 0) {
internal_error("Internal error: cannot sort the vif names\n");
}
ifaces_vifs_chosen[best_ii,best_vi] = 1;
iftree_interfaces_vifs_port[best_ii,best_vi] = xorp_rt_port++;
}
# KernelTun: rafael
# kerneltun_port = xorp_rt_port++;
}
max_xorp_rt_port = xorp_rt_port;
}
function check_state()
{
for (ii = 0; ii < iftree_interfaces_max; ii++) {
ifname = iftree_interfaces_ifname[ii];
if (iftree_interfaces_has_mac[ii] != 1) {
message = "Missing MAC address configuration for interface " ifname;
syntax_error(message);
}
if (iftree_interfaces_has_mtu[ii] != 1) {
message = "Missing MTU configuration for interface " ifname;
syntax_error(message);
}
}
}
function generate_click_config_header()
{
printf("//\n");
printf("// Generated by XORP FEA\n");
printf("//\n");
}
function generate_kerneltun()
{
printf("\nelementclass FixChecksums {\n");
printf(" input -> SetIPChecksum\n");
printf(" -> ipc :: IPClassifier(tcp, udp, -)\n");
printf(" -> SetTCPChecksum\n");
printf(" -> output;\n");
printf(" ipc[1] -> SetUDPChecksum -> output;\n");
printf(" ipc[2] -> output\n");
printf("}\n\n");
printf("tun :: KernelTun(172.16.0.1/24) -> Paint(0) -> _xorp_rt;\n\n");
}
function generate_click_shared_ip_input()
{
check_ip_header = "CheckIPHeader(INTERFACES";
local_ip_routes = "";
is_first_address = 1;
for (ii = 0; ii < iftree_interfaces_max; ii++) {
for (vi = 0; vi < iftree_interfaces_vifs_max[ii]; vi++) {
for (ai4 = 0; ai4 < iftree_interfaces_vifs_addresses4_max[ii,vi]; ai4++) {
addr4 = iftree_interfaces_vifs_addresses4_addr[ii,vi,ai4];
prefix4 = iftree_interfaces_vifs_addresses4_prefix[ii,vi,ai4];
check_ip_header = check_ip_header " " addr4 "/" prefix4;
route = addr4 "/" ipv4_addr_bitlen " " max_xorp_rt_port;
if (is_first_address) {
local_ip_routes = route;
is_first_address = 0;
} else {
local_ip_routes = local_ip_routes ", " route;
}
}
}
}
check_ip_header = check_ip_header ")";
printf("\n");
printf("// Shared IP input path and routing table\n");
printf("%s :: Strip(14)\n", xorp_ip);
printf(" -> %s\n", check_ip_header);
printf(" -> %s :: LinearIPLookup(%s);\n", xorp_rt, local_ip_routes);
}
function generate_click_arp_responses()
{
printf("\n");
printf("// ARP responses are copied to each ARPQuerier and the host.\n");
printf("%s :: Tee(%u);\n", xorp_arpt, iftree_vifs_max + 1);
}
function generate_click_input_output_paths()
{
port = 0;
for (ii = 0; ii < iftree_interfaces_max; ii++) {
for (vi = 0; vi < iftree_interfaces_vifs_max[ii]; vi++) {
xorp_c = "_xorp_c" port;
xorp_out = "_xorp_out" port;
xorp_to_device = "_xorp_to_device" port;
xorp_ar = "_xorp_ar" port;
xorp_arpq = "_xorp_arpq" port;
if (! iftree_interfaces_vifs_enabled[ii,vi]) {
from_device = "NullDevice";
} else {
#
# TODO: XXX: we should find a way to configure polling
# devices. Such devices should use "PollDevice" instead
# of "FromDevice".
#
from_device = "FromDevice(" iftree_interfaces_vifs_vifname[ii,vi] ")";
}
if (! iftree_interfaces_vifs_enabled[ii,vi]) {
to_device = "Discard";
} else {
to_device = "ToDevice(" iftree_interfaces_vifs_vifname[ii,vi] ")";
}
arp_responder = "ARPResponder(";
mac = iftree_interfaces_mac[ii];
is_begin = 1;
for (ai4 = 0; ai4 < iftree_interfaces_vifs_addresses4_max[ii,vi]; ai4++) {
addr4 = iftree_interfaces_vifs_addresses4_addr[ii,vi,ai4];
if (is_begin)
arp_responder = arp_responder addr4;
else
arp_responder = arp_responder " " addr4;
is_begin = 0;
}
arp_responder = arp_responder " " mac ")";
first_addr4 = "0.0.0.0";
if (iftree_interfaces_vifs_addresses4_max[ii,vi] > 0) {
first_addr4 = iftree_interfaces_vifs_addresses4_addr[ii,vi,0];
}
arp_querier = "ARPQuerier(" first_addr4 ", " mac ")";
paint = "Paint(" port + 1 ")";
print_non_ip = "Print(\"" iftree_interfaces_vifs_vifname[ii,vi] " non-IP\")";
printf("\n");
printf("// Input and output paths for %s\n",
iftree_interfaces_vifs_vifname[ii,vi]);
printf("%s :: Classifier(12/0806 20/0001, 12/0806 20/0002, 12/0800, -);\n",
xorp_c);
printf("%s -> %s;\n",
from_device,
xorp_c);
printf("%s :: Queue(200) -> %s :: %s;\n",
xorp_out,
xorp_to_device,
to_device);
printf("%s[0] -> %s :: %s -> %s;\n",
xorp_c,
xorp_ar,
arp_responder,
xorp_out);
printf("%s :: %s -> %s;\n",
xorp_arpq,
arp_querier,
xorp_out);
printf("%s[1] -> %s;\n",
xorp_c,
xorp_arpt);
printf("%s[%u] -> [1]%s;\n",
xorp_arpt,
port,
xorp_arpq);
printf("%s[2] -> %s -> %s;\n",
xorp_c,
paint,
xorp_ip);
printf("%s[3] -> %s -> Discard;\n",
xorp_c,
print_non_ip);
port++;
}
}
# KernelTun ARPResponder configuration: rafael
}
function generate_click_send_packets_to_host()
{
printf("\n");
printf("// Local delivery\n");
# TODO: XXX: Fix the Local delivery for *BSD and/or user-level Click
if (is_kernel_click) {
#
# XXX: Note that if both kernel-level and user-level Click are enabled
# (which is allowed), this script will print the kernel-level Click
# configuration.
#
printf("%s[%u] -> ToHost;\n",
xorp_arpt,
iftree_vifs_max);
# XXX: last port in xorp_rt is reserved for local delivery
printf("%s[%u] -> %s -> ToHost;\n",
xorp_rt,
max_xorp_rt_port,
ether_encap);
} else {
printf("%s[%u] -> Discard;\n",
xorp_arpt,
iftree_vifs_max);
# XXX: last port in xorp_rt is reserved for local delivery
printf("%s[%u] -> Discard;\n",
xorp_rt,
max_xorp_rt_port);
}
}
function generate_click_forwarding_paths()
{
#
# Forwarding paths for each interface
#
port = 0;
for (ii = 0; ii < iftree_interfaces_max; ii++) {
for (vi = 0; vi < iftree_interfaces_vifs_max[ii]; vi++) {
xorp_cp = "_xorp_cp" port;
paint_tee = "PaintTee(" port + 1 ")";
xorp_gio = "_xorp_gio" port;
xorp_dt = "_xorp_dt" port;
xorp_fr = "_xorp_fr" port;
xorp_arpq = "_xorp_arpq" port;
xorp_sw = "_xorp_sw" port;
ipgw_options = "IPGWOptions(";
is_begin = 1;
for (ai4 = 0; ai4 < iftree_interfaces_vifs_addresses4_max[ii,vi]; ai4++) {
addr4 = iftree_interfaces_vifs_addresses4_addr[ii,vi,ai4];
if (is_begin)
ipgw_options = ipgw_options addr4;
else
ipgw_options = ipgw_options ", " addr4;
is_begin = 0;
}
ipgw_options = ipgw_options ")";
first_addr4 = "0.0.0.0";
if (iftree_interfaces_vifs_addresses4_max[ii,vi] > 0) {
first_addr4 = iftree_interfaces_vifs_addresses4_addr[ii,vi,0];
}
fix_ip_src = "FixIPSrc(" first_addr4 ")";
mtu = iftree_interfaces_mtu[ii];
ip_fragmenter = "IPFragmenter(" mtu ")";
printf("\n");
printf("// Forwarding path for %s\n",
iftree_interfaces_vifs_vifname[ii,vi]);
xorp_rt_port = iftree_interfaces_vifs_port[ii,vi];
printf("%s[%u] -> DropBroadcasts -> %s :: PaintSwitch();\n",
xorp_rt,
xorp_rt_port,
xorp_sw);
printf("%s :: %s\n",
xorp_gio,
ipgw_options);
printf(" -> %s\n",
fix_ip_src);
printf(" -> %s :: DecIPTTL\n",
xorp_dt);
printf(" -> %s :: %s\n",
xorp_fr,
ip_fragmenter);
printf(" -> [0]%s;\n\n",
xorp_arpq);
printf("%s[0] -> StoreIPAddress(%s,12) -> FixChecksums -> %s;\n",
xorp_sw,
first_addr4,
xorp_fr);
for (jj = 0; jj < iftree_interfaces_max; jj++) {
for (vj = 0; vj < iftree_interfaces_vifs_max[jj]; vj++) {
xorp_rt_port2 = iftree_interfaces_vifs_port[jj,vj];
if (jj == ii && vj == vi) {
printf("%s[%u] -> %s :: Tee(2) -> ICMPError(%s, redirect, host) -> %s;\n",
xorp_sw,
xorp_rt_port2+1,
xorp_cp,
first_addr4,
xorp_rt);
} else {
printf("%s[%u] -> %s;\n",
xorp_sw,
xorp_rt_port2+1,
xorp_gio);
}
}
}
printf("%s[1] -> %s\n",
xorp_cp,
xorp_gio);
printf("%s[1] -> ICMPError(%s, timeexceeded) -> %s;\n",
xorp_dt,
first_addr4,
xorp_rt);
printf("%s[1] -> ICMPError(%s, unreachable, needfrag) -> %s;\n",
xorp_fr,
first_addr4,
xorp_rt);
printf("%s[1] -> ICMPError(%s, parameterproblem) -> %s;\n",
xorp_gio,
first_addr4,
xorp_rt);
port++;
}
}
}
function is_end_of_statement(token)
{
# Get the last character
l = length(token);
s = substr(token, l, 1);
if (s == ";")
return 1;
else
return 0;
}
function is_end_of_string(token)
{
# Get the last character
l = length(token);
s = substr(token, l, 1);
if (s == "\"")
return 1;
else
return 0;
}
function is_begin_of_comment(token)
{
# Get the first two characters
l = length(token);
if (l < 2)
return 0;
s = substr(token, 1, 2);
if (s == "/*")
return 1;
else
return 0;
}
function is_end_of_comment(token)
{
# Get the last two characters
l = length(token);
if (l < 2)
return 0;
s = substr(token, l-1, 2);
if (s == "*/")
return 1;
else
return 0;
}
function process_statement(statement)
{
if (is_debug)
printf("Statement: %s\n", statement);
tokens_n = split(statement, tokens);
for (i = 1; i <= tokens_n; i++) {
# printf("Token: %s\n", tokens[i]);
}
# TODO: need to deal with strings
for (i = 1; i <= tokens_n; i++) {
if (tokens[i] == "{") {
config_level++;
continue;
}
if (tokens[i] == "}") {
config_level--;
if (config_level < 0)
syntax_error("Too many }");
continue;
}
if (config_level == 0) {
ignore_level[0] = 1;
is_level0_interfaces = 0;
is_level0_fea = 0;
is_level0_fea_level1_click = 0;
is_level0_fea_level1_click_level2_kernel_click = 0;
is_level0_fea_level1_click_level2_user_click = 0;
if (tokens[i] == "interfaces") {
ignore_level[0] = 0;
is_level0_interfaces = 1;
}
if (tokens[i] == "fea") {
ignore_level[0] = 0;
is_level0_fea = 1;
is_level0_fea_level1_click = 0;
is_level0_fea_level1_click_level2_kernel_click = 0;
is_level0_fea_level1_click_level2_user_click = 0;
}
}
if (ignore_level[0])
continue;
#
# Configuration section: "interfaces {}"
#
if (is_level0_interfaces && (config_level == 1)) {
if (tokens[i] == "targetname:") {
if (i == tokens_n)
syntax_error("Missing target name");
i++;
v = tokens[i];
iftree_interfaces_targetname = v;
continue;
}
if (tokens[i] == "interface") {
if (i == tokens_n)
syntax_error("Missing interface name");
i++;
# TODO: check that the interface name is valid
v = tokens[i];
iftree_interfaces_max++;
iftree_interfaces_ifname[iftree_interfaces_max - 1] = v;
# XXX: by default each interface is enabled
iftree_interfaces_enabled[iftree_interfaces_max - 1] = 1;
continue;
}
syntax_error("Invalid keyword");
}
if (is_level0_interfaces && (config_level == 2)) {
if (tokens[i] == "enabled:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
if (v == "true")
iftree_interfaces_enabled[iftree_interfaces_max - 1] = 1;
else
iftree_interfaces_enabled[iftree_interfaces_max - 1] = 0;
continue;
}
if (tokens[i] == "discard:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
iftree_interfaces_discard[iftree_interfaces_max - 1] = v;
continue;
}
if (tokens[i] == "description:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
while (! is_end_of_string(v)) {
if (i == tokens_n)
syntax_error("Missing end-of-string");
i++;
v = v " " tokens[i];
}
iftree_interfaces_description[iftree_interfaces_max - 1] = v;
continue;
}
if (tokens[i] == "mac:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
iftree_interfaces_mac[iftree_interfaces_max - 1] = v;
iftree_interfaces_has_mac[iftree_interfaces_max - 1] = 1;
continue;
}
if (tokens[i] == "mtu:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
iftree_interfaces_mtu[iftree_interfaces_max - 1] = v;
iftree_interfaces_has_mtu[iftree_interfaces_max - 1] = 1;
continue;
}
if (tokens[i] == "vif") {
if (i == tokens_n)
syntax_error("Missing vif name");
i++;
# TODO: check that the vif name is valid
v = tokens[i];
p = iftree_interfaces_max - 1;
iftree_interfaces_vifs_max[p]++;
q = iftree_interfaces_vifs_max[p] - 1;
iftree_interfaces_vifs_vifname[p,q] = v;
# XXX: by default each vif is enabled
iftree_interfaces_vifs_enabled[p,q] = 1;
continue;
}
syntax_error("Invalid keyword");
}
if (is_level0_interfaces && (config_level == 3)) {
if (tokens[i] == "enabled:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (v == "true")
iftree_interfaces_vifs_enabled[p,q] = 1;
else
iftree_interfaces_vifs_enabled[p,q] = 0;
continue;
}
if (tokens[i] == "address") {
if (i == tokens_n)
syntax_error("Missing address value");
i++;
# TODO: check that the address value is valid
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
is_ipv4_address = 0;
is_ipv6_address = 0;
if (split(v, tmp_array, ".") == 4)
is_ipv4_address = 1;
if (split(v, tmp_array, ":") > 1)
is_ipv6_address = 1;
if (!( is_ipv4_address || is_ipv6_address))
syntax_error("Invalid address value");
if (is_ipv4_address) {
iftree_interfaces_vifs_addresses4_max[p,q]++;
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
iftree_interfaces_vifs_addresses4_addr[p,q,r] = v;
}
if (is_ipv6_address) {
iftree_interfaces_vifs_addresses6_max[p,q]++;
r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
iftree_interfaces_vifs_addresses6_addr[p,q,r] = v;
}
continue;
}
syntax_error("Invalid keyword");
}
if (is_level0_interfaces && (config_level == 4)) {
if (tokens[i] == "prefix-length:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (is_ipv4_address) {
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
iftree_interfaces_vifs_addresses4_prefix[p,q,r] = v;
}
if (is_ipv6_address) {
r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
iftree_interfaces_vifs_addresses6_prefix[p,q,r] = v;
}
continue;
}
if (tokens[i] == "broadcast:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (is_ipv4_address) {
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
iftree_interfaces_vifs_addresses4_destination[p,q,r] = v;
}
if (is_ipv6_address) {
syntax_error("Invalid keyword");
}
continue;
}
if (tokens[i] == "destination:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (is_ipv4_address) {
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
iftree_interfaces_vifs_addresses4_destination[p,q,r] = v;
}
if (is_ipv6_address) {
r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
iftree_interfaces_vifs_addresses6_destination[p,q,r] = v;
}
continue;
}
if (tokens[i] == "multicast-capable:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (is_ipv4_address) {
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
iftree_interfaces_vifs_addresses4_multicast[p,q,r] = v;
}
if (is_ipv6_address) {
r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
iftree_interfaces_vifs_addresses6_multicast[p,q,r] = v;
}
continue;
}
if (tokens[i] == "point-to-point:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (is_ipv4_address) {
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
iftree_interfaces_vifs_addresses4_p2p[p,q,r] = v;
}
if (is_ipv6_address) {
r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
iftree_interfaces_vifs_addresses6_p2p[p,q,r] = v;
}
continue;
}
if (tokens[i] == "loopback:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (is_ipv4_address) {
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
iftree_interfaces_vifs_addresses4_loopback[p,q,r] = v;
}
if (is_ipv6_address) {
r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
iftree_interfaces_vifs_addresses6_loopback[p,q,r] = v;
}
continue;
}
if (tokens[i] == "enabled:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
p = iftree_interfaces_max - 1;
q = iftree_interfaces_vifs_max[p] - 1;
if (is_ipv4_address) {
r = iftree_interfaces_vifs_addresses4_max[p,q] - 1;
if (v == "true")
iftree_interfaces_vifs_addresses4_enabled[p,q,r] = 1;
else
iftree_interfaces_vifs_addresses4_enabled[p,q,r] = 0;
}
if (is_ipv6_address) {
r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
if (v == "true")
iftree_interfaces_vifs_addresses6_enabled[p,q,r] = 1;
else
iftree_interfaces_vifs_addresses6_enabled[p,q,r] = 0;
}
continue;
}
syntax_error("Invalid keyword");
}
#
# Configuration section: "fea {}"
#
if (is_level0_fea && (config_level == 1)) {
if (tokens[i] == "targetname:") {
if (i == tokens_n)
syntax_error("Missing target name");
i++;
v = tokens[i];
fea_targetname = v;
continue;
}
if (tokens[i] == "click") {
is_level0_fea_level1_click = 1;
is_level0_fea_level1_click_level2_kernel_click = 0;
is_level0_fea_level1_click_level2_user_click = 0;
continue;
}
# XXX: ignore the rest of the configuration
continue;
}
if (is_level0_fea && is_level0_fea_level1_click &&
(config_level == 2)) {
if (tokens[i] == "enabled:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
if (v == "true")
is_click_enabled = 1;
else
is_click_enabled = 0;
continue;
}
if (tokens[i] == "kernel-click") {
is_level0_fea_level1_click_level2_kernel_click = 1;
is_level0_fea_level1_click_level2_user_click = 0;
continue;
}
if (tokens[i] == "user-click") {
is_level0_fea_level1_click_level2_kernel_click = 0;
is_level0_fea_level1_click_level2_user_click = 1;
continue;
}
# XXX: ignore the rest of the configuration
continue;
}
if (is_level0_fea && is_level0_fea_level1_click &&
is_level0_fea_level1_click_level2_kernel_click &&
(config_level == 3)) {
if (tokens[i] == "enabled:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
if (v == "true") {
is_kernel_click = 1;
} else {
is_kernel_click = 0;
}
continue;
}
# XXX: ignore the rest of the configuration
continue;
}
if (is_level0_fea && is_level0_fea_level1_click &&
is_level0_fea_level1_click_level2_user_click &&
(config_level == 3)) {
if (tokens[i] == "enabled:") {
if (i == tokens_n)
syntax_error("Missing value");
i++;
v = tokens[i];
if (v == "true") {
is_user_click = 1;
} else {
is_user_click = 0;
}
continue;
}
# XXX: ignore the rest of the configuration
continue;
}
}
}
function syntax_error(message)
{
is_syntax_error = 1;
printf("Syntax error (file %s line %d): %s\n", FILENAME, FNR, message);
exit(1);
}
function internal_error(message)
{
is_internal_error = 1;
printf("Internal error (file %s): %s\n", FILENAME, message);
exit(1);
}
{
for (i = 1; i <= NF; i++) {
token = $i;
# Filter-out the comments
if (is_begin_of_comment(token)) {
if (in_comment)
syntax_error("Nested comments");
in_comment = 1;
}
if (in_comment) {
if (is_end_of_comment(token))
in_comment = 0;
continue;
}
if (is_end_of_comment(token))
syntax_error("Missing begin-of-comment");
statement = statement " " token;
if (is_end_of_statement(token)) {
process_statement(statement);
statement = "";
}
}
process_statement(statement);
statement = "";
}
END {
#
# Initialize internal state
#
calculate_state();
check_state();
#
# Check for syntax and internal errors
#
if (is_syntax_error || is_internal_error)
exit(1);
#
# Check if Click is enabled and whether it is user-level or kernel Click
#
if (! is_click_enabled)
exit(0); # XXX: don't print any Click configuration
if ((! is_user_click) && (! is_kernel_click))
exit(0); # XXX: don't print any Click configuration
generate_click_config_header();
generate_click_shared_ip_input();
generate_kerneltun();
generate_click_arp_responses();
generate_click_input_output_paths();
generate_click_send_packets_to_host();
generate_click_forwarding_paths();
#
# Check again for syntax and internal errors
#
if (is_syntax_error || is_internal_error)
exit(1);
exit(0);
}
# Local Variables:
# mode: AWK
# sh-indentation: 4
# End:
--------------060504090302010507020407--