#!/pkg/bin/tclsh
#
# tcl script : rpl_test.tcl
#
#  Jean-Michel Esnault, 2007
#
#  Copyright (c) 2007 by cisco Systems, Inc.
#  All rights reserved.
#

if [catch {
    source /pkg/bin/rpl_common.lib
    source /pkg/bin/show_tech_common.lib
    namespace import ::xr::show_tech::*
    namespace import ::xr::rpl::*
} err] {
    puts "Could not source support library."
    puts "$err"
    exit 1
}


# run from user's home directory /disk0/usr
cd       

set ::usage "
usage: [file tail $::argv0] -i input_filename -p policy_name 
         \[-o | --output_filename  output_filename\]
         \[-a | --attach-point attatch_point\]
         \[--src-ip source_addr\]
         \[--dst-ip dest_addr\]
         \[--src-as source_as\]
         \[--dst-as dest_as\]
         \[-u | --update-number number\]
         \[-b | --binary\]
         \[--bin2xml\]
         \?

defaults:

    src-ip      : 192.168.0.1
    dst-ip      : 192.168.0.2
    src-as      : 100
    dst-as      : 100
    attachpoint : neighbor-in
    output      : stdout
 
examples:

   test -p foo -i test1.xml
   test -p foo -i test1.xml -o test1.result.xml
   test -p foo --input-filename test1.xml --policy foo --attach-point neighbor-out 

"

proc parseArgs {__argv} {

    if ![string length [string trim $__argv]] { puts $::usage ; exit }

    set ::argv $__argv 
    set ::debug 0
    set ::bin 0

    parse_argv {
        switch -exact -- $1  {
            -i -  --input-filename   { set ::arg_arr(finput)  $2  ; shift ::argv } 
            -o -  --output-filename  { set ::arg_arr(foutput) $2  ; shift ::argv }
            -p -  --policy           { set ::arg_arr(policy)  $2 ; shift ::argv }
            -u - --update-number     { set ::arg_arr(route_number) $2 ; shift ::argv }
            -a - --attach-point      { set ::arg_arr(attach_point) $2; shift ::argv }
            --src-ip                 { set ::arg_arr(src_ip) $2; shift ::argv }
            --src-as                 { set ::arg_arr(src_as) $2; shift ::argv } 
            --dst-ip                 { set ::arg_arr(dst_ip) $2; shift ::argv }
            --dst-as                 { set ::arg_arr(dst_as) $2; shift ::argv }
            --debug                  { set ::debug  1 }
            --bin                    { set ::bin    1 }          
            --bin2xml                { set ::bin    2 }
            -4                       { set ::arg_arr(as) -4   }
            -2                       { set ::arg_arr(as) -2   }
            ?                        { puts $::usage ; exit }
            default { 
                return -code error "error parsing command line: bogus '$1'"
            }
        }
    }   
} 

