Revision: 11651
          http://xorp.svn.sourceforge.net/xorp/?rev=11651&view=rev
Author:   bms_fbsd
Date:     2009-12-03 17:00:44 +0000 (Thu, 03 Dec 2009)

Log Message:
-----------
forcibly re-add.

Added Paths:
-----------
    trunk/xorp/fea/fea_click_config_generator

Added: trunk/xorp/fea/fea_click_config_generator
===================================================================
--- trunk/xorp/fea/fea_click_config_generator                           (rev 0)
+++ trunk/xorp/fea/fea_click_config_generator   2009-12-03 17:00:44 UTC (rev 
11651)
@@ -0,0 +1,1151 @@
+#!/usr/bin/awk -f
+#
+# $XORP: xorp/fea/xorp_fea_click_config_generator,v 1.13 2007/09/27 00:33:34 
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 names must be "_xorp_rt4" for IPv4 and
+#    "_xorp_rt6" for IPv6.  Those elements must support handler interface
+#    compatible to elements LinearIPLookup() and LookupIP6Route()
+#    respectively for adding and removing forwarding entries.
+# 2. The first network interface/vif must be connected to _xorp_rt4[0] and
+#    _xorp_rt6[0], the second network interface/vif must be connected to
+#    _xorp_rt4[1] and _xorp_rt6[1], and so-on.
+#    The last port in _xorp_rt{4,6} is reserved for local delivery.
+#    Note that the interfaces/vifs are ordered lexigraphically by their names.
+#
+# Note that if both kernel-level and user-level Click are enabled
+# (which is allowed), this script will print the kernel-level Click
+# configuration.
+#
+# TODO: for now the IPv6 path generation is disabled by default, because:
+#   - There are few incomplete IPv6-related pieces (search for the "TODO"
+#     marker in the code below).
+#   - Currently the lastest Click release (1.4.3) does not support an
+#     IPv6 lookup element that has "add" and "delete" handlers to
+#     add/delete routing entries.
+#     Note that the lastest implementation of the LookupIP6Route()
+#     in the CVS tree supports those two handlers.
+#
+# To enable IPv6 path generation, modify below:
+#    enable_ipv6 = 0;
+# to
+#    enable_ipv6 = 1;
+#
+
+BEGIN {
+    # XXX: for now IPv6 generation is disabled
+    enable_ipv6 = 0;
+
+    # Lookup element flavor selection
+    # IPv4: LinearIPLookup, DirectIPLookup and TrieIPLookup should work
+    ipv4_lookup_element = "LinearIPLookup";
+    # IPv6: LookupIP6Route is the only option at the moment
+    ipv6_lookup_element = "LookupIP6Route";
+
+    # 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_ip4 = "_xorp_ip4";
+    xorp_rt4 = "_xorp_rt4";
+    xorp_ip6 = "_xorp_ip6";
+    xorp_rt6 = "_xorp_rt6";
+    xorp_arpt = "_xorp_arpt";
+    xorp_toh = "_xorp_toh";
+    # TODO: XXX: fix ether_encap if necessary
+    ether_encap4 = "EtherEncap(0x0800, 1:1:1:1:1:1, 2:2:2:2:2:2)";
+    ether_encap6 = "EtherEncap(0x86dd, 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";
+}
+
+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++;
+       }
+    }
+
+    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_click_shared_ip_input()
+{
+    check_ipv4_header = "CheckIPHeader(INTERFACES";
+    local_ipv4_routes = "";
+    check_ipv6_header = "CheckIP6Header(";     # TODO: is this enough?
+    local_ipv6_routes = "";
+    is_first_address4 = 1;
+    is_first_address6 = 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_ipv4_header = check_ipv4_header " " addr4 "/" prefix4;
+               route = addr4 "/" ipv4_addr_bitlen " " max_xorp_rt_port;
+               if (is_first_address4) {
+                   local_ipv4_routes = route;
+                   is_first_address4 = 0;
+               } else {
+                   local_ipv4_routes = local_ipv4_routes ", " route;
+               }
+           }
+           for (ai6 = 0; ai6 < iftree_interfaces_vifs_addresses6_max[ii,vi]; 
ai6++) {
+               addr6 = iftree_interfaces_vifs_addresses6_addr[ii,vi,ai6];
+               prefix6 = iftree_interfaces_vifs_addresses6_prefix[ii,vi,ai6];
+               #
+               # XXX: unlike the CheckIPHeader() element, the
+               # CheckIP6Header() element arguments are the list of 
+               # bad addresses instead of our addresses.
+               #
+               #check_ipv6_header = check_ipv6_header " " addr6 "/" prefix6;
+               route = addr6 "/" ipv6_addr_bitlen " " max_xorp_rt_port;
+               if (is_first_address6) {
+                   local_ipv6_routes = route;
+                   is_first_address6 = 0;
+               } else {
+                   local_ipv6_routes = local_ipv6_routes ", " route;
+               }
+           }
+       }
+    }
+    check_ipv4_header = check_ipv4_header ")";
+    check_ipv6_header = check_ipv6_header ")";
+
+    printf("\n\n");
+    printf("// Shared IPv4 input path and routing table\n");
+    printf("\n");
+    printf("    %s :: Strip(14)\n", xorp_ip4);
+    printf("   -> %s\n", check_ipv4_header);
+    printf("   -> %s :: %s(%s);\n", xorp_rt4, ipv4_lookup_element,
+          local_ipv4_routes);
+
+    if (enable_ipv6) {
+       printf("\n\n");
+       printf("// Shared IPv6 input path and routing table\n");
+       printf("\n");
+       printf("    %s :: Strip(14)\n", xorp_ip6);
+       printf("   -> %s\n", check_ipv6_header);
+       printf("   -> GetIP6Address(24)\n");    # XXX: need this in IPv6!
+       printf("   -> %s :: %s(%s)\n", xorp_rt6, ipv6_lookup_element,
+              local_ipv6_routes);
+    }
+}
+
+function generate_click_arp_responses()
+{
+    printf("\n\n");
+    printf("// ARP responses are copied to each ARPQuerier and the host.\n");
+    printf("\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;
+           xorp_nda = "_xorp_nda" port;
+           xorp_nds = "_xorp_nds" 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] 
")";
+           }
+
+           // IPv4 ARP
+           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 ")";
+
+           # IPv6 Neighbor Discovery
+           ip6_ndadvertiser = "IP6NDAdvertiser(";
+           is_begin = 1;
+           for (ai6 = 0; ai6 < iftree_interfaces_vifs_addresses6_max[ii,vi]; 
ai6++) {
+               if (is_begin)
+                   is_begin = 0;
+               else
+                   ip6_ndadvertiser = ip6_ndadvertiser ", ";
+               addr6 = iftree_interfaces_vifs_addresses6_addr[ii,vi,ai6];
+               # TODO: fix prefix length fetching!!!
+               ip6_ndadvertiser = ip6_ndadvertiser addr6 "/64 " mac;
+           }
+           ip6_ndadvertiser = ip6_ndadvertiser ")";
+
+           first_addr6 = "0::0";
+           if (iftree_interfaces_vifs_addresses6_max[ii,vi] > 0) {
+               first_addr6 = iftree_interfaces_vifs_addresses6_addr[ii,vi,0];
+           }
+           ip6_ndsolicitor = "IP6NDSolicitor(" first_addr6 ", " mac ")";
+
+           paint = "Paint(" port + 1 ")";
+           print_unknown = "Print(\"" iftree_interfaces_vifs_vifname[ii,vi] " 
unknown protocol\")";
+
+           printf("\n\n");
+           printf("// Input and output paths for %s\n",
+                  iftree_interfaces_vifs_vifname[ii,vi]);
+           printf("\n");
+           printf("    %s -> %s :: Classifier(\n",
+                  from_device,
+                  xorp_c);
+           printf("    12/0800,                // [0] IPv4 packet\n");
+           printf("    12/0806 20/0001,        // [1] ARP request\n");
+           printf("    12/0806 20/0002,        // [2] ARP reply\n");
+           printf("    12/86dd 20/3aff 54/87,  // [3] IPv6 ICMP ND 
solicitation\n");
+           printf("    12/86dd 20/3aff 54/88,  // [4] IPv6 ICMP ND 
advertisment\n");
+           printf("    12/86dd,                // [5] IPv6 packet\n");
+           printf("    -)                      // [6] Unsupported 
protocol;\n");
+           printf("    %s :: Queue(200) -> %s :: %s;\n",
+                  xorp_out,
+                  xorp_to_device,
+                  to_device);
+
+           # IPv4
+           printf("\n");
+           printf("    // IPv4\n");
+           # Plain IPv4 packets
+           printf("    %s[0] -> %s -> %s;\n",
+                  xorp_c,
+                  paint,
+                  xorp_ip4);
+           # ARP request
+           printf("    %s[1] -> %s -> %s;\n",
+                  xorp_c,
+                  arp_responder,
+                  xorp_out);
+           # ARP reply
+           printf("    %s :: %s -> %s;\n",
+                  xorp_arpq,
+                  arp_querier,
+                  xorp_out);
+           printf("    %s[2] -> %s;\n",
+                  xorp_c,
+                  xorp_arpt);
+           printf("    %s[%u] -> [1]%s;\n",
+                  xorp_arpt,
+                  port,
+                  xorp_arpq);
+
+           # IPv6
+           if (enable_ipv6) {
+               printf("\n");
+               printf("    // IPv6\n");
+               # Plain IPv6 packets
+               printf("    %s[5] -> %s -> %s;\n",
+                      xorp_c,
+                      paint,
+                      xorp_ip6);
+               # ICMP Neighbor Discovery Solicitation
+               printf("    %s[3] -> %s -> %s;\n",
+                      xorp_c,
+                      ip6_ndadvertiser,
+                      xorp_out);
+               # ICMP Neighbor Discovery Advertisment
+               printf("    %s :: %s -> %s;\n",
+                      xorp_nds,
+                      ip6_ndsolicitor,
+                      xorp_out);
+               printf("    %s[4] -> [1]%s;\n",
+                      xorp_c,
+                      xorp_nds);
+           } else {
+               printf("\n");
+               printf("    // Discard IPv6\n");
+               # Plain IPv6 packets
+               printf("    %s[5] -> Discard;\n",
+                      xorp_c);
+               # ICMP Neighbor Discovery Solicitation
+               printf("    %s[3] -> Discard;\n",
+                      xorp_c);
+               printf("    %s[4] -> Discard;\n",
+                      xorp_c);
+           }
+
+           # Unknown protocol
+           printf("\n");
+           printf("    // Unknown protocol\n");
+           printf("    %s[6] -> %s -> Discard;\n",
+                  xorp_c,
+                  print_unknown);
+
+           port++;
+       }
+    }
+}
+
+function generate_click_send_packets_to_host()
+{
+    printf("\n\n");
+    printf("// Local delivery\n");
+    # TODO: XXX: Fix the Local delivery for *BSD and/or user-level Click
+    printf("\n");
+    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 :: ToHost;\n", xorp_toh);
+    } else {
+       printf("    %s :: Discard;\n", xorp_toh);
+    }
+
+    # XXX: last port in xorp_rt{4,6} is reserved for local delivery
+    printf("\n");
+    printf("    // IPv4\n");
+    printf("    %s[%u] -> %s -> %s;\n",
+          xorp_rt4,
+          max_xorp_rt_port,
+          ether_encap4,
+          xorp_toh);
+    printf("    %s[%u] -> %s;\n",
+          xorp_arpt,
+          iftree_vifs_max,
+          xorp_toh);
+
+    if (enable_ipv6) {
+       printf("\n");
+       printf("    // IPv6\n");
+       printf("    %s[%u] -> %s -> %s;\n",
+              xorp_rt6,
+              max_xorp_rt_port,
+              ether_encap6,
+              xorp_toh);
+    }
+}
+
+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_nds = "_xorp_nds" 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\n");
+           printf("// Forwarding path for %s\n",
+                  iftree_interfaces_vifs_vifname[ii,vi]);
+           xorp_rt_port = iftree_interfaces_vifs_port[ii,vi];
+
+           printf("\n");
+           printf("    // IPv4\n");
+           printf("    %s[%u] -> DropBroadcasts\n",
+                  xorp_rt4,
+                  xorp_rt_port);
+           printf("    -> %s :: %s\n",
+                  xorp_cp,
+                  paint_tee);
+           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",
+                  xorp_arpq);
+
+           printf("    %s[1] -> ICMPError(%s, timeexceeded) -> %s;\n",
+                  xorp_dt,
+                  first_addr4,
+                  xorp_rt4);
+           printf("    %s[1] -> ICMPError(%s, unreachable, needfrag) -> %s;\n",
+                  xorp_fr,
+                  first_addr4,
+                  xorp_rt4);
+           printf("    %s[1] -> ICMPError(%s, parameterproblem) -> %s;\n",
+                  xorp_gio,
+                  first_addr4,
+                  xorp_rt4);
+           printf("    %s[1] -> ICMPError(%s, redirect, host) -> %s;\n",
+                  xorp_cp,
+                  first_addr4,
+                  xorp_rt4);
+
+           if (enable_ipv6) {
+               printf("\n");
+               printf("    // IPv6\n");
+               # TODO: Must fix this bellow!!!
+               printf("    %s[%u] -> DropBroadcasts\n",
+                      xorp_rt6,
+                      xorp_rt_port);
+               printf("    -> DecIP6HLIM\n");
+               printf("    -> [0]%s\n",
+                      xorp_nds);
+           }
+
+           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++;
+               p = iftree_interfaces_max - 1;
+               iftree_interfaces_ifname[p] = v;
+               # XXX: by default each interface is enabled
+               iftree_interfaces_enabled[p] = 1;
+               continue;
+           }
+           syntax_error("Invalid keyword");
+       }
+
+
+       if (is_level0_interfaces && (config_level == 2)) {
+           if (tokens[i] == "disable:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               p = iftree_interfaces_max - 1;
+               if (v == "true")
+                   iftree_interfaces_enabled[p] = 0;
+               else
+                   iftree_interfaces_enabled[p] = 1;
+               continue;
+           }
+
+           if (tokens[i] == "description:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               p = iftree_interfaces_max - 1;
+               while (! is_end_of_string(v)) {
+                   if (i == tokens_n)
+                       syntax_error("Missing end-of-string");
+                   i++;
+                   v = v " " tokens[i];
+               }
+               iftree_interfaces_description[p] = v;
+               continue;
+           }
+
+           if (tokens[i] == "discard:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               p = iftree_interfaces_max - 1;
+               iftree_interfaces_discard[p] = v;
+               continue;
+           }
+
+           if (tokens[i] == "unreachable:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               p = iftree_interfaces_max - 1;
+               iftree_interfaces_unreachable[p] = v;
+               continue;
+           }
+
+           if (tokens[i] == "management:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               p = iftree_interfaces_max - 1;
+               iftree_interfaces_management[p] = v;
+               continue;
+           }
+
+           if (tokens[i] == "mac:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               p = iftree_interfaces_max - 1;
+               iftree_interfaces_mac[p] = v;
+               iftree_interfaces_has_mac[p] = 1;
+               continue;
+           }
+
+           if (tokens[i] == "mtu:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               p = iftree_interfaces_max - 1;
+               iftree_interfaces_mtu[p] = v;
+               iftree_interfaces_has_mtu[p] = 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] == "disable:") {
+               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] = 0;
+               else
+                   iftree_interfaces_vifs_enabled[p,q] = 1;
+               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;
+                   # XXX: by default each address is enabled
+                   iftree_interfaces_vifs_addresses4_enabled[p,q,r] = 1;
+               }
+               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;
+                   # XXX: by default each address is enabled
+                   iftree_interfaces_vifs_addresses6_enabled[p,q,r] = 1;
+               }
+               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] == "disable:") {
+               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] = 0;
+                   else
+                       iftree_interfaces_vifs_addresses4_enabled[p,q,r] = 1;
+               }
+               if (is_ipv6_address) {
+                   r = iftree_interfaces_vifs_addresses6_max[p,q] - 1;
+                   if (v == "true")
+                       iftree_interfaces_vifs_addresses6_enabled[p,q,r] = 0;
+                   else
+                       iftree_interfaces_vifs_addresses6_enabled[p,q,r] = 1;
+               }
+               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;
+               # XXX: by default Click is enabled
+               is_click_enabled = 1;
+               continue;
+           }
+
+           # XXX: ignore the rest of the configuration
+           continue;
+       }
+
+       if (is_level0_fea && is_level0_fea_level1_click &&
+           (config_level == 2)) {
+
+           if (tokens[i] == "disable:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               if (v == "true")
+                   is_click_enabled = 0;
+               else
+                   is_click_enabled = 1;
+               continue;
+           }
+
+           if (tokens[i] == "kernel-click") {
+               is_level0_fea_level1_click_level2_kernel_click = 1;
+               is_level0_fea_level1_click_level2_user_click = 0;
+               # XXX: by default kernel-level Click is enabled
+               is_kernel_click = 1;
+               continue;
+           }
+
+           if (tokens[i] == "user-click") {
+               is_level0_fea_level1_click_level2_kernel_click = 0;
+               is_level0_fea_level1_click_level2_user_click = 1;
+               # XXX: by default user-level Click is enabled
+               is_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] == "disable:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               if (v == "true") {
+                   is_kernel_click = 0;
+               } else {
+                   is_kernel_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_user_click &&
+           (config_level == 3)) {
+           if (tokens[i] == "disable:") {
+               if (i == tokens_n)
+                   syntax_error("Missing value");
+               i++;
+               v = tokens[i];
+               if (v == "true") {
+                   is_user_click = 0;
+               } else {
+                   is_user_click = 1;
+               }
+               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) > "/dev/stderr";
+    exit(1);
+}
+
+function internal_error(message)
+{
+    is_internal_error = 1;
+    printf("Internal error (file %s): %s\n", FILENAME,
+          message) > "/dev/stderr";
+    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_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:


Property changes on: trunk/xorp/fea/fea_click_config_generator
___________________________________________________________________
Added: svn:executable
   + *


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

_______________________________________________
Xorp-cvs mailing list
[email protected]
http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-cvs

Reply via email to