proc validateArgs argv {
    set ip_regex \
            {^\s*(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\s*$}
    upvar 1 $argv _argv
    foreach arg [array names _argv] {
        set $arg $::arg_arr($arg)
    }

    ;# exit if input file not found or not on command line.
    if { ![info exist finput] || ![file exist $finput] } {
        return -code error "file not found"
    }
    set ::input "$finput"

    ;# set outpout to stdout or filename.
    set ::output ""
    set ::stdout 1 
    if [info exist foutput] {
        set ::stdout 0
        set ::output "-o $foutput" 
    }


    ;# exit if we don't have a policy name
    if { ![info exist policy] || ![string compare $policy {} ] } {
        return -code error "no route policy"
    } 
    set ::policy "$policy"

    ;# default to neighbor-in attachpoint if not specified.
    if [info exist attach_point] {
        switch -exact -- $attach_point {
            in -
            neighbor-in {
                set ::location "neighbor-in"
            }
            out -
            neighbor-out {
                set ::location "neighbor-out"
            }
            default {
                return -code error error "unknown attachpoint"
            }
        }
    } else {
        set ::location "neighbor-in"
    }

    ;# 
    set ::update_number ""
    if { [info exist route_number] && [string is integer $route_number] } {
        set ::update_number "-u $route_number"
    }

    ;# overwrite BGP peering info.
    set ::src_ip "192.168.0.1"
    set ::src_as "100"
    set ::dst_ip "192.168.0.2"
    set ::dst_as "100"
    if  [info exist src_ip] {
        if ![regexp $ip_regex $src_ip]  { 
            return -code error "bogus ip address"
        }
        set ::src_ip $src_ip
    }
    if  [info exist dst_ip] {
        if ![regexp $ip_regex $dst_ip]  { 
            return -code error "bogus ip address"
        }
        set ::dst_ip $dst_ip
    }
    if  [info exist src_as]  { set ::src_as $src_as }
    if  [info exist dst_as]  { set ::dst_as $dst_as }

    ;# 2 bytes or 4 bytes as.
    set ::as ""
    if [info exist as] { set ::as $as }
}



proc BuildExecCommand argv {
    upvar 1 $argv _argv
    switch $::bin {
        1 {
            lappend lcmd "bgp_policy_test -p $::policy -a $::location  -i $::input $::output"
            
        }
        2 {
            ;#  -bin2xml  w/ no --output
            lappend lcmd "bgp_policy_test -p $::policy -a $::location -i $::input"
            lappend lcmd  "bgp_policy_btoa $::output"
        }
        default {
            set cmd  "pr_test_xml2bin $::update_number -i $::input "
            append cmd "$::as $::src_ip $::src_as $::dst_ip $::dst_as"    
            lappend lcmd  $cmd
            lappend lcmd  "bgp_policy_test -p $::policy -a $::location"
            lappend lcmd  "bgp_policy_btoa $::output"
        }
    }
    return $lcmd
}



proc Exec {argv} {
    set ::cl 79
    if [catch { 
        parseArgs  $argv
        validateArgs ::arg_arr
    } err] {
        puts "$err:\n  in '$argv'"
        return
    }    
    set cmds [BuildExecCommand ::arg_arr]
    if {[info exist ::debug] && $::debug} {
        puts [join $cmds " | "]
    } else {
        if { $::stdout  && $::bin == 0 } {
            puts [h1 "Test route-policy $::policy at $::location attachpoint"]
            puts [h2 "Policy $::policy"]
            puts [show rpl route-policy $::policy]
            if ![catch { open $::input } fh] {
                puts [h2 "Input Routes ($::input)"]
                puts [read $fh]
                close $fh
            }
            puts [h1 "Results:"]
            puts [eval exec [join $cmds " | "]]
            puts [h1 "End RPL Test Policy"]
        } else {
            puts -nonewline "Test route-policy $::policy at $::location attachpoint ..."
            if [catch {
                if $::stdout {
                    if { $::bin == 2 } {
                        puts [eval exec [join $cmds " | "]]
                    } else {
                        eval exec [join $cmds " | "] > $::input.out
                        puts " redirected to $::input.out"
                    }
                } else {
                    eval exec [join $cmds " | "]
                }
             } err] {
                puts "Error: $err"
            } else {
                puts " Done!"
            }
        } 
    }
}


if [catch { Exec  $argv } err] {
    puts $err
}


exit

Unit Testcases:

Exec "--input-filename test_community.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in -p foo"

Exec "-4 --input-filename test_community.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in "

Exec "-2 --input-filename test_community.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--policy foo"

Exec "-2 -i test_community.xml -o test_community_result.xml -u 1 -a  neighbor-in -p foo "

Exec "--input-filename test_community.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--src-ip 1110.0.0.1 --src-as 111"

Exec "--input-filename test_community.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--dst-ip 10.0.0.1 --dst-as 111 --src-ip 20.0.0.1  --src-as 222"

Exec "--input-filename test_community.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--src-ip 192.168.0.1"

Exec "--input-filename bogus.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--dst-ip 10.0.0.1 --dst-as 111 -o results.xml"

Exec "--input-filename test_nlri.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--dst-ip 10.0.0.1 --dst-as 111 -o results.xml"

Exec "--input-filename test_nlri.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--dst-ip 10.0.0.1 --dst-as 111 -o results.xml"

Exec "--input-filename test_nlri.xml --output-filename \
test_community_result.xml --route-number 1 --attach-point  neighbor-in \
--dst-ip 10.0.0.1 --dst-as 111 -o results.xml" 

Exec "--input-filename test_nlri.xml --output-filename \
test_community_result.xml --route-number abc  --dst-ip 355.256.0.256 --dst-as 111 -o results.xml"
                                     

Exec " ? "